exult-1.2/0000777000175000001440000000000010062225335006254 5exult-1.2/FAQ0000644000175000001440000011227610060711771006535 Exult F.A.Q. (frequently asked questions) last changed: 23 May 2004(GMT The latest version of this document can be found at http://exult.sourceforge.net/faq.php 0. Changes to the FAQ 0.1. - 23 May 2004 0.2. - 27 January 2004 0.3. - 12 December 2003 1. Introduction 1.1. Exult Version 1.2. Why is it called Exult - what is the meaning of this name? 1.3. Is Exult free ? 1.4. Do you accept donations? 1.5. Does Origin support Exult? 1.6. Will Exult support other Ultimas? 1.7. But isn't Pentagram some kind of Exult for U8? 1.8. Will there be a multiplayer Exult? 1.9. Where do I find Exult? 1.10. What is a snapshot? Are these screenshots or what? 1.11. How do I compile a source code snapshot for my OS? 1.12. What is the latest version of Exult? 1.13. On what platform does Exult run? 2. Exult and Ultima 7 2.1. Do I need Ultima 7? 2.2. Does Exult work on all versions of the game? 2.3. Can you play through U7 yet? 2.4. How about Serpent Isle? 2.5. Do the Add-ons work? 2.6. Do save games from the original work in Exult? 2.7. Do Exult savegames work on all Operating Systems? 2.8. Where do I find Ultima 7 on the net to download? 3. Miscellaneous 3.1. Where do I find a walkthrough? 3.2. Where do I find the configuration file? 3.3. Why can't I move my party with the arrow keys? 3.4. Do the carriages, ships and the magic carpet work? 3.5. So why can't I sail a ship in BG? 3.6. Will you implement the extended intro for SI? 3.7. Why is the party formation different? 3.8. What should I do when Exult keeps crashing when I try to save? 3.9. Why does the game run so choppy? 3.10. Why can't I hear the Sound Effects? 3.11. Why do I hear strange, noisy effects in Linux? 3.12. Why is the music so much louder/softer than the sfx/speech? 3.13. Why does my monitor stay black when I try to run Exult? 3.14. What are the improvements in Exult over the original Ultima 7? 3.15. Are there issues with the SI style paperdoll in BG? 3.16. How do I disable all improvements? 3.17. I heard that Exult is meant to be a game engine. Can I make my own game with Exult? 4. Bugs, known issues and not yet implemented features 4.1. Bugs 4.2. How do I submit a proper bug report? 4.3. Broken by Design 4.4. Known Issues 4.5. Known Compile Issues 4.6. Not yet implemented 5. Gameplay FAQ 5.1. Why is there a gameplay FAQ? 5.2. Why can't I cast mark/recall on the Virtue Runes (BG)? 5.3. Why can't I get the sacrifice in Skara Brae to work (BG)? 5.4. Why can't I talk to the mayor of Skara Brae (BG)? 5.5. Where did my gem of the Demon vanish to (BG-FoV)? 5.6. Where is the pikeman that lets you train in Monitor (SI)? 5.7. How do I get the Mandrake Roots for Fedabiblio (SI)? 5.8. Why can't I summon the Great Hierophant (SI)? 5.9. Why won't Xenka speak about sacrifice (SI) 5.10. An important note about the Serpent Staff (SI) 5.11. How to break the plot by doubleclicking some pillars (SI-SS) 6. Questions and Answers 6.1. How can I get answers concerning Ultima 7/Exult? 6.2. How do I contact the author of this FAQ? 7. Links and Thanks 7.1. Important Links 7.2. Thanks -------------------------------------------------------------------------------- 0. Changes to the FAQ 0.1. - 23 May 2004 * 1.12. What is the latest version of Exult? 1.2 now. * 1.4. Do you accept donations? No we don't but SF would be happy. * 1.12. What is the latest version of Exult? 1.2 now. * 3.2. Where do I find the configuration file? if you really can't find it. 0.2. - 27 January 2004 * 1.12. What is the latest version of Exult? 1.1.9rc1 now. * 4.4. Known Issues Items descriptions in SI-only work now. * 5.9. Why won't Xenka speak about sacrifice (SI) added. * 5.10. An important note about the Serpent Staff (SI) Willem fixed this. 0.3. - 12 December 2003 * 5.3. Why can't I get the sacrifice in Skara Brae to work (BG)? Stuart told me another workaround. * 6.1. How can I get answers concerning Ultima 7/Exult? still used the old invalid address for irc and #exultlog (thanks Lars). -------------------------------------------------------------------------------- 1. Introduction 1.1. Exult Version This documentation is for the 1.2 version of Exult. If you have another Exult version, its documentation can be found where you installed the release. 1.2. Why is it called Exult - what is the meaning of this name? Jeff wrote on the Boards: I originally wrote it [Exult] solely for X-windows, so that's where the 'X' comes from. The "ult", of course, comes from Ultima. It was only about 6 months ago [02/29/2000] that I replaced the X code with SDL, which is multiplatform. Then Arthuris ported it to Win32 (and to BeOS). He had also ported the earlier version, but it was much harder to maintain that way. Ibrahim Holtzmann: I'd like to point out that "exult" is also an English verb that means "to rejoice, to exhibit great happiness". 1.3. Is Exult free ? Exult is more than free: it's Free (notice the caps). Exult is released under the GNU GPL (General Public License). This means that the source code for Exult is freely available and you can do whatever you want with it. However, if you make modifications to any of Exults components and publicly redistribute your work you are required to make the source freely available in turn. Obviously the Exult team would be very grateful if any modifications you make are contributed back to the main code, so that everyone can benefit from them. If you want to work on Exult just send an e-mail to the team. More information on the GNU GPL at http://www.gnu.org/copyleft/gpl.html. 1.4. Do you accept donations? No the Exult team will not accept donations. For us there are greater legal matters involved, which none of us particularly want to explore. We do not want to risk the wrath of EA for directly profitting off xult. If you want to donate to anyone, donate to Sourceforge. We wouldn't be here if it weren't for them. 1.5. Does Origin support Exult? First of all, Origin has been owned by EA for a long time now and from recent developments it seems that Origin only exists now to maintain Ultima Online. Furthermore, Origin and/or people that worked for Origin claim that the source code for Ultima 7 (BG/SI) has been lost for some time. So there is no chance for the Exult team to have a look at the actual code. Also the team tried to contact some people from Origin earlier but got no positive or negative response on the Exult project. So far it seems that both Origin and EA have decided to ignore Exult. On the other hand former Origin employees contacted the team and congratulated the team on their effort. Most noticeable are Lord British himself and Ken Demarest (Programming Manager of Ultima 7)(hint:spell his name backwards). 1.6. Will Exult support other Ultimas? Exult supports only Ultima 7 (BG/SI and the add-ons). It will never support any other Ultima nor do members of the team plan to develop something similar. The reasons for this are that no other Ultima is similar to Ultima 7 in the internal workings and also the team used to be quite sick of reverse engineering a game already. 1.7. But isn't Pentagram some kind of Exult for U8? Pentagram is a pet project by some members of the Exult team (currently mostly Willem, Colourless, Fingolfin and Darke). It is a map and shapes viewer and nothing more (although the team does indeed invest some time to disassemble the Usecode of U8). It isn't meant to be something similar to Exult. It is rather a clever plan to stir up interest in other coders to carry this basic work further. Any developer is welcome to take a look and contact us. Seriously Pentagram is slowly progressing and you can find snapshots of the code and Win32 binaries for it on the Pentagramsnapshots page. On the official Pentagram homepage at http://pentagram.sourceforge.net/ you might find more information on this project in the future. For now you can find some nice screenshots of the map viewer in action. 1.8. Will there be a multiplayer Exult? No. Jeff on the Forum: The question is 'why?'. I continue working on Exult, in large part, because nobody makes games like Ultima7 anymore. While I think a multiplayer game would be technically interesting, I don't see the need. There are lots of them already, and many experienced people working on new ones. Note however that Exult is open source. If you want a multiplayer U7 no one holds you back to code it in. 1.9. Where do I find Exult? The latest official version is found on http://exult.sourceforge.net/ Daily snapshots (by Travis Howell) of the Win32 binary and of the CVS source tree can be found at http://exult.sourceforge.net/download.php. A BeOS binary snapshot can be found at http://digilander.iol.it/burton666/exult-beos.zip. Jack Burton provides this weekly or whenever it compiles for him. Thanks! There is also a version available for AmigaOS/MorphOS at http://www.muenster.de/~tomjoad/exult.html. Please see 1.13. for some more information on this port. 1.10. What is a snapshot? Are these screenshots or what? Bugs and not yet implemented features in Exult get fixed almost daily in the code. A release is very time consuming that's why there are so few. The snapshot is the newest source code of the program. It is updated almost daily, sometimes twice a day. There is information on how to build your own binary in the source but there is also the newest pre-compiled Windows executable. If you there is no new one this means that either there were no changes to the code or the source failed to compile. Also this FAQ mainly addresses the snapshots as people use them and ask question. And all the new features and improvements are found in those! 1.11. How do I compile a source code snapshot for my OS? The source code snapshots contain a file called "README.OS" (like Readme.win32, Readme.MacOS) that explains everything. 1.12. What is the latest version of Exult? The current official release is V1.2 See also 1.9. to learn where to get the latest version. To find out which version you are running, press 'v' while in game. 1.13. On what platform does Exult run? Exult should be able to be compiled (with minor modifications) on any platform that SDL supports. Right now the source can be compiled in Linux/i386, Linux/Alpha, MacOS (requires at least MacOS 8.5 or higher), OSX, OpenBSD, FreeBSD, Solaris, BeOS and Win32 (Windows 9x/ME/NT4/2000/XP). Ruediger Hanke's ported Exult to MorphOS and AmigaOS. You can get this version at http://www.muenster.de/~tomjoad/exult.html. Recently Artaxerxes started working on a port for Zaurus, a Linux/ARM based PDA. It is already fully playable (Artaxerxes played through SI). Pictures of the Zaurus running SI can be found at http://exult.sourceforge.net/images/screenshots/zaurus/ and an IPK package at http://exult.sourceforge.net/download.php. -------------------------------------------------------------------------------- 2. Exult and Ultima 7 2.1. Do I need Ultima 7? Yes. Exult won't work without the original files. 2.2. Does Exult work on all versions of the game? It seems to run most of the available versions of the game. The most common ones nowadays with the included Add-ons (Forge of Virtue and Silver Seed) runs for sure. However there are reported problems with the localized versions of the game (French, German and Spanish). Conversation threads don't seem to skip to the next line in the proper places and therefore are unreadable in some cases. SI was published in English and Spanish (as we recently discovered to our surprise) but we seem to have fixed the main problem with the Spanish version. V0.91 Alpha2 adds fixes for the French version, which should work now. If you are running a Spanish or German version Black Gate and you notice problems please contact us. 2.3. Can you play through U7 yet? You can play through the Black Gate/Forge of Virtue without cheating and plot holes. And since Beta1 the same is true for Serpent Isle/Silver Seed. 2.4. How about Serpent Isle? Serpent Isle is now playable without cheating and plot holes. Two members of the team have already finished the game with Exult. Old quotes on this topic from the time when SI wasn't playable at all in Exult. Colourless: I can't say much about the what will happen except that a completely working Serpent Isle will be an annoying task to complete. It is close to BG in some ways, but very different in others. Jeff: My feelings about SI are the same as Colourless, who has done all the work so far on it. I'd much prefer to add enhancements to BG (which would apply to SI as well), and perhaps write a new RPG. Now, if EA would provide us with information about SI's internals, that would change things. And also, since Exult is open-source, it would be fine if anyone wants to volunteer to work on SI. 2.5. Do the Add-ons work? "Forge of Virtue" (Add-on to Black Gate) and the "The Silver Seed" (Add-on to Serpent Isle) are bug-free now. 2.6. Do save games from the original work in Exult? Save games that were made with the original Ultima 7 or U7Run don't work with Exult. You have to start a new game when you begin playing with Exult. Sorry! 2.7. Do Exult savegames work on all Operating Systems? Exult savegames are compatible on all supported Operating Systems. For example a saved game of the Mac port of Exult works on Windows 98 as well. However it is not advisable to use savegames of games started with the 1.1.x snapshot of Exult with the 1.0 release. 2.8. Where do I find Ultima 7 on the net to download? Don't! You may be able to find it on the net but it would be pirating the game and the Exult team doesn't support pirates. Look for the Ultima Collection in stores or on EBay (http://www.ebay.com). Don't ask the team for copies. Don't ask on the forum for copies, your post and the entire thread will be deleted. And please don't ask for the answers to the copyright questions. -------------------------------------------------------------------------------- 3. Miscellaneous 3.1. Where do I find a walkthrough? If you need help with the game itself, like walkthroughs, hints, location of NPCs items take a look at the following sites: * http://members.aol.com/UltimaWrld/ultima07.html The Ultima 7 section of Excalibur's World of Ultima site. * http://www.ultimainfo.net/Codex/Ultima7.htm Paulon Dragons selection of notes and information on Ultima 7. * http://www.ultimainfo.net/Codex/FAQ2.htm#U7 The Ultima 7 section of Paulon Dragons Ultima games FAQ. * http://www.ultimainfo.net/FAQ/ultimafaqs.htm#11 The U7 section of the more detailed Ultima Gameplay FAQ. 3.2. Where do I find the configuration file? You can find exult.cfg in specific directories: * On Windows systems the file can be found in the same folder you installed Exult to * On UNIX systems you can expect to find it in $HOME/.exult.cfg (keep in mind that the dot before exult.cfg means that it is hidden from normal view). * In Mac OS X it is ~/Library/Preferences/exult.cfg 3.3. Why can't I move my party with the arrow keys? Nadir implemented keyboard walking in the 1.1 (unstable) branch of our source. For details see ReadMe.txt. 3.4. Do the carriages, ships and the magic carpet work? Yes. The sail of ships look odd sometimes but otherwise these means of transportation work quite well. 3.5. So why can't I sail a ship in BG? To sail a ship in BG you naturally need to have the deed to this ship in your party. Then double-click on the sail of the ship and your party moves aboard it and sits down. Once they are all seated, double-click the gangplank to close it. Now double-click on the sail once more to have it unfold. You should be able to move the ship then. 3.6. Will you implement the extended intro for SI? The extended intro for Serpent Isle can be found at http://www.io.com/~dloubet/. At this moment we don't even think about implementing this extended intro. Why not? It sure would be nice to use it. But you may have noticed some effects missing from the intro. You may have noticed that there is no sound. You may have noticed that there is neither speech nor subtitles. All that would have to be addressed and add to that the longer running time and that you have to synchronize the music with it. Then what about the size of it? You would need to compress it and make sure all our supported platforms make use of it. Everyone volunteering to do it is welcome to. 3.7. Why is the party formation different? In Exult the party (the Avatar and his companions) move quite differently than they do in the original. The problem is that this was controlled by the original executable. Changing the formation now is not as easy as it sounds as the party formation has effects on other game internals. Changing it to be more like the original may force us to replay the whole game to make sure we didn't introduce new bugs. Recently Jeff added an optional formation that behaves way more like in the original game. The default is still the "loose" Exult formation. See ReadMe.txt. Jeff: It's not a bug, it's a feature! I like it that way. Everyone is sensitive to different things, and I always though the formation-walking in the original U7 looked really stupid. Eventually, someone may add the original type of walking to Exult, probably as an option. 3.8. What should I do when Exult keeps crashing when I try to save? This is not normal behavior for Exult. Normally when you restart and "Journey Onward" Exult will actually restore to the point you saved. Please do not play further at this point. You should restore to an earlier save game, no matter how much game time you loose. Your game must have gotten corrupted and when you play on with it you will most likely experience even more serious problems. Please also avoid saving when a scripted sequence is running. Whenever you can't control the Avatar on your own a scripted scene is running and saving at this time will break the game on reloading. 3.9. Why does the game run so choppy? Well, every Ultima required a fast computer. Even though Exult is just an engine that runs the ancient Ultima 7 it still requires a fast computer. Seriously, if the game runs choppy for you, try the speed setting in the Game Options menu and if that doesn't help also play with the original resolution (320x200), try a different scaler or disable scaling altogether. 3.10. Why can't I hear the Sound Effects? Please read the Audio section of our ReadMe.txt. 3.11. Why do I hear strange, noisy effects in Linux? This is due to a bug with OSS. We advice installing ALSA. Please read ReadMe.txt for a little more extensive explanation. 3.12. Why is the music so much louder/softer than the sfx/speech? Music is played via midi but the sfx (sound effects) and speech are played via wave. Midi and Wave volume are set up separately in the settings of your Operating System and not by Exult. 3.13. Why does my monitor stay black when I try to run Exult? The most common reason for this is that you try to run Exult full screen in a resolution that isn't supported by either your monitor or your graphics card. Edit your exult.cfg (see ReadMe.txt) to disable full screen. If Exult now runs fine in a window you have to select a different resolution (also editable in exult.cfg) to run it full screen. If it still doesn't run contact us. 3.14. What are the improvements in Exult over the original Ultima 7? * Many more keyboard shortcuts than the original had. Including in BG the 'k' key that checks if you have the right key for a lock in your inventory. The list of keys can be found in the Documentation. * A new worked over Game Options menu. This menu is explained in detail in the Documentation and many of the following improvements and Video/Audio options can be accessed via this menu. Open this Game Options Menu by pressing 'Esc' in the game. * SI style paperdoll (inventory screen) in BG. Very impressive. For this you need to have Serpent Isle installed on your hard drive and you must set the path to it in exult.cfg (see the Documentation) and activate it in the Gameplay Options . This new inventory screen acts sometimes a little buggy, so if an item seems to have disappeared disable the paperdolls in the Gameplay Options. * A beautiful new save game box. This allows you much more save games than the original (you should run out of disc space before you run out of save game slots), shows a screenshot of the location you saved at, the members of your party, your stats, game time and the date you actually saved. The save game box is opened either via the game menu or the 's' key. * Face status bars at the bottom of the screen that show your health (and that of your party members) as well as your mana. Double-clicking on the face opens the inventory and double-clicking on the bars shows the status screen. * Middle mouse button support. In the normal game, the middle mouse button activates the target-function (which could also be accomplished by pressing 't'). for modal gumps, the middle mouse acts as 'return', the right button as 'escape', so you can now for example accept the default slider value by just pressing the middle button. The escape function is also available during most other actions like selecting a target or conversations. * Wheel mouse support. If you have a wheel mouse some features are auto-enabled in Exult. In slider gumps (e.g. how much gold you want to drop), scrolling the mouse up/down, moves the slider either left or right. Holding down 'Alt' while using the wheel scrolls 10 steps. The save game menu scrolls one line, while pressing 'Alt' it scrolls pages. You can also scroll the map of the game up or down and while pressing 'Alt' you scroll left or right. * Fast Mouse which makes the mouse cursor move faster in full screen mode. * Multiracial Avatar in BG. As with the paperdoll support you need to have SI installed and the path set in exult.cfg. * Higher resolutions than the original. You can set the resolution as high as your computer supports. But there are some issues with it and it is considered cheating. * Compressed save games. Since Beta1 Exult compresses save games by default as zip files. They are still labeled *.sav and have the save game name in the zip comment. 3.15. Are there issues with the SI style paperdoll in BG? There are some issues. The paperdoll in BG is still limited to the slots it had originally. That means: * You can either equip a pair of gauntlets or one/two rings. * The 'shield behind back', 'weapon behind back' and 'belt' slots are one and the same in BG. (So if you have a weapon on your back, you can't use your belt slot) * If an item seems to have disappeared disable the paperdolls in the Game Options, retrieve the item and enable the paperdolls again. Sparks paperdoll looks very odd (Spark on steroids) as there is no paperdoll for kids in SI and we have to use the adult paperdoll. Unless someone draws heaps of art we can't do anything. 3.16. How do I disable all improvements? To get an Ultima 7 that looks and behaves as close to the original as possible there are several things to do (though I wonder why you'd want to do that): * make custom key bindings files (see Documentation) in which you disable all the keys that were not in the original for Black Gate and Serpents Isle. Since the Alpha 4 release you have to assign 's' to old_file_gump to enable the old save game menu (the line in your custom key bindings file should look like: S old_file_gump) * Edit the exult.cfg file to point to those custom keys. * Disable SI-style paperdolls for BG in exult.cfg (see the documentation for that). * Alternatively click on the disk icon and disable the paperdolls in the Gameplay Options. * Edit the exult.cfg to use the resolution of 320x200, to run in full screen and disable scalers. * The disc icon in the Avatar paperdoll opens the new game menu. As of now this cannot be altered. Sorry! 3.17. I heard that Exult is meant to be a game engine. Can I make my own game with Exult? Work has begun on "Exult Studio" which is aimed to be an editor for all kinds of files that are used by Ultima 7. As of now there is already a Gimp plug-in to edit shapes. For much more information "Exult Studio" see exult_studio.txt. Jeff: As for the future, my main plan is to add editing capabilities, with the long-range goal of writing an original RPG. -------------------------------------------------------------------------------- 4. Bugs, known issues and not yet implemented features 4.1. Bugs To see a list of open bugs and bug reports go to http://sourceforge.net/bugs/?group_id=2335 4.2. How do I submit a proper bug report? 1. Read the Documentation and this FAQ to see if that is not already covered and you have all set up correctly. 2. Before you report a bug to the bug tracker please try the latest snapshot. If the bug still occurs make sure that no one else already reported the bug (in the bug tracker). 3. If you are not a SourceForge member please include your e-mail address. This is important so we can get back to you. If you are a SourceForge member please log in before submitting a bug. If you are a member of SourceForge you will also get notified of follow ups on your bug automatically by E-mail. 4. Make sense in the topic! For example, if the problem is with Rowenna in Skara Brae don't just choose "Skara Brae" in the topic. "BG: Rowenna crashes game" makes more sense. Sadly the space for the topics is limited. Explain the topic in "Detailed Description". 5. Include information on what version of Exult you are using. You should have used the latest snapshot but please tell us the date of the snapshot. 6. State which Operating System you use (Windows 9X, Linux, ...). 7. Please include a save game (use common sense if it is really needed). You will find those in the game directories you put in the exult.cfg. They are called exult**bg.sav (** is a number) for BG and exult**si.sav for SI. You can look up the filename in the save game dialog as well (to the right, above the party members). As some parts of the game may require you to complete other quests or stuff before you get to the bug you want to report it's much easier for the team to look at the problem (speeds the process up a bit as they are much more likely you take a look at the problem this way). You need to check the box saying "Check to upload and Attach file".. See this screenshot for an example: http://exult.sourceforge.net/images/sfbug.png 8. One bug per subject please. Note for attaching save games SourceForge requires users to be registered. Therefore we strongly advice users to register with SF. Any bug report that requires a save game will most likely be tagged invalid if we don't receive a save game after we requested it. You can also use our forum to report bugs. But if you do please follow the guidelines mentioned above (you can't include a save game of course). Though be aware that bugs submitted to the bug tracker are more likely to get attention than bugs submitted to the forum. So if you want to have a bug fixed follow these steps! 4.3. Broken by Design Exult often behaves and works differently than the original Ultima 7. These behaviors are sometimes features that just differ from the way the original worked. Some are bugs that the development team consider to have almost no detrimental effect to the enjoyment/running of the game, but would require a large amount of time and effort to fix. Please don't bother the team about those as some of these will be fixed in the future, others will only be fixed when someone who thinks it should be done differently sits down and codes it. The following are such 'features' of Exult: * Birds and animals open doors and such, like the human and sentient creatures of Britannia do. * Party members don't walk lockstep with the Avatar like they do in BG/SI. Please see 3.7. Why is the party formation different?. * The way the Avatar and the companions walk. Is it 2 frames or 3 frames? This has been changed a lot as this was disputed almost every four weeks. Finally it works like the original and the Avatar uses two frames and the companions use three frames. * Combat works differently. We don't have any hard data or formulae that tell us how combat worked in BG/SI, so Dr.Code put something together. If you have any information you've worked out related to this, please tell either the forum or the exult-general mailing list. Recently Jeff added options to change combat somewhat. See the ReadMe.txt. * Negative health and unconsciousness. Yes, it may look weird to have people walking around with negative health, but that's the way it currently works. * Some music loops endlessly in Exult. This is actually a correction of a bug in the original. We respects the midi looping flag as set by U7's original data files but the original didn't. Users who prefer the original (broken) are able to choose so in the Game menu. 4.4. Known Issues * There might be a bug when you have any of the games installed in a path with spaces in it (see ReadMe.txt). * Stealing and killing innocent NPCs doesn't work yet like it does in the original * Movement is sometimes jerky or slow. * We don't know what all the data in 'weapons.dat' and 'ammo.dat' means, so hit points and damage don't work as well as in the original game. * If you run a resolution higher than the original (320x200) some NPCs that are further away from the Avatar may seem to disappear and reappear when you get away or closer to them. * With scalers enabled you might encounter slow downs of the game. * The speech in the intro is out of sync with the lips animation. But now it matches the speed of the text. * There are reported problems with digital sound effects or speech when using Vortex series sound cards (like the Diamond MX 300) under Win9x/ME. Exult is triggering a bug in the drivers. * There is also a problem involving Win9x/ME, C-Media soundcard chipsets and MIDI music. We suggest you first upgrade your drivers to the newest ones. Get them at http://www.cmedia.com.tw/. If that doesn't help, please contact us. * Nvidia 40.x reference drivers have issues with all SDL based programs. Use either a later or earlier version of the Nvidia reference drivers. Possible workaround for the above mentioned audio issues: We added a config file option for Windows "config/audio/force_waveout" that when set to "yes" will force SDL to use waveout rather than attempting to use DirectSound. Using this option may fix problems some people have with sound in Exult under Windows. Additionally it seems to fix the popping sound when starting Exult in Win9x/ME/2k. This setting is now the default setting so downloading the latest snapshot is the only thing you need to do. 4.5. Known Compile Issues * There is a bug/incompatibility with the flex bundled Linux distributions (RH7.0, for example) that breaks compilation. Upgrading to a more recent version of flex should fix it. * After compiling yourself remember to copy the exult*.flx files from the data dir in the source to the Exult data dir you chose in exult.cfg. This applies only if you don't use "make install" 4.6. Not yet implemented * Stealing, killing innocent NPCs doesn't work yet correctly -------------------------------------------------------------------------------- 5. Gameplay FAQ 5.1. Why is there a gameplay FAQ? Although you can find many useful gameplay FAQs on the internet we do get asked some questions quite frequently as people think these are bugs with Exult. Note that this section contains text that may spoil your game. Caution is advised. 5.2. Why can't I cast mark/recall on the Virtue Runes (BG)? You never could do this in the original as well. You have to use the Virtue Stones that you find in the same building as the runes. 5.3. Why can't I get the sacrifice in Skara Brae to work (BG)? "I'm trying to get Forsythe in Skara Brae to sacrifice himself to destroy the well of souls. But I can't seem to get Rowenna or Trent to talk to me about sacrifice." The solution to this is that Rowenna and Trent are standing too far apart. When you reunited the pair you initiated the conversation with Trent from too far away (this happens when you run at a higher resolution than the original one). Now you can either reload a game from before you reunited them or you have to hackmove Rowenna closer to Trent. After that the two will talk to you about sacrifice. Stuart Hillman told me of another way around this bug: Stand next to Trent when talking to Rowenna and next to her when talking to Trent. 5.4. Why can't I talk to the mayor of Skara Brae (BG)? You might be talking to "The Other Forsythe"(TM). There's a ghost in the Skara Brae town hall that looks like Forsythe, but isn't. This was fixed in more recent versions of Exult but with games started with earlier versions this bug is still present. You need to start a new game of Exult to fix this. But this bug poses no problem, so if you don't want to start a new game, just ignore that clone and search for the real Forsythe. 5.5. Where did my gem of the Demon vanish to (BG-FoV)? For forging the black sword you need to bind the demon to the gem you got from that invincible dragon you met in the test of courage. Some people mistake that little dark-blue gem with the glowing gem you received from Lord British. If you use the glowing gem on the isle of fire it just vanishes with a shattering sound. 5.6. Where is the pikeman that lets you train in Monitor (SI)? The pikeman that lets you enter the list field in Monitor sometimes disappears due to a bug in the game (even the original). This bug occurs when you enter the banquet scene of Monitor. To avoid this bug, we recommend, that you approach the banquet hall from the right and/or double-click the entrance door to the hall when the party is standing very close to it. 5.7. How do I get the Mandrake Roots for Fedabiblio (SI)? Fedabiblio in Moonshade sends you on a quest to find fresh Mandrake Roots. You get to Monk Island but can't find the any fresh roots. The problem is that fresh roots only appear depending on the tide. One of the nameless monks of the island tells you to ask him when the tide is right. Keep coming back to him and when he tells you the tide is right walk to the northern shore of the island to find fresh roots. 5.8. Why can't I summon the Great Hierophant (SI)? If you follow some walkthrough you might find that your summoning of the Great Hierophant doesn't work. This is a problem with the walkthrough. You need to have a personal item of the Great Hierophant in your inventory, namely the Serpent Staff. If possible don't just play following the walkthrough, but go out and explore Serpent Isle. It's hard to imagine someone could miss the cave to the east of Monitor... 5.9. Why won't Xenka speak about sacrifice (SI) For Xenka to speak about sacrifice some parts of the game need to have been played correctly. The sacrifice conversation option will only turn up if: * you have returned the amulet to the Gwani AND * you have spoken with the Chaos Hierophant AND * you have picked up the Serpent Staff from its proper location (see 5.10.) AND * you have not yet healed the Chaos Serpent 5.10. An important note about the Serpent Staff (SI) The Serpent Staff in SI is a very important item. It doesn't seem like it but it is crucial to some major plot elements that you have the staff in your possession. Unfortunately the game also demands that you get the staff properly. For that I recommend to get it without cheating and to stand right next to it. Just picking it up and not transfering it to the inventory at once, but instead putting it on the ground again could break later plot. Willem coded a workaround in Exult so the problem might disappear. 5.11. How to break the plot by doubleclicking some pillars (SI-SS) In the dining hall of the fort in the add-on Silver Seed you can doubleclick the pillars. This teleports you to the test in the gargoyle city. If you haven't done this test yet this breaks that plot later on and if you already have it is still a nuisance. So better don't do it. Obviously a slight oversight of the add-on designers. Could be fixed by changing the usecode and the map slightly. -------------------------------------------------------------------------------- 6. Questions and Answers 6.1. How can I get answers concerning Ultima 7/Exult? The best way to get answers to questions is to go to the Online discussion forum at: http://exult.sourceforge.net/forum/ To get answers concerning Ultima 7 in general go to the Ultima newsgroup: news://rec.games.computer.ultima.series Or go to the Ultima Dragons homepage http://www.udic.org and find your way from there (this is an online Ultima fan club) Some Exult developers like to hang out on IRC on irc.freenode.net, channel #exult. The logs of #exult can be found at http://www.math.leidenuniv.nl/~wpalenst/exultlog.php. 6.2. How do I contact the author of this FAQ? This FAQ is maintained by Dominus Dragon of the UDIC AKA Dominik Reichardt. Feel free to contact me with improvements or complaints regarding the FAQ. I am part of the Exult Team though I only write the FAQ and Documentation and don't code at all. -------------------------------------------------------------------------------- 7. Links and Thanks 7.1. Important Links * Exult homepage at http://exult.sourceforge.net/ * Daily code snapshot at http://exult.sourceforge.net/download.php * Message board at http://exult.sourceforge.net/forum/ * Bug reports to http://sourceforge.net/bugs/?group_id=2335 7.2. Thanks Of course big thanks go to the Exult Team for breathing life back into this jewel of a game. Max Horn deserves my gratitude for making the FAQ easier to maintain via XML/XSL. Thanks to all those I stole comments from without quoting them, those that sent me improvements and don't get quoted and so on. If you helped me in some way feel my gratitude without being mentioned. Thanks go to Matt0 who really got me thinking about doing this FAQ (though he just did it to tease me). exult-1.2/mac/0000777000175000001440000000000010062225324007012 5exult-1.2/mac/mac_autoconfig.h0000755000175000001440000000316707724430452012102 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Do we have a version of SDL that we can compile against? */ #define HAVE_SDL 1 // missing defines: #define PACKAGE "exult" #define VERSION "0.99cvs" #define VER_MAJOR "0" #define VER_MINOR "99" #define VER_EXTRA "cvs" /* Define if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define if the C++ compiler supports BOOL */ #define HAVE_BOOL 1 /* Define if you have the snprintf function. */ #define HAVE_SNPRINTF 1 /* Do we have zlib? (for compressed savegames) */ #define HAVE_ZIP_SUPPORT 1 #define HAVE_HASH_MAP 1 #define HAVE_HASH_SET 1 #define SIZEOF_SHORT 2 #define SIZEOF_LONG 4 exult-1.2/mac/ExultMac.mcp.xml.sit0000755000175000001440000002405107443515410012562 StuffIt (c)1997-2001 Aladdin Systems, Inc., http://www.aladdinsys.com/StuffIt/ ()rrT Reserved@Y&Y'x~ #'SExultMac.mcp.xmlTEXTCWIEBuV=vuVM2s~$d;o=h<WWyc w|3&"p4Q6ô~"oY;9> iWk=b_ϋ7GVzjXonX~$7?De3e'1 j\_gzu7 3TBPxZtQQrZO1#蒦Lqwś&T7[xZ03y$Ȅb" 1!Tqq3c&n-̉^˵ G%>y29/ !?ЗH,q*5t,3ٱmqqauJP pN&SQDMx-S!|BL aNURƜLtá\/SgB+lTx^Ƽ-/Fk 3Bu< 5Ht Ch`pF48IbdP&0@;Cί@k%Q؋| J(x2FkYIb$h f w0Ŗ&J4I/dBytx)gizc2;k Ρna .ӹTXJ,\o(ڝ-Bqw3zZSQRT\)'ij $/S񕞙%/Q9y\"q0D TS{u [:Pb /9k޾Ti(GZ0\IӔ̐GaG Tw6j96W!(pv%?fX E:zhh#8 œvs9,>]hm(yq *ZtKKZmЕ-!- LGKf$0M8$3=s]Xa|)c0>Wd/r g9D!8e8[>f`=Ǒৢ{%PA#El71= Q_o:Ʈ?u*Bn8Γzny, #JmِE1@٫HLdcbtEђɾ%?ĸ3gUK\I4 ] DßΌF SC kM} q~">s(WjȘf(_涺)Lwǻ <q-2ҎUΜ5}]!'- иe˗ZwZp "]†Kd9R `\6) sF7kL6clEvTjb |#u!*̢/HS+Nxm!?I|pV9?҈h 0#̫hFGi|bUZ^f'jͬkbe]s4<&aTࣺv;^2l3UT`MХu/K,4^Ƃ1 ^>'Ft'n54<׭7tgS9)P$xܹX&#ts >{ z4$Nf[[d&=pRP #RT?ML+'r鋜PanǸep /DAc(0Xl%RmOm"ꐠWF(hp!ϸ,M4M&;2#@v!_P;:8KhaT11슁o7N؛v6uz32_*ȸrקda&8oaj%HZ(鞦(rTsX=n^*4^~D< oPVX\+`6]E)@{y}J%k1~ER)18ǚQ Shj;*aPbv٢f]Şm+P ,rj#0#gH{:kʥ'wXX[y2~pW}8R2lԇ(&d+?A(o<پ_1Qw?FᅎoLoU`H*bKrR)7Dg1?~Y9koWAt:F"Đd`Gjע I岁 EIK =}D4%/ɶaz!<RPE+S`b?,(y(mb6oj?A{}1q٠]&F ҚO2mi>}1AIw> }7 Dhsj|,O>zMgJ#=S6D /tZ̀Ck8$P>u?<4GcBiUhQO<H;wU>RNF'pLP֋v=B X<tO?znu:׉?pظ6ԟ1Wv{w:LOKU>&Gf)6^E[^¯8:Mnwrtѓy>T;(p!|t zaP6{{^ߋУѻT')g~AQEi`XDOi `z^wn n7j Z*~qxNDgEĥ4Y+9)[exO-4|kq(FA7.U\ҕ_(Mp.h>X'xk!pDG Pd?uàI{_F|jZmU"zw\~arGWo: )ͅ{A]b&$ނS <;%F)LJC_wE7WM L'cwWR=Sv(ߪm_sp趁O B qap{⻥@GbfX~1B1w~ucӢ?Įhp>'hJ E S ~q?1]9G="%ʹdg8wc2"Ye{Pd`Azd }X se)%R9Jɶs~ڐuIt,K(Cgc]mYHGD(s/lPK9݋Sud6g41ՄYb LV-uC tʥ}q-,ۛ6BԅyCr3yJCWyfb'8!}bj2 @Ay%;#d<IMj0?:<-` mLDHS02k A§WUp-}&f^@{)E,bX3QY@mLsWT/Qme3r ت2yUs=n Agz WwpR8fCfhUsk8 )4:VYtއw}C<-d`G)n l|ziW|k9 ZTUV kpz9) i*z>j}mS#^ l,]`Mn ~UT'D` yiUFR{ DAjh>% RH> Ak]7&A< 'Ή 0^ro(QL)]6nR5#7 q=γ I7ILLk:50_r$y R-Y7'"U37V$xfͥ3u|UGd| ,e[d2U#)z€ )!s(~p݈lHObqgXj' /HV '\SgIv>^`j4H~ew2j+̊ r_S\92|2\N"V-w2*06TW 3 )\u6yጩuBoyTXr  Ĩ_k3ma[VnLȀYFCI=Ϟ2'|s-;hxՊʘ,f L AaJ&|K4Dhq pR 6EXQ:nzj3bo5}BRvPB_r  gvؽTxďԍVE"\n&l :.Rp^I[u1pl,'^oY_U8N :PXo(8=~]YIl+l/v(< pHl>.PyaO:b0bh<eQNeѢ#Z>751_+\*,^ae#J.k1zhLύ(rI%VJXGkk3VR^ȉF"P+L7Xɸ kT:umʗ8Ô/gPri-?@#g)߹ (xbac dk+qQ1fn FV]]CJkAxގ0\Z2x]YIC/MVMa#v۾k~3id񃿎rx5 :%8'5b `<4}U9,*F"|4%BlqRn,E RgpzN-4coֹbY伧!$Iiwyd>Z[)gLu5R(/~ 5kY]Ra& beG.!䟐%Xx0JX [%oeZGl{HGsF]@6C0݄ Z,h5)#Lk1n<މ7]XO׋my+Q-Kr/X>O ̵#3/kcI' ,$L8=;XzcGgO<\)8]zݰp=ױY"3zFtNQLѝ ӐERcY0\bZtZt*ĉ?m߲=K&q=䳄 뒚4_ 2[Gp5v&Naduz{6f6:S!1$}ݦL5)p' ۇЎ 0~ 3HKZ4 "膍|ULLx%~! 4Dh#}!pRz/ޠ"nC{/HZגJ~B7ܥg1ag|s!;"dqbtb(cҪ%5xpfC$QPwiҋooz&< ΜG [n`;Gh+?.89ԩ8PTfg]o~"U.4PʱN 9$Gtgv2nKE^ONwgMQ]=YNS^s x *y4Uyy5JFˮZaB`y# 8JDhpJ`"vޯ؞+ddKz`֒ XL$YYH^} hH*Q\1rg1O}DlM͡f2H W H:Yε, O2[S_dE.[X޳6]7ҏL2,e!2>H}ݕN3namI~oCW=4j7 oH}(&\.s坹#<2թ֩^') =c/Q}͐Y2fgUFșm6 xYp 0,Nt~$,}Ɨl t+ _vZϞ_;o3̈́|U3@J'kЀЪON&<F}[s 5xX7 |@oeMeㇻ-[[ ;NiZ4Vo\CT>lAB~]ׁ: ]L]>\;u&ɩw~O3`41J H-ibZj^- \ߗǻ'EeB2m7η h@y21@T['oxmE5I,*8}v;^@'g5%~rh`Rvy5=6"/nz;,&1oT~vNhACGӯeMp۞X~|صOi2fcV/P XASd#K9vHD c-̬̂k3C/>KCY"X=\b>hDDDe`pښ 8Z *̷}pPBu\ %d7R4Ȗe{aA+4\kI^|:b0ն!w.p%WƗ 4T֣䅗W/0e 0ɶ{`EuպGi\ 95`^s΍D9Ϥl,#%زR[rYEG* FVnnw .籺XGRѝiRaxVC*N'Hiҵ.Z&9m TLakⰁhfX- Wq\ P6 jEM Jq2lbm?eCj]lTHP3/rV -P߁xI0ԄfPjUEO㷟O+U]XuG؂,z^wH4KD$sW4HبUdZLaAfzGҤǔD)H,x({sV|(GhJcJ(N`oXdZ狁alZ1B6Ea?FD,m۽4QʚIM2]P U! tSG hh;5RP^gɇ2hr5fv;hCrxgJ?VZ ̟Ga?=8{hV׾By s+J>!HkDiDo ]xz|TF#Y`)kyUnETicGĖ2,P^;03e5<No23&Z d)@vsFMf1g 9G JWTdUEVs!*N9?U onQ(g6 (SV&:{^qZ;)\M޺Ο'H9)H|}uj١eu\eă'+^Q<ՑCDĮG#QĻ4=5C9;]$7 63exult-1.2/mac/exult_version.rsrc.bin0000755000175000001440000000140007443674311013311 exult_version.rsrcrsrcVSED,2͸mBINm00.9.8rc1 0.9.8rc1, 2002, The Exult Team0.9.8rc1Exult 0.9.8rc1*ExultExult2002exult.sourceforge.net7 The Exult Teamhttp://exult.sourceforge.netmSORT^STR#vers*VH4ProductVendorexult-1.2/mac/mac_prefix.h0000755000175000001440000000173307724430452011236 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // this tells the code we compile on the macintosh. #define MACOS 1 // no autoconf on macintosh, thus "emulate" it #include "mac_autoconfig.h" // missing functions: #define isascii(x) (!((x) & 0x80)) exult-1.2/mac/exult_icon.rsrc.bin0000755000175000001440000013220007333356427012562 exult_icon.rsrcrsrcDougڵImBINXultICN#FREFAPPL=8P)@<=08P`N]HnHnܩ/.<䩏Hnܩ( l P0(H/HnN7B=8NpN]Hnܩ/.Hn|<|<|<|<|xXicnsXICN#??>|<|<|<|<|xicl8+++++V+++++V++V+V+++++++V++++++VVV+VVVVV+V+++V+++VVV+V++V+V++VV+Vil32Eًntg^7$Ĕ `Qʽǚђ 1ƈX|; >ñ@ +lUz;cc sµA3(2 v3e} Kü%n .ϸ.]s +^%ۿ?W {҅9Aԝ (&C|n %Tνx*nÉε㢟/{"ұɞS}WC`  .eni{`ī{* ' ݊bf ll#l3ܗ"BŖ"Taި#Ct"ٕ2=ёo:N9ًntg^7$Ĕ `Qʽǚђ 1ƈX|; >ñ@ +lUz;cc sµA3(2 v3e} Kü%n .ϸ.]s +^%ۿ?W {҅9Aԝ (&C|n %Tνx*nÉε㢟/{"ұɞS}WC`  .eni{`ī{* ' ݊bf ll#l3ܗ"BŖ"Taި#Ct"ٕ2=ёo:N9ًntg^7$Ĕ `Qʽǚђ 1ƈX|; >ñ@ +lUz;cc sµA3(2 v3e} Kü%n .ϸ.]s +^%ۿ?W {҅9Aԝ (&C|n %Tνx*nÉε㢟/{"ұɞS}WC`  .eni{`ī{* ' ݊bf ll#l3ܗ"BŖ"Taި#Ct"ٕ2=ёo:N9l8mk 1F?G Pm FMUwV>_"S3*NNNNQONNNC B2̜; 4݈ "-;Ry 7)&W3<8 dlich#H????????? ???ich8 +VV++++++++++VV++++V+++++V+V+++++V++VVV+V+++V+V+++V+++V++++++++++++++V+V+V++V++VVVV++++++VV+V++++++++V+V++++++VV++++++++++VV++V++ih32 ŀ )  S+sp@3џLǫܝ̡ĵ[ TdžKHtƜbŨVvŔ#dü!½C ĔWBĎ {<-DBcݽJsX&T· :ml1=Vǽ>¨#Ė Č-'^3]jj ]?^$dz.r d˃ S׋ >ϟ6y ˑNjV> ق yo>ՎT~|{{||{åˀLF]B•wΕԫ+Ð>9ԣc2Ev3jK,ےsFv Wȓ'OGxz&EjdGzUI|{MkXڌ kc۝Qkܩ>޴ ֥&߻ 7i 3A\ ܫ )J ہk ;h I ӻ@b 3kJE   4/Ɠŀ )  S+sp@3џLǫܝ̡ĵ[ TdžKHtƜbŨVvŔ#dü!½C ĔWBĎ {<-DBcݽJsX&T· :ml1=Vǽ>¨#Ė Č-'^3]jj ]?^$dz.r d˃ S׋ >ϟ6y ˑNjV> ق yo>ՎT~|{{||{åˀLF]B•wΕԫ+Ð>9ԣc2Ev3jK,ےsFv Wȓ'OGxz&EjdGzUI|{MkXڌ kc۝Qkܩ>޴ ֥&߻ 7i 3A\ ܫ )J ہk ;h I ӻ@b 3kJE   4/Ɠŀ )  S+sp@3џLǫܝ̡ĵ[ TdžKHtƜbŨVvŔ#dü!½C ĔWBĎ {<-DBcݽJsX&T· :ml1=Vǽ>¨#Ė Č-'^3]jj ]?^$dz.r d˃ S׋ >ϟ6y ˑNjV> ق yo>ՎT~|{{||{åˀLF]B•wΕԫ+Ð>9ԣc2Ev3jK,ےsFv Wȓ'OGxz&EjdGzUI|{MkXڌ kc۝Qkܩ>޴ ֥&߻ 7i 3A\ ܫ )J ہk ;h I ӻ@b 3kJE   4/Ɠh8mk %^T.'s*@@m)WOPLFUwG#ecKy;x C^_AM3V[F*'8c}@ics#Hpppics8VVVV+VVVV++VVVV+VVVVVVVVVVVVit32;腷ʘG33GFF4 +1( 4R Dmޱx=R3mޱ|].,xŀɽ3 e³l  ɀއ3Ȱƀ̃3eѷ|ǁ e ɔeb}ƀ x3dпuHRbnɹłO3*ٿоtHELWC6vÀ ƻ-4̹|cVKL3 JŭW4BvYf`J2€ Ȼ{a#4 ̿ɨmZaN :ʒXF4G±uV Nͫ ˼fR#dwȋXHd3Ȝ|1E"ڿʺna tǿ{h{YRÿȓrJeĿȯunreǿDzteC@Ǜ{XQ`Ƚ0Cy廽x/ & û_عĹ}qed |ɋʸķd4a2ĹºH3B!@»01H,%G @Ű&f$)E5¿ ɦ/E,Áɝ ƾ1E#œ 3 ȵ&EŻ GþEuǯ E 忿Ĵ|E3dɥ{E쾿ĦZEG;ˤzE漿2EG!ͪE)ȷGζ)GG:ؽǪje¦B3EUϽĠCC/ʹkɼeȎɰsFfȮ FF$ŦG1*?O̺eq ˥e1Eѿ44λ,fFę9QΞh&QВsV4 ѻ344 ٫`Y#ec C͔xa $BqWKӷ~u/4~۩eq< ]͝[c.Ӝ#33 *Ӿ$7n̻̐ ůWh鐷f o f2Ymw`n$fD7ǭKmyLKDE /2.,+*)*)(%T׽Vn8K@)+,--.-. //01478, G E lҭoFu ŮR 3 D fŲ&Ԭԛ}tQ.fcԃӁ҅ρ uUM'Sd߀4ڮxm3St܀;ԱՀրʨKS õv\T\k|$״ѱr SQ='³u`WW\bgnuyyɴnbehoyٵSP̿xX/  *Ⱦ/(4CiôDS Цq= *ƽ/  Iv Sc_ƩV  +Ž0 I`@S #] ,ż/Wn4cT2 +Ƽ/EF3IR3G+Ž0E職G3QE4-ž1E踘FFe.3EeFR.ſ2ER f2Ff.ſ3E fF2H/4E05E06E27Ee8;ED@AEELKEEWSEa_EmnExzEƅƍœěä) &G3ھ0EG>߀ ܾ6EGY߽CG3 ᾳ^3㿫s 忟| F.Ŕ FTӑ8ޚ`e4崘1 Yـ ͨD4ۿŇ4;ο1e!x<Հ ˮ.d˺ud!DzбLD Eqw|PG"EJX0DQ23D:ߓE90fр ځ8;0 3fۀ78(U݉77 4 Vޟ@6#4 dھ]E.RςXG R37ufS MS"SQyQQ#̠cn4E4ʅ33腷ʘG33GFF4 +1( 4R Dmޱx=R3mޱ|].,xŀɽ3 e³l  ɀއ3Ȱƀ̃3eѷ|ǁ e ɔeb}ƀ x3dпuHRbnɹłO3*ٿоtHELWC6vÀ ƻ-4̹|cVKL3 JŭW4BvYf`J2€ Ȼ{a#4 ̿ɨmZaN :ʒXF4G±uV Nͫ ˼fR#dwȋXHd3Ȝ|1E"ڿʺna tǿ{h{YRÿȓrJeĿȯunreǿDzteC@Ǜ{XQ`Ƚ0Cy廽x/ & û_عĹ}qed |ɋʸķd4a2ĹºH3B!@»01H,%G @Ű&f$)E5¿ ɦ/E,Áɝ ƾ1E#œ 3 ȵ&EŻ GþEuǯ E 忿Ĵ|E3dɥ{E쾿ĦZEG;ˤzE漿2EG!ͪE)ȷGζ)GG:ؽǪje¦B3EUϽĠCC/ʹkɼeȎɰsFfȮ FF$ŦG1*?O̺eq ˥e1Eѿ44λ,fFę9QΞh&QВsV4 ѻ344 ٫`Y#ec C͔xa $BqWKӷ~u/4~۩eq< ]͝[c.Ӝ#33 *Ӿ$7n̻̐ ůWh鐷f o f2Ymw`n$fD7ǭKmyLKDE /2.,+*)*)(%T׽Vn8K@)+,--.-. //01478, G E lҭoFu ŮR 3 D fŲ&Ԭԛ}tQ.fcԃӁ҅ρ uUM'Sd߀4ڮxm3St܀;ԱՀրʨKS õv\T\k|$״ѱr SQ='³u`WW\bgnuyyɴnbehoyٵSP̿xX/  *Ⱦ/(4CiôDS Цq= *ƽ/  Iv Sc_ƩV  +Ž0 I`@S #] ,ż/Wn4cT2 +Ƽ/EF3IR3G+Ž0E職G3QE4-ž1E踘FFe.3EeFR.ſ2ER f2Ff.ſ3E fF2H/4E05E06E27Ee8;ED@AEELKEEWSEa_EmnExzEƅƍœěä) &G3ھ0EG>߀ ܾ6EGY߽CG3 ᾳ^3㿫s 忟| F.Ŕ FTӑ8ޚ`e4崘1 Yـ ͨD4ۿŇ4;ο1e!x<Հ ˮ.d˺ud!DzбLD Eqw|PG"EJX0DQ23D:ߓE90fр ځ8;0 3fۀ78(U݉77 4 Vޟ@6#4 dھ]E.RςXG R37ufS MS"SQyQQ#̠cn4E4ʅ33腷ʘG33GFF4 +1( 4R Dmޱx=R3mޱ|].,xŀɽ3 e³l  ɀއ3Ȱƀ̃3eѷ|ǁ e ɔeb}ƀ x3dпuHRbnɹłO3*ٿоtHELWC6vÀ ƻ-4̹|cVKL3 JŭW4BvYf`J2€ Ȼ{a#4 ̿ɨmZaN :ʒXF4G±uV Nͫ ˼fR#dwȋXHd3Ȝ|1E"ڿʺna tǿ{h{YRÿȓrJeĿȯunreǿDzteC@Ǜ{XQ`Ƚ0Cy廽x/ & û_عĹ}qed |ɋʸķd4a2ĹºH3B!@»01H,%G @Ű&f$)E5¿ ɦ/E,Áɝ ƾ1E#œ 3 ȵ&EŻ GþEuǯ E 忿Ĵ|E3dɥ{E쾿ĦZEG;ˤzE漿2EG!ͪE)ȷGζ)GG:ؽǪje¦B3EUϽĠCC/ʹkɼeȎɰsFfȮ FF$ŦG1*?O̺eq ˥e1Eѿ44λ,fFę9QΞh&QВsV4 ѻ344 ٫`Y#ec C͔xa $BqWKӷ~u/4~۩eq< ]͝[c.Ӝ#33 *Ӿ$7n̻̐ ůWh鐷f o f2Ymw`n$fD7ǭKmyLKDE /2.,+*)*)(%T׽Vn8K@)+,--.-. //01478, G E lҭoFu ŮR 3 D fŲ&Ԭԛ}tQ.fcԃӁ҅ρ uUM'Sd߀4ڮxm3St܀;ԱՀրʨKS õv\T\k|$״ѱr SQ='³u`WW\bgnuyyɴnbehoyٵSP̿xX/  *Ⱦ/(4CiôDS Цq= *ƽ/  Iv Sc_ƩV  +Ž0 I`@S #] ,ż/Wn4cT2 +Ƽ/EF3IR3G+Ž0E職G3QE4-ž1E踘FFe.3EeFR.ſ2ER f2Ff.ſ3E fF2H/4E05E06E27Ee8;ED@AEELKEEWSEa_EmnExzEƅƍœěä) &G3ھ0EG>߀ ܾ6EGY߽CG3 ᾳ^3㿫s 忟| F.Ŕ FTӑ8ޚ`e4崘1 Yـ ͨD4ۿŇ4;ο1e!x<Հ ˮ.d˺ud!DzбLD Eqw|PG"EJX0DQ23D:ߓE90fр ځ8;0 3fۀ78(U݉77 4 Vޟ@6#4 dھ]E.RςXG R37ufS MS"SQyQQ#̠cn4E4ʅ33t8mk@   &1;BFD?6,   %7K^p{gTA. &>ZzȗiK1 8YkG*'Gs]5 +Sl= -XwB *V{@  %Ps:Dg/5nV"  &WB@m-  +bOCʶy2  )aƬ_BAbR>ƨ}O)%Py/ "WȨyF ML2pϯ}FUm&DغM (i< !Vʜ\& =U ,gڵw6"bo$6{ϜSD5A7  2zG Hf#&eVNסQVcPϑ@Ko#Oȃ3Cv'Kx*>y*Eo#;x)^WdC֡PEiK̑A4q%T3 %f|,&_߲j%M6 0nҟS8D <ʼn>%gVLߵp+Kk"'_ҡV 3|37wÉ?[JMرm*=h# .h˘P%f:Fܹ{6 C\.fΠ[  'i;Kܼ>Cc' 8sΣa%$cJ,^ٺ@;}= &Qɞ^$ Wp:#*Lӳ|< &FtU]Ȟf7  *&  @pppVVVV+VVVV++VVVV+VVVVVVVVVVVVBNDLBFREFNXultZicl8fICN#ricns~ics#ics8L (+ /3\#7-7Owner resource Item Icon Item Icon Item Icon Item Icon Item Iconexult-1.2/NEWS0000644000175000001440000003067210061526374006705 06/10/04 v1.2 Official release with all the improvements and bug fixes from the last two years. 02/29/04 v1.1.10rc2 Fixed a number of crashes Fixed some Windows-only problems, including resurrection Added more Black Gate paperdoll art 01/27/04 v1.1.9rc1 Cleaned up non-MIDI music driver support Cleaned up diagnostic output Fixed various schedule and pathfinding bugs Worked around Serpent Staff bug from original SI Lots of minor bugfixes 10/18/03 v1.1 Beta3 Fixed item duplication Fixed missing NPCs Fixed disappearing items Fixed cosmetic bug in 2xSaI scaler Fixed resurrection Improved SFX handling for items Improved schedule support 08/08/03 v1.1 Beta2 Fixed missing item descriptions in Windows Fixed missing exultmsg.txt on some platforms 07/20/03 v1.1 Beta1 Party Formation Improved combat system with pausing, hit display and targeting Spellbook improvements Exult Studio improvements and porting to GTK+2 Support for arrow/keypad walking and running OGG Vorbis music system FM Synth emulator Additional paperdoll art (SB-X, Oblivious) Scale2X scaler (Andrea Mazzoleni) Ported to the Zaurus (Artaxerxes) Experimental OpenGL scaling/rendering Tons of bugfixes (see ChangeLog for details) 06/05/02 v0.99 RC 2 Support for 32 bit usecode (for large usecode functions) Many changes to Exult Studio (tiles, combos, freetype fonts, etc.) Improvements to UCC (conversations, etc.) SFX improvements (thanks to Simon Quinn) Tons of bugfixes (see ChangeLog for details) 03/12/02 v0.98 RC 1 UCC, Exult's Usecode compiler works again UCXT, Exult's Usecode decompiler, is now included Subpackages for Linux distributions can be built (RPM, Debian) Exult's data files have a CRC now, so it is easier to detect a mismatch between them and the main executable Gumps can be dragged even in target mode SI's intro and ending are complete Music looping is user-configurable New scaler from Kreed: BilinearPlus Configurable combat difficulty Tons of bugfixes (see ChangeLog for details) 11/26/01 v0.96 beta 1 It is now possible to complete both BG and SI Savegames are now compressed. They are now actually zip files, so you can use your favourite tool to open them. This should make things easier especially when submitting bugs to SourceForge which has a size restriction on attachments. Gameplay Options Dialog has been implemented together with a slew of extra features that can be configured The speed of the party may be configured Middle mouse button support Fast mouse in full-screen modes Tinted background behind text in conversations Wheelmouse support for slider gumps You can now freeze in SI Multiracial Avatar support in BG (requires SI) The currently playing music track is stored within savegames so that it started again on load Scheduled usecode is now retained between save/load Endgame and Quotes entries in the menus are now only visible when appropriate Allow choice of MIDI device in Win32 Many broken animations were fixed (especially in SI) Show SFX icon next to BG/SI to show that support for digital sfx is enabled. Tons of bugfixes (see ChangeLog for details) 08/25/01 v0.94 alpha 5 Colourless' amazing stats display (press "r" to toggle the various modes) Lots of work on performance improvements (faster scalers, faster renderer, etc.) Near-perfect dungeon renderer Lots of work on MacOS by Fingolfin (both Classic and MacOS X), including MIDI support. Return to menu option in BG and SI game menus Detect incorrect/incomplete path settings in the configuration file and show only valid entries (BG/SI) in the main menu. If neither game is available, a warning is displayed. Video Options in-game menu (still incomplete) Text/speech synch in BG intro and near-perfect butterfly animation Support for scale > 2 in Point and Interlaced scalers Exult now compiles with MS Visual C++ Tons of bugfixes (see ChangeLog for details) 06/28/01 v0.93 alpha 4 There is a new in-game menu (invoked with ESC) from which various setup actions can be performed. Currently this includes a nice audio configurator. The save gump has been improved greatly with support for a mini-screenshot, save-game details and infinite savegames. World wrapping has been implemented Lots of work on SI (spell scrolls, spellbook, jawbone and combat gumps, keyring, general fixes) We now have Near Pixel Perfect Maps (tm) which are displayed when using the teleport cheats. MIDI SFX are unsupported now by default. The use of digital SFX is strongly encouraged, even though there are still a few problems. See the FAQ for details. Combat has been improved: NPCs now flash red when they are hit, Protection mode is supported and many bugs have been fixed Win32 SMP-safeness More work on ExultStudio (Linux only for now) Tons of bugfixes (see the ChangeLog for details) 04/11/01 v0.92 alpha 3 Savegame names have been changed to exultXXbg.sav for the Black Gate, and exultXXsi.sav for the Serpent Isle. (The savegames themselves have not changed, so you can rename them to make them work again.) Multiple scalers can now be used. Use config/video/scale_method set to either "2xSaI", "bilinear", "point", "interlaced" and "SuperEagle". "2xSaI" is the new scaler, "bilinear" is the old one, "point" duplicates the pixels, "interlaced" is the same as "point" except misses every other line, "SuperEagle" is another scaler by Derek (the author of 2xSaI). New cheat screen (F2) similar to the originals'. Currently allows for some level of NPC editing. Pick Pocket cheat (Ctrl-Alt-P). Forces all actors to display inventory. Grab Actor cheat (Ctrl-Alt-G). Default Enabled. When enabled clicking on a NPC will make it the default NPC in the cheat screen. The default NPC is edited by not entering a npc number. NPC Numbers cheat (Ctrl-N). When enabled, clicking an a NPC will display their number instead of their name. More NPC schedules (sew, lab-work, etc.) implemented. Many bugs (especially combat/weapons and audio) fixed. Black Gate paperdoll art by Adam Delman and Philip Gottschalk 02/08/01 v0.91 alpha 2 Dynamic keybindings. Use config/disk/game/(gametitle)/keys to specify a keybinding-file. See data/default.key for an example. Can now use the Serpent Isle paperdolls while playing The Black Gate. To use, the Serpent Isle path in the config file must be filled in with an absolute path. Paperdolls may be a little buggy. Massive code restructuring and cleanup (use STL wherever possible, pervasive use of namespaces, more portable C++ conformance, etc.) These changes have the side effect of improving stability. Gamma correction (use + and -) More schedules support Improved, easier to use shape browser Serpent Isle paperdolls Improved weapons support Support for the French version of BG (Frederic Wagner) Alpha/Linux cxx support (Christoph Reichenbach) Allow for disabling/enabling of palette fades Improved BG intro (plasma screen, animations, etc) New cheats (Heal, Resurrect, Max Party Level) Sound Tester (Alt-1) Screen Shots (Ctrl-Alt-S) Reworked audio subsystem (including MIDI repeat support for Timidity) Loads of bug fixes (Read ChangeLog for details) 11/20/00: v0.90 alpha 1 New scaling code contributed by Derek Liauw Kie Fa (2xSaI filter) Exult logo & menu at startup & mouse support in menu Many more cheats (ArchWizard, Hack-mover, ...) Key ring for BG (same as original SI) Improved help About box GIMP plugin is functional (load & save) Better SI support (not playable yet) Midi Sound Effects (Windows & Timidity only) Tons and tons of fixes (magic, schedules, weights, dungeons, missile eggs, explosions, invisibility, protection, ...) More quotes & credits :-) 8/22/00: v0.40 Note: ALL save games from before this update are now broken. Games must be restarted. Better introduction sequence. Can be interrupted by keypress. Main menu implemented. Proper instruments in MIDI music and XMI support. Cheating mode: any keys which enable additional features can be disabled/enabled from the config file 'God mode' (alt-G) and teleport (ctrl-alt-t) cheat added. Support for barges (Flying carpet, ships, carts...) Teleports. Combat: Monsters attack, and the music plays. More shortcuts: 'f', 'w', 'm', 'b'. Serpent Isle awareness (not useful yet) Better shape browser. The usual slew of bug-fixes. 7/6/00: V0.35 Scrolling works like the original. Same for conversations. First attempt at combat: You can attack/kill monsters, but generally (with a few exceptions), they don't fight back. Spellbook and magic (some spells at least) work. Weather: Storms, clouds. Scaling: 2X scaling with antialiasing. See README for details. 6/2/00: V0.30 Save/load implemented. MIDI improvements in Windows version. More animations: You can see the weapons being carried. Better object identification and inventory management. View the endgame movie by hitting F10. NPC schedules/pathfinding improved. Moongates work. Sleeping works (but animation not done). 5/8/00: V0.26 MIDI in Windows version!! Correct Avatar/NPC animation frames (finally), and improvements to 'seashore' animations. Inventory improved: Armor, etc. goes where it's supposed to (although there are still a few things to be fixed). You can now read signs, books, and scrolls. Much improved shape browser (a development aid). Many bug fixes. New pathfinding framework. New object access API for some data-objects 4/25/00: V0.25 Improved midi support using the timidity binary and patchsets under linux. Earthquakes (except in Win32 version)! In-game scripted introduction. More animated objects. Some NPC schedules now implemented. Lighting and transparency. Better USECODE support. You can solve the Trinsic murder, and then answer the mayor's copy-protection questions to get the password. Also speed, compilation and debugging improvements. Improved inventory support. You can buy items, and feed Iolo. Better support for building win32 targets. Improved rendering pipeline. Still not perfect, but definitely a vast improvement. 3/23/00: V0.20 Speech and midi support from Dancer Vesperman, as well as automatic configuration. Inventory partly working. You can open bags and boxes, and drag items in/out of them. Mouse pointers and fonts from Ultima7 are now used. Animated objects (like fountains and flags) supported. 2/29/00: V0.12 Fixed crashes at start and after initial conversation, thanks to Richard Wesley. Added obstacle detection. You now need to open doors to get through them, and you can climb up/down stairs. Replaced XLib and Win32 code with the SDL library. Should make porting to Windows far easier. 2/20/00: V0.11 Loads of improvements to the USECODE interpreter, especially with conversations. 2/10/00: V0.10 Added USECODE interpreter. Removed my previous conversation engine (which I'll use in another project). Exult creates the "gamedat" directory and files automatically. Moved web site to exult.sourceforge.com. 7/5/99: W.J. Palenstijn's WIN32 port! 6/10/99: First attempt at obstacle avoidance. 5/28/99: Wrote a script compiler for NPC's. 5/24/99: Modified conversation engine to handle the notion of a conversation "topic". Also show character "portraits". 4/23/99: From Tristan Tarrant: Read item names from "text.flx" instead of trying to enumerate them in the code. 4/14/99: V0.07 First implementation of an NPC conversation engine. 12/21/98: V0.06 Startup memory requirements are reduced dramatically. A port to MSDOS (320x200 VGA) is added. 12/4/98: V0.05 Added text rendering using the FreeType package and the "avatar.ttf" font. Left-clicking on many of the game items now causes their names to show on the screen. 11/5/98: V0.04 2 other characters walk around randomly. Double-click on doors and shutters to open/shut them. Program exits gracefully when window is closed. 10/14/98: V0.03 Avatar now walks around using the right-mouse button. 10/6/98: V0.02 Show moveable objects from "ireg" files. Read in all objects shown. Improves display performance. Attempt (with partial success) to show objects in proper z-order. 9/25/98: V0.01 Try to open files first lower-case, then upper (u7open()). exult-1.2/beos/0000777000175000001440000000000010062225324007202 5exult-1.2/beos/exult.rsrc0000644000175000001440000001016307400647066011170 RSODDDDDh#  application/x-vnd.Be-elfexecutableapplication/x-SDL-executable             a          `Exult Ultima7 engineExult Ultima7 engineSMIM BEOS:TYPE BEOS:APP_SIGNOCIeBEOS:L:STD_ICONNCIMeBEOS:M:STD_ICONVPPABEOS:APP_VERSIONFPPABEOS:APP_FLAGS9exult-1.2/data/0000777000175000001440000000000010062225327007166 5exult-1.2/data/bg/0000777000175000001440000000000010062225327007556 5exult-1.2/data/bg/collar.shp0000644000175000001440000000033110012751274011457 q         exult-1.2/data/bg/gorget.shp0000644000175000001440000000026610012751274011501 a }zz~}|~}}|x{~z~zwv|}|}{}~ }zz~}|~}}|x{~z~zwv|}|}{}~exult-1.2/data/bg/male_av_face.shp0000644000175000001440000000360307331266364012605 9E          " +++"  &  &  &  *  *   * *   * *   $              +++              . !# Ͼ$"$$$Ϻ"  ϻ--   ϾϺϻ--   . !!# %   #   %     %--- $ "            ---       exult-1.2/data/bg/mr_faces.shp0000644000175000001440000003131207365611341011774 2)'"h*(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S U U S  U U O U  U O U .   U O U    U O } U  . U}O} U   U }O }U  U}O U mlmU}O}Um lm U }O}UmlmU O }U mU O}U- ml mU O}U .*U}O U.sWksU}OU6oToloTo+U}OU   UO}U mm UO} Umlmmnm}O} mmkm }O}m }O ml }O * }O}( }O  }O! ml m..- }O" O# }     O$} .}O%} . }O&} .-}O'   -}O(   S)   S*    O+OS,  S-S. S/ S0  S1 S2  S3S(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S 7U S  UU O U     U O U     U O U      U O } U             U}O}U         U}O }U   }O U     }O}U     }O}U     UO }U   ,  O}U   ,  O}U    ,, U}O     ,    }O      U}O    , UO}    ,, O}     }O} ,  }O&} ,$,n U}O   , U}O $ U}O}   , q  U}O    , U}O! ,, U}O" , UO# }   ,q UO$}  ,, q U}O%}   ,    }O&}, }O' ,, , }O(U,, S) ,,. S* U ,,. O+OS,  S-S. S/ S0  S1 S2  S3S(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S 7U S  U  U O U   U O U   U O U  U O }U U}O}U& U }O }U U}OU, U}O}U }O}U   O}Uk, O}gkO}i,  }O"ki}Oi }OU kik, k  O}Uiklik,  O}Ullg}O}$Ul, }O}Ul  }O Ul }O U }O}U }O U   }O!   , }O" O# }  O$}  ,}O%}  }O&} }O' ,   ,}O(    ,+,S)  ,+ S*  + O+OS,  S-S. S/ S0  S1 S2  S3S(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S UdU S  U-ݡU O UVtc tVU O U V..u-U O U...-U O }Uu.,,uU}O}U -u-  ..dU}O}U., ,-.-}O.. + +,.}O} u +,}O}  .UO }  .dUO}(- - + VU O}.. ,U}O .t, -VU}O+,WU}Ou , + U O}u,+sU O}.* U }O}*+sU }O}u   * dU }O u+*  + U }O +  U }O}&+ + , U }O uύ+  ,c U }O!u +  U}O" л   ޡU O#*}uVU O$}  -U}O%}-u U}O&"}" dac}O'"  }O( -S)   + ,  S*   q  O+OS,  S-S. S/ S0  S1 S2  S3S(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S 7U S  7U O ;U O U VdVU O UVe:--9dU O } UVߓ ΐVU}O}U Vt-. u ,t U }O }U V. u u V U}O U- uߒ t U}O}U uu  -VU }O} U-uVU O }U ܌  tU O}V.u eUO} e-u-:V}Oߒu W}O":.  -ߟ}Oϒ ΓO}. tss ΟO}u: Ώq  -}O}u  }O}u- q }OΏ ܑ }O$- .}O}u  u }O -,.}O!u u}O".,uuO#}  ..O$}uuu}O%},- }O& }  :u}O': }O(Uu  S) c  S*  O+OS,  S-S. S/ S0  S1 S2  S3S(3S  }} S}}}} }}}}}}SKR}}}}}}}}R}S}}} }SSO ;U S 7U S  7U O Ud U O U  U O Uݡ  U O } U U}O}U-.ϓ.. .tU }O }U.-   sU}O U. U}O}U.  .U}O} U. " UO0}Ut. m-UO}U.ϑm*UO} ϑ U}O .U}O . U}O  ntU O} *  U O}U -q-pU }O}U U }O}UTlU }O UT յmU }O U rU }O} UVU }O UTUV- U }O! T U&- , VU}O"UV r -U O#}t-UdO$}  -..}O%} .. }O& }s..- }O'.}O(,-S)   S*     O+OS,  S-S. S/ S0  S1 S2  S3Sexult-1.2/data/bg/magic_boomerang.shp0000644000175000001440000000103607256474661013341  )+ )*+ )*++*++*++*++*+ +*++*++*+ + )+ )*+ ~}|zx )*+ ~+*+ |~+*+ ~ +*+  +*+  +*+ +*+ ֳ ٳ ֳ ٳ ֳ ٳ ֳ  exult-1.2/data/bg/bluedress.shp0000644000175000001440000000607607515126777012231 > $  * 4  8  WS VS TVSQR#VR VRSQRW%RQ RP QQRW'VP QSPPQRT+RPQRSRQP QSTV+PQRSR Q QSUT/RQ RQ QRSTW/SR QRSTSTU/ SRQRSTST- U SRQRSTSV+  TSRQRSV) U SRQQS RSW' SRSRQSRQRSTW'TSSRQR RSTUW' SRQ RSTUW'W SRQ RSTU'URSRSU'VRS RS RSU+ URQRSR S RSTV+TR SRSU+WSRQ RQ RQSW+WSRQRQQRSRQRW+WTRQRQRSRQR+VSRQ RQRSRT-WTRQ RQRS RSW-USRQRSRQRSRSRW/WSRQRSRQRS RW1TR QRSRQRU3 VSQPQRQ RQRS3 URQNQRQ RQRSW5 VSQNQ RSRQ RQRSV5 URQNQR SRQ RQRW7!WS QRSRQ RQRV9"WSQPQR STS RQQRV;#WS Q RSTUTU R QRW;$VS QRST USRQNQS;%TQ RST UTSRQNRS;&TQRST UTSR QRW;'WS RS TUTSRQ QU;(S RS T UTSR QRT=)US RS T UTR QRSV=*T RS T UTR QRW?+US RSTUTR QRW?,SRSRST UTSR QRS?-SRSRS T UTSR QS?.S RQR T UTR QRS=/S RR TUWVTRQNQNQ!0RSRS T UW 0TSRQQ1SRSTUV 1TSRQ2RSTUW 2 V 3WW 8 VV VQQTVW WRNW R WRQPQS WNT WQQRT WNQTVRQNRTU  QNTWSQPNSTU VRNRSTWS QSTUW/QNRSTU SRQPQSW/WRQRQRSTSRQPQNRV9WSQP Q SRQNRTVWT9TNQNQRS RS TU9USNQN QRSRSTSTU7URQRQPQRSRSTSRNSUW7 URQRQNQRSRSRNRT5 VQQR QRSRQ RSRST5 SQRSRQRQRQNRTSV5 T RSRQR QRSTSV5 TSRQ R QNQRSTUW3TRNQNQ RQPRSRSTU3TSRSQNQ RQRSTW3TSQRQRSRQRST/TSQR QNPQRSQQST- WSNQRQRSRNQRST)QR SRPQRSRQRST)S RNQRSRQRS+SRSRQRSRQRST+WTRQR S RQNRT- TRNRSRNRT-SR SR STSRT- SRQRSTSRQS-WSQRSQT/ TQNRSR S5TSRNRSR SRRS T7TS RQR SRNRS TW;WTSRSQR SRSTST;WSRNR SRSRQSRSTW; S QNRST SRQRTSNRSQRV=!S QRSTSTUTRSTSV="SNQRST UTUTSR SW?#TRNQRS TUT SNV?$VSQPQSTUT USTS TSQNV?%WTRPNQSTUT U TSTSRV?&TRQNRSTUTUTRST SRNRW?'TSRNNRSTUTURSTRNRU=(TSRST UTSTUTVW;)T SNRTU TUW5*WUSNRSU+WRSTU,TNRT U-VNST U.WST U/WUT U0W U 1WU2 8 8 8 8 8 8exult-1.2/data/bg/hoods.shp0000644000175000001440000000352510013004435011316 U ...- .   .. ,... . .......- -..- - . --. . -  ... - .. . . -. . . .- . .. % .-- -# - - -. - . ..- . --.- ...- .   .. ,.. . . .... ..  - . --. . - ... - .. . . -.  . . .- . .. .-- -#- - -.- . ..- . --. - pqpopopop qsspopssspr qq -qp  q qsp rsoq ss prs pops ops'oros oq% spprp p# rprprrppqr rpqrq ssr s r rsq po qoooponoonnnnon nopnqnnqon oqq qop ىoq pnp p ppqpoq nqpnp qnq opq  qpooq nqp؉o'n ponqnp'pooqpo opqp#opopqopoqqoppq qp q pqpq ppexult-1.2/data/bg/musket.shp0000644000175000001440000000310710013257045011515 G >@u u~ .}~t}| }{~ ~z}z{ r{~ r{z} |z{ r{~ r|z} r|z{|{~ u  {~ r|z} r}|z{ {~ r{z} ||}z{ {~ {z} ||z{ {~ r{z} }|z{ {~|z} |u  {~ || z{ s{~r|z} }|ܜz{z} |z| z{ r{~ rz} r|| }z{~|{~ ~~~ ~u܏ u u u u uu uu u u uuu u u u    G@ ~}~{||{||{}~r|{}r~|{}r~|{} r~|{} r~|{} r~|{} r~|{}  r~|{}r~|{r~"&"'#(#) #* #+ #,u#-uu$.%/%0u&1u&2u'3u '4 u(5(6u )7*8*9u *:u+;u ,<-=uexult-1.2/data/bg/greaves.shp0000644000175000001440000000250707504111152011643 G   w | x zzz   yzz~{~xxzxzzxz| zxzzz xz }} }zx xzxzz } {~  |{w| x|}{|{ww~ ށ{xw| wy|yy|wz{x~wx  |x~} {y~|w|  yw{~{~ |w{~  wx~|~}~|~ x|~w{~|{}~ {|{wzwy{} ~|wy {|  |    zv  zz  zyzzzxzxxzxzzz xz zxz }zx xz }}xz z} } z~| ~z~z |wx ~zz{~ xwx{|{zz| ~xwx{ ~|zz}}|xz y|zz{w~|{z~z ~|zwzy|} {z~|zy zy~ {z~z}y~| z~}z }{} ~z}   } exult-1.2/data/bg/firewand.shp0000644000175000001440000000146210011537040012000 2 P$$%% #$ $ O O O O O O O O O O O O O OO  $%#% $O$ ~}|zxO  ~ O |~ O ~ pO  rnpq   p"p rnp sp"q  pnp  OrqO O  O  O  O  O  O O O Oexult-1.2/data/bg/fem_av_face.shp0000644000175000001440000000451407331266364012440 L 8A    "$$&&Ÿǎ(**&     Ÿ      ݓssuuݒutsuuuuts-..-.u޿.ϒu ܒ..u ܿ. u ݿ.u"s. uu$us.uu$ݼ.u&ss.ݓ(sے.u(usݓ-(-..u*usu...uu*uݓϿ..uu(uݓ..uu uuu uuuu uu u  uusuus-..-.޿.ϒu..u. .. ...-(-u.Ͽ.ݓ.. uu u u u ssޓuuuݒtݓuuuuu uuusݓ .u ߓu uu ߅. uu u. uu"--. uu$-. Ͽuu$u. ,u&ߓ u(uu ޅ(߅ uu*߅- ޅuuu*߅u uuu(u߅uuu- Ͻuuuu uu uuuu uu u  uuuݓuuuu uݓ .uu uu. uu. u-. . Ͽ. , u  u- u uuu- Ͻuu u u uu uexult-1.2/data/bg/spiked_shield.shp0000644000175000001440000000161407365306377013040  ## # #'###+## /###3# # }7 #}#vy#7 vyyv |; yv| ; # =#? #~ ? ~xy}vy?v{~xvyv|?yw| }{yv|? ~?  ?; vy;  yv; xz 7  yxv| 7   3  /   + ' #exult-1.2/data/bg/iolo_face.shp0000644000175000001440000000127007331266364012141   ~vvxv~yvxvxvxxvwz|~vyvyvv|}|xxv"vxx~"y{ywy$y|yyvvyv}$~|yv{vv||~vxw"y{~v{$y{~{v}$y{~{v {z~~v{}yyvvyv{{}y~~yvy}{{vyvz|{vyvwvvw|~zvwvvwyx|~zvwyyy ~|y~ }|{y|yyvv~|yv{vv||~{{~{~{z~{}yyvvyv{}y~~yvy}{{vyvz|{vyvwvvw|~zvwvvwyx|~zvwyyy ~|y~exult-1.2/data/bg/mr_intro.shp0000644000175000001440000003113007365611341012044 X2\! *(3S   S SKRRS SSO ; S   S   ۷ O  ܸۚ O ᘽ ۸ O  ۘ O ᘙܘ O   O  ܚO  O   O O   O֮   OծޚܙḚO ծܙ˚ḘOծ0ṭݹܮO֮  Oۘݚ O ֮ۚڷٷ۷ۙۚO՚ܘᚸO՘ܘܙO  ♘ۘOۚᘙOܙᚘO ֘ᚙۘᘗO! ᚙ ۽O" ۚܡO#  ۚ  O$ܙ ܽO%ܽ O&ա߽O'ᠡ ⡟O(ᡟ ᠟ S) ߗ S*  ᠡ O+OS,  S-S. S/ S0  S1 S2  S3S(3S   S SKRRS SSO ; S 7 S   O   O ⚙ O ᙘ  O Oᘙ O  ♘O  ۙ O ۚOO ߚ ܚO֮   Oծ ߙO ޘۗۚO ᘙO ᚘO  ۚޙ O  ޚܘ O ᘚ O՚ۘݙO  O֚ޘܚ ޘ O ܻ ᘮO ߚݙ♮O!  O"ޙ O#  ᙚO$  O%՚  O&ա O'  O(ծ S)   S*  Ὗ O+OS,  S-S. S/ S0  S1 S2  S3S(3S   S SKRRS SSO ; S 7 S     O    O    O ܚ O  O&ܚᚙ  O ܚ Oծܙ  Oܸۙ O  Oծᙚۚ OۘO՚ߘ  O ՚۶O ܚ O֮   O۴  O֮ٲO$ծܘ Oծ  O ծܘ  O  O O ֮ ܘ   O!  O"  O#   O$֟  O%՟ O&ՠ ܠO'՗ ܘ  O(՘Ի  Ժ˚S) ݻґ S* ݻ  O+OS,  S-S. S/ S0  S1 S2  S3S(3S   S SKRRS SSO ; S  S   O   ʯ O ̽ O ̽  O ̽O ޘ ̽ˮO֮ ᚙݘ ݙO ݘO ݚOܘˮO  ܘˮO  O ܘO ̚ ̯O  ۘOֽܚ Oܘ ܚ O㽘  O ݘ O㚘 ܙݙ O ݚ  O  ᘚݘۘ Oݚ ܘ O ۘߚܙ O!ۘ O"  ܙ O# O$ޘ  ̽O%ܙ˽̽ O&ՠ ˡO'ՠ 㡠O(ՠ ܘ㡠S)  ܠ S* ݙ   O+OS,  S-S. S/ S0  S1 S2  S3S(3S   S SKRRS SSO ; S 7 S  7 O ; O   O -  O  O   O  ̽  O   O   O  O ծ  O֯ -O -⽯O O  O   O ܚ Oᚘܸܙ⚻ Oս۸ۘOս  Oᙘܘ۸ܚ O$ᙘܘ ۘ Oᙘ ᚙ O 㚙 O!  ̽ܙ O"  O#  O$ O% O& ՚ O'˽  O(ծ  S) ʡ  S* ࡠ O+OS,  S-S. S/ S0  S1 S2  S3S(3S   S SKRRS SSO ; S 7 S  7 O   O   O   O  O   O    O   ⚮O O  ܘO,ծڸڸ ܘO֮*ڸڸܘ۷O  ڸ ݘܷO ♘ݘڷO ۸ O ڸڸ O ڸۘ  O֮۸ƻ  Oծۚݚ۸ޚ Oծȭٸܸܷ O ծʘڸڸ ڷ O ܘ۸ O ۚ O     O! ֭  O" ᚘ会 O#ˡO$ ֟ݙ⠡O% ՟ޘO&  O'ՠO(S) ߘ S*    ݚ O+OS,  S-S. S/ S0  S1 S2  S3Sexult-1.2/data/bg/shamino_face.shp0000644000175000001440000000117507331266364012641 }  ,,,)(,)((())('&'(+ )-+ -+" "" " " "  ")   )((())('&'( )-+     exult-1.2/data/bg/bgfiredoom.shp0000644000175000001440000000363507256474661012354   -- s邸 s ݂ s ꂠܸ s s ݠܸ  s ܸ  s 鸠ܸ  s 鸠݂ ݂킠 鸠 ݂ s 鸠 ݂s 긠݂ s  ݂ s  ݂ s  ݂s頸݂s݂ s݂s݂s s!"݂#s $%݂ &s 'ܸ (݂ )s * +݂ ,s -$H s邸 s ݂ s ꂠܸ s s ݠܸ  s ܸ  s 鸠ܸ  s 鸠 ݂ s 鸠݂ s 鸠݂ s ݂s݂ s݂킠 鸠 ݂ s 鸠  ݂!s "긠#݂$s%&݂'s ( )݂ *s + ,݂-s.頸/݂0s12݂ 3s45݂6s78݂9s:;s<=݂>s ?@݂ As Bܸ C݂ Ds!E!F݂!Gs!Hexult-1.2/data/bg/hoe_of_destruction.shp0000644000175000001440000000453207256474661014116 Z K 4.      !                                                             ! " # $ % & ' ( ) * + , - .7P         !                                                            ! " #  $ % & '  ( ) *  + , -  . / 0  1 2 !3  !4 "5 #6 #7 $8 %9 %: &; '< '= (> )? )@ *A +B +C  ,D -E -F .G /H /I 0J 1K 1L 2M 3N 3O4Pexult-1.2/data/bg/caddellite_helmet.shp0000644000175000001440000000272007256474661013661      J IK JL KKM LJLTKMNMKLLONR KLK O RNRNMKJKR NORNRTNMKJKRN TRONRTNM KMK NRT7TRKNTRNM KLMNMTKRT3RMLRNTRNMNRTRKLR3RTMLTRTR NRNKLTR/TNRTNTRNRTMRN/TNNL T MJNT+TRLTT TMJNT#RTNKLKJLNTRTNL NLKMNTRTN NKLMR!RTN NKLNRTRNTTNKMNT!TRN NRLNT TRN TNRNT TRNRT TRN   JIKJLKKMLJLTKMNMKLLONR KLK O RNRNMKJKR NORNRTNMKJKRN TRONRTNM KMK NRT7TRKNTRNM KLMNMTKRT3RMLRNTRNMNRTRKLR3RTMLTRTR NRNKLTR/TNRTNTRNRTMRN/TNNL T MJNT+TRLTT TMJNT#RTNKLKJLNTRTNL NLKMNTRTN NKLMR!RTN NKLNRTRNTTNLMNT!TRN NRMNTTRN TNRNTTRNRT TRN   exult-1.2/data/bg/shoes.shp0000644000175000001440000000067710012544105011332                           exult-1.2/data/bg/orangedress.shp0000644000175000001440000000570107515126777012547 $  8  -)  )(   )'(# ( ()'(-%(%' (%'(-' % ') %'( +(%'$()('% ') +%'()(') /(' ( '() -/)( '() ) / )('() ) -  )('() ) +  )('() )  )(') ()-' )()(')('() -' )('( '() -' )(' () -'- )(' () ' ()() ' () () () + ('()( ) () + ( )() +-)($' (' (')-+-)('('()('(-+- ('('()('(+ )(' ('()( -- (' ('() ()-- )('()('()()(-/-)('()('() (-1 ( '()('( 3 )'%$'(' ('()3 ('$'(' ('()-5 )'$' ()(' ('() 5  ('$'( )(' ('(-7!-) '()(' ('( 9"-)'%'( ) ) ('$'( ;#-) ' ()  ( '(-;$ ) '() )('$');% ' ()  ()('$();& '()  )( '(-;'-) ()   )( ' ;() ()  )( '( =) ) ()  ( '() =* ()  ( '(-?+ ) ()   ( '(-?,)()()  )( '()?-)(')()  )( ')?.) ('(  )( '()=/) ('(  -  ( '!0()() - 0 )( '1)()    1 )('2()  - 2  3-- 8 ߒ-  )(+t )'$( (* ,)'&') (%'* (&'( '%$))'$(* t (%') *')* (') r)(')*+ /('()* t*)( ')* / )'( )* *)('&'() t9 )'&'( )('&'()* t9*'& '() () *+ t9 )'()()*)* 7 ('('&'()()*)('(+-7 t ('('&'( )('( 5 -('( '()('() 5 )'()('('('( *5 * ()('('('()* 5 +)(' ('()*.3*( ' ('()()* 3t+)( ' ('()*+-3 *)'('()('()*+/ )'('&'()(') - )'( '()('() t)(' ('()('() )) (&'()('(*+* ('()('()++*('( )('(*- *('()(*+- *('()*)(*- *('()*)(*-,)'()(*/ *($'()( )*5 )('()( )()*+7+)( ) ()* ; +*)()('( )()*)*+;*) ( )( )()( )*-; *)'()* )()*)'()()=!*)('()*)*( )*)*=")('()* +* *)()*?# ) () * + *)?$,*)('()*+* +*)()?% *('()*+ + *)*)()?&s*('()*+* *)()*)()?'t )('()*+ *)()*)*=( *)()* +*)*+ -;)t*)'(*+ + ,5* ,+*('()+ tt+ ,)()*+,,+()* +,--)* +,.-*+,/ +,0- +, 1  ,2t 8 8 8 8 8 8exult-1.2/data/bg/custom_sword.shp0000644000175000001440000000277210016753545012755  I!!   } } } { { { {~ z} }x |x~ {v~ zv} |zv} |zv} |zv} |zv} |zv} |zv} %& |zv} &)( |zv} )( |zv}&(|zvw(*|z* (%&'(*()(* (*  # $# (&"/  "$( $&   '*)    ~}|zx,+'&% ~ '%)*+)*' |~!%')**( ~ ')+|  '*  z|~+ }v|z| |v~ }z| ~                               ! " # $ % & ' ( ) * + , -./exult-1.2/data/bg/dupre_face.shp0000644000175000001440000000120507331266364012314  d )))( )""""" ~w~  )))()~w~  exult-1.2/data/bg/knife.shp0000644000175000001440000000074710011541532011303    ~ ~} }{ {z x x{ ~       ~}|zx   ~   |~   ~      {         exult-1.2/data/bg/triple_xbow.shp0000644000175000001440000000425710012544105012545  O !   } }{ ~ |} ~|{  ! #~# |!~#    ֎ ֒$+  ֒($ (, HH(,H H H H HH|HH H H|HH H|H HH HH HH HH H HH H !          ~  }  |{} ~  } {| ~}|zx   ~  |~ q  ~ op #qnpq5 ւp"p ~-rnpo|%֎so"q#֐op" ֐pn ֒rq +$֒   H$(   ,(   ,(H  H HH  H  H|H   H H|H H H|HHHH HHHH HH HH HHHexult-1.2/data/bg/death_scythe.shp0000644000175000001440000000556310011522536012657 s V A. - MLKLM SP9LI I J KME QN J I IJIROK J IMK)SPLK LQNM L MRO M  SPNM  QNM RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP Q QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN RO SP QN  RO !SP "QN #RO $SP %QN &RO 'SP (QN )RO *SP +QN ,RO -SP .7P  SQN RNP QNP NJSQN M JQNPKLM JKQNP!K LMNLJKSQN%LIJKLNMKJKSON)IIJKMNMK QNPI IJLN SQNIIJ SPNII QNOI QOPJIJ SRO KJIJ SQO  KJM SOP KJI TRO NJI SQO OK SOP MK TRO MK SQO MK SOPM TRO   SQN   SQO   TROP   SRO   SQO SOP TRO SQO SOP TRO SQO SOP TRO SQO SOP TRO SQO SOP TRO SQO SOP TRO SQO  SOP !TRO "SQO #SOP $TRO %SQN &SQO ' TROP (SRO )SQO *SOP +TRO ,SQO -SOP .TRO /SQO 0SOP 1TRO 2SQO !3SOP !4TRO "5SQO #6SOP #7TRO $8SQO %9SOP %:TRO &;SQO '<SOP '=TRO (>SQO )?SOP )@TRO *ASQO +BSOP +CTRO ,DSQOP -ESRO -F TSQO .GSOP /HTRO /ISQO 0JSOP 1KTRO 1LSQO 2MSO 3NTQO 3OR4Pexult-1.2/data/bg/magicgorget.shp0000644000175000001440000000033610012751274012500 u  |}x|zzI}} |}{}   |}x|zzI}} |}{} exult-1.2/data/bg/flx.in0000644000175000001440000000117710026506300010612 ../exult_bg.flx hoe_of_destruction.shp caddellite_helmet.shp magic_boomerang.shp great_dagger.shp gorget.shp magicgorget.shp cleaver.shp faces.shp faces2.shp amulets.shp bgfiredoom.shp fellowshipstaff.shp BGmap.shp defaultkeys.txt fem_av_face.shp male_av_face.shp dupre_face.shp iolo_face.shp shamino_face.shp greaves.shp spiked_shield.shp mr_faces.shp mr_intro.shp firesword.shp greencloak.shp greycloak.shp ring_of_protection.shp greentop.shp orangedress.shp bluedress.shp death_scythe.shp firewand.shp knife.shp starburst.shp hawk.shp musket_ammo.shp shoes.shp triple_xbow.shp pants.shp collar.shp hoods.shp musket.shp custom_sword.shp exult-1.2/data/bg/fellowshipstaff.shp0000644000175000001440000000506607261141140013412 6  =.     !  '                                                                    ! " # $ % & ' ( ) * + , - .7 P                      '                                                   ! " #  $ % & '  ( ) *  + , -  . / 0  1 2 !3  !4 "5 #6 #7 $8 %9 %: &; '< '= (> )? )@ *A +B +C  ,D -E -F .G /H /I 0J 1K 1L 2M 3N 3O4Pexult-1.2/data/bg/pants.shp0000644000175000001440000002127310013233104011324 "t u $tt t  t tsst srtsr r3 ssq srp3sqrpqssrqp 5tspqpqr q5srppqrqrp7&trqpqrqpqrpp7 rppq"prqppprt7tsqpqrppqrt9s rqqsstrqpq;qttrss;rt stsqp=tsptrstsqttrtrqrprtsqprtppq tsqp ِsrqrsts prs tr sprs! t t tsqsr tڄ  srpoqs tspqr  rs  ܒ  qqprpܒ rqstpqrttrst qrtsrqpqstqptrpstppqttr prtrt srpqsts rtstpr rtrts s opstrsrtsstst trqpr tqt tsqsttr tpstrsqs tpqrڑttq tsrtrs tsqtt r tsqstqr trqps t spt!rtss !st "tt "rqt #t $ sst &   sߟ uttۡtsݠs;ޡݡrۢ٢; s ٠۠= s&ݟtr֙ޟ=pppۃ=ݟrpprp st? sqsܟ?&۞rqrۡ?pq ݞsܢsr?ݢr؄ p۞? rq؄ݡߡݡ! ߢspquܟsrrqٛބܞ ؜  spsrt pׄڒu s! pׄ ! stpqr ܟtrqp tq  t stsܞs rܟprstڝtrqٟtrךߢ֙ܞpqۢ۟١t۟qrt : ڝtqp:ttp ܟ:rst ڝt:tspqל:۝st֙t:tp t tݞts֙:pqt:۟tڞp:۝ sٝt:t sٝs:s۞sٝ ts p: ۞qr!tښt: ! pם"t۞t: "ܞ t#tگ #ts$tܝt $st%t %t &ޟ&t &. u. .u.Ͽ...u.. .- u/ -.u.- , u3- -.Ͽ-,+u3- -   -u5- ,  , ,.u5-,  , , ,-u7 - ,  -  , , -u7- , - -.-   -.u .- , , .-  -.. -.. - ,+ .u...- , .u .-, . , ,.u-,+ ,-. ,  -. , + - ,--..-, + -- -.ϓ,-  -. . Ͽ-  , -.! .-  t -, u .    - , -u .-   .  ,u . .  Ͻ  u. .  +, u  .t.- , -u. -u- .- . &. u Ͽ  u.Ͽ--u-u- u9.- -.u- u;.   -,  .u;.-, ,  ,  u;u-, , ,  -.u= -, $ , , -- -u?  --.-, ,u? ,-.--.-,  u?.- , -.. - u?-   .-.u- , .u!.- -..- , ,. ..Ͽ, . u - . -, -  .-,  .- ,-! .- + .Ͽ- ,- .ϑ    .- , - . .  .-  ,. .-, ,u.  . , -..- -..-   ...  ..   ..- , -. -.-.- & u ::: 9ΰ:93έ9u:9ͫ5 :u:98 :7 9ΰ9879899ͬ8 9:989ͬ88 :9 9889ͫ899889u9:9889 98ͮu; :9 89ΰ:98 :u=89:::98 u=:::98 :?:9 .9u :9̈́:9 u 98 ΄ :989:8 :ά89u:9: :͑ :98ΰ:! :Ϋ t :9Ͱ: :9  :9ͪ: : 9Γ  :989 :ά  :9ͬ:9:9ͫ9::ά 9t :9ͬ::98:::ͬ:: ::ͬ :::89::Ϋ::έ::: :99::Ϋ9 ::9:::Ϋ9::: :: :έ: :9 ΰ:: :ά9::: :9::έ: :έ: 9: :9::: :9 :ΰ :!:: !: " : ":: #: $:: % : & u  u u:uuuuu: u:uu9u9t9 u:uͪu9 9:u 9u;u:99 9 u;u9899 8 u; u989u= u98 9ͬ99 8u= ή9:99u=9:u:9u?u98:u::9u?uή8:uu98u!u99uuͫͬuͯuu :u u9 u ά9u :9 u ͪ9! :Ϋ u 99 u9   u:ͪ9ΰ ::  u:99:9u:9u:ͫ 9:Ͱ ::ͪͰ: ::ͫ89: ::99:::::: ::::::9:::9::: ά9:::::::9: 9:: :: :9!:: !9:": : "::#:: # ::$:: $:: %:: &:&:exult-1.2/data/bg/musket_ammo.shp0000644000175000001440000000015510012544105012521 m c  rp rpr rp rqor rqpopq,exult-1.2/data/bg/hawk.shp0000644000175000001440000000313210012752762011142 Z.D =. ہr/t pڞqٟٞprـrqڞٛorpڞם poq؜oqqppspoqqurڟpםrܑs݌ڑs܏rsqtܐtrސpq޹ݠurq t u߅oڵttrבݵڞr غן tqк u)q ۠ q sqp ׅ~8 R  /rt ܁۞ppٌٟq؛r۶ڞqr؝מproۜqopp۞qqoqܠops؊ppڟrܶuqsrqsrsځ qprtt qru߹ out ۑtց ڵݑrtrڞڄ ׺آ qt q)u ۑ ؞ Ёq pqs ~7 P /rt ܁۞ppٌٟq؛r۶ڞqr؝מproۜqopp۞qqoqܠops؊ppڟrܶuqsrqsrsځqprttqru߹ out ۑtց ڵݑrt rڞڄ ׺آ qt q)u ۑ ؞ Ёq pqs ~exult-1.2/data/bg/faces2.shp0000644000175000001440000000366307256474661011403 u   } ononnonn~       ononnonn~       ݼ H{f{      ݼ H{f{         #     #    %    '        '   '   # TvTv                              TvTv      exult-1.2/data/bg/firesword.shp0000644000175000001440000000261007504111152012206  =!! 2 02222000&0&$0$02012012012012012012012012012012012012012*'012*'0120*'00'0$&*' *'*'*' '  W'* *'* /$ %& (&( *   ~}|zx V*'* ~ V* &$&' |~*&%&' ~ +*&%'' *&%'!&$'v|  z|  |v~ }z| ~                             ! " # $ % & ' ( ) * + , -./exult-1.2/data/bg/cleaver.shp0000644000175000001440000000130307256474661011646  Au~ uu߃{yzy|z{|}yuz{}~}zz~zxz{~yxyuz v|{w{~}yv{|~~x}~}}{ ~| }|u~~|z{u|y~|yuq ~}|zx ~ - |~߶- ~ߢ  rߢ  ߅pnp " rnp u  p"|y|! ropq~}{}# ݢo(~}z{| }~z} ~{z~| ~{wx~ u| xw}| |y|}  |exult-1.2/data/bg/greentop.shp0000644000175000001440000001436507514410114012040 $_S t?       %' + + /  / /  /  -   +  +  )'ߪ' ' ' ) )  %    ?      //  9*9  9 7  7 * 5  5 5  5  *3 3  3  / -* + --  +      #F                                    #F     u                               #Fu u   u     u           u        u               8                                                 #F                                 + )  '   '       #F      9                     3  1  //  '  !      exult-1.2/data/bg/defaultkeys.txt0000644000175000001440000000502307570007753012566 # default key bindings Alt-KP+ resolution_increase Alt-KP- resolution_decrease KP+ brighter KP- darker Esc close_or_menu right walk_east left walk_west up walk_north down walk_south KP7 walk_north_west KP8 walk_north KP9 walk_north_east KP4 walk_west KP5 center_screen KP6 walk_east KP1 walk_south_west KP2 walk_south KP3 walk_south_east Shift-right walk_east 1 Shift-left walk_west 1 Shift-up walk_north 1 Shift-down walk_south 1 Shift-KP7 walk_north_west 1 Shift-KP8 walk_north 1 Shift-KP9 walk_north_east 1 Shift-KP4 walk_west 1 Shift-KP6 walk_east 1 Shift-KP1 walk_south_west 1 Shift-KP2 walk_south 1 Shift-KP3 walk_south_east 1 Alt-right scroll_right Alt-left scroll_left Alt-up scroll_up Alt-down scroll_down home center_screen Del delete_selected Ctrl-right move_selected 1 0 0 Ctrl-left move_selected -1 0 0 Ctrl-down move_selected 0 1 0 Ctrl-up move_selected 0 -1 0 Ctrl-pageup move_selected 0 0 1 Ctrl-pagedown move_selected 0 0 -1 Ctrl-C copy Ctrl-x cut Ctrl-v paste F2 cheat_screen F3 map_teleport F4 toggle_fullscreen F10 show_endgame Alt-F4 quit Alt-Enter toggle_fullscreen Alt-1 sound_tester Ctrl-B shape_browser B useitem 761 # Show spellbook INSERT create_item -1 # Create last shape C toggle_combat SPACE pause_combat Ctrl-D delete_object E toggle_eggs F useitem 377 # Feed G useitem 675 11 # Use abacus Alt-G toggle_god_mode Ctrl-G change_gender H help Alt-H toggle_hack_mover Ctrl-H cheat_help Ctrl-Alt-H party_heal Alt-I toggle_infravision I inventory K try_keys Ctrl-L party_increase_level Alt-L skiplift_decrement Ctrl-Alt-M toggle_map_editor Ctrl-M create_item 644 -1 100 # Create gold Shift-Alt-M play_music -2 # Previous song Alt-M play_music -1 # Next song M useitem 178 0 # Show map Ctrl-P repaint P useitem 627 # Use lockpick Alt-Q quit Ctrl-R quickrestore R face_stats Alt-S change_skin Ctrl-Alt-S screenshot Ctrl-S quicksave S save_restore Ctrl-Alt-T map_teleport Ctrl-T next_time_period Alt-T cursor_teleport T target_mode V about Alt-W toggle_wizard_mode W useitem 159 # Use watch Alt-X quit Z stats Ctrl-Alt-G grab_actor Ctrl-Alt-P pick_pocket Ctrl-N npc_numbers 1 inventory 0 # Show inventory for Avatar 2 inventory 1 # Show inventory for character 2 3 inventory 2 # Show inventory for character 3 4 inventory 3 # Show inventory for character 4 5 inventory 4 # Show inventory for character 5 6 inventory 5 # Show inventory for character 6 7 inventory 6 # Show inventory for character 7 8 inventory 7 # Show inventory for character 8 exult-1.2/data/bg/ring_of_protection.shp0000644000175000001440000000063007504111152014073 @dt OOOOOOO   OO *    OO    OOexult-1.2/data/bg/greycloak.shp0000644000175000001440000000510107504115673012174 A /0 @    !!))AAAAAA  A   A A    A   C   C  C  A  A   A   A  C   C   AA   A  A  A C  C   CC  C  C   C!  C"  E#    E$  E% E& E'  E( E)   G*    G+ | I,| I- || I.| | I/ ||I0  ||I1 |  | K2  ||M3  | |M4|  |M5|  || M6| | |  O7| ||O8| | |O9| | |Q:|| |S;|  || <A< ||=|| =| > >|?|@      ~~ ~ # +   LJLuQMQu Q   ~ ~ ~ ~# ~ A~~  9~LJL / ~QMQ # Q  exult-1.2/data/bg/starburst.shp0000644000175000001440000000040610011546370012235                 exult-1.2/data/bg/amulets.shp0000644000175000001440000000331707504111152011661 #Ir  }      z|v|y |y       ) )         PPTP PTP}N| { |}        {|~z{}~{|~  ~           ~}~|~ {~~ |~}            exult-1.2/data/bg/faces.shp0000644000175000001440000000537207504114134011276 _9          !    !  l # iln %  n % jn  % RpRpn %  mknkgk ' onkjmk m ) onlinmkm  +  n ((lnp  - mkmn  /* pjijo    -   p    /                                l  iln  n  jn    RpRpn  mknkgk  onkjmkm  onlinmkm  n ((lnp   mk mn  pjijo     p           %) )%+)'%(%%(% (%(%!%(% + )%+'#+%)  %(,%.% %(%(  ) (''%') )'(% +  +( %   # !) !  !  )!* *%!%+  +%*! %% +! + % *%  *')  )  % $% $   %( *% % %+ + + +  % (% + )+%)  (%(  )(') ) +  +   )  *%+ + %% +*% *   uuuޓ.!uuu# u.uu%.u'$ki޾'uqklpru.u' uopuuu'$uuqyqxsu'uu luuu'ujlluu) u u+ uuuuu+uu+ul-u) .u'u uuu  - u-u uu uuu  uu uuu  u.u.ki޾qklpru.opuuqyqxsuu lujllu uul- u uu -exult-1.2/data/bg/greencloak.shp0000644000175000001440000000507107504111152012320 9 0- @    !!))AAAAAA  A   A A    A  C   C  C  A  A   A   A  C   C   CA   A  A  A C  C   CC  C  C   C!  C"  E#    E$  E% E& E'  E( E)   G*    G+  I, I-  I.  I/ I0  I1   K2  M3  M4 M5   M6  O7 O8  O9  Q: S;   <A< = = > >?@       # +   **u u        #  A  9** /   #   exult-1.2/data/bg/BGmap.shp0000644000175000001440000017337207312457552011224 ~feefPQPQPQPQPQPQ PQ PQPQ PQPQPQPQPQ PQPQ)PQPQ;PQPQPQ P PQPQ-PQPQPQPQ3PQPQ!PQPQ PQPQPQPQPQPQPQPQP5PQ~NPQiPQ PQ PQAPQPQ PQPQ+PQPQP PQPQPQPQP~] PQPQYPQ)PQPQ PQPQWPQ%PQ P5PN~NPN~PQ~PQ PQPQPQ PQPQ-PQPQ)PQPQPQPQ PQ PQPQ#PQ P7P] PNp~PoQPQ PQ PQPQ PQ P QPQPQPQ)PQ!PQ PQPQPQPQP PQPQPQP~PN~PQ!PQPQPQPQ PQPQ PQ%PQPQPQPQ7PQPQP%PQPQ P]pQPN~P Q PQPQPQPQPQPQ PQPQ PQ PQPQPQ PQPQPQ PQ PQPQ PQPQPQPPQPQP QPp~PNQPQPQPQPQPQ PQPQ+PQ'PQPQPQ PQPQP QPQPQ PPQP~ܫQNܪNP Q PQRPQN PQPQPQPQPzN P}PQ!PQ PQPQPQPQPQ1PQ P3PQ~ N~P ܬPQP NppPQMKzMPQ PQPNKzMP{}PL|~PQ PQPQPQ PQ PQPQ PQ PQPKz} PQ PQPQP PQP QP~QګNPQP p PNp~}zzN PQPNKz}PLK| PQPQ PQPQPQPQPQPQPQ P{ |}~}PQPQP PQPNpp]P~ ~PQPQpQPQp zzz{N PQP NK{zzzMQzN PQPQ PQPQPQPQ+P{yK|~}~}PPQp ] P~ ~ P~ QPQ }|yzy{NPQ PNKzKLzz{pN?PQPQPQyy|} PQ PP]P~  TNP~  Q"}~z{y{zy{N PQPNKzyz} z |pQPQPQ#PQ%PQPQP L}} PQP PNpNP~P~ rRS }zzzLMPQPNK z||z z{|~PQPQ PQPQ PQPQ PQPQPQP Lyz|PQ PNp~PQSRܬPQ  }z{y{zzz|PQP}{zz|q|{|K{pNPQ]PQ PNz|ة} PQPQ P~ NPQTS SqܪRPSRPS{ zz|}PQPMzz|q|}{pQPQ PQ PQPQPQPQPQPQ'PQPQPLzƛSQPQ P P~p q P| z}QP Lz|{|r |{}~PQPQPQPQPQPQPQPQPNzRPS }QPQ P P ~r T RPQPQ~yz{} PQP|r {{pQPQPQ PQPQPQPNzƛRP~NPR }Q PQPPQP rr PS~z} PQ P} r }Kz~PQ PQPQ PQPQ PMK PQ}P }QPQ Pت ܪ  rrRPS~{{}PQ P Q  |{QPQPQPQPQPQPQ PQPQ PNzz PQPQ}PQ PP QPQث ܫRPQ P~ PQP ~r r {z|QP Q~Q] PQ5PN{yz| P}QP P~  ۟PQP }P r {{~ PQ PQتت PQ PQPQ'PNz{}PN~}}QPQPPQP~  RPQQ {}PQ PQp rrr |{Q P QP N#PQ PQPQ PNzy}NPQ{z{NPQ P P~  RPSS yPQP~ |z{~P QتN PQ PQPQP ~y}}PRQ{z{P PQ    PQ  zPQp|rQPQ~NPQت~APN z} PNR|QP P Qp ~  RPQ  p}PQP~  r{P~]PNq Q PQPQ PQPQ PQ P ~QPN PQPPQ PQzƙ P }QPQP  {z~Pت]P~} PQPQ!PQPQPQPQPKz{ yRPQSyMPQPq  yS}{{|~Pث |zQ!PQPQ PQ!PQ P PQPNzK zƛSQS z} Pp rKy }| P~ |zQPQPQ'PQ PQ P QPQPQPPQ PKKzKzƛ S zy}PQ ۛ~zyzS|zSܫ |{QPQPQ PRQPQPQPQPQPPQ P~}~{ Kzz   zz| P rq~ z}۪}zS|{~PP RPQ PQPQPQ PPNP~ } }zz }  r z| PQ~z z} ٜ٫}zS {z{ PQNP~RQPQPQPQPQPPQ PQP}y   zz|PQ PSr~}}}٫ ~zSr {~ Pة~PQPQPQPQPQ PQPQPQ PQPQPPQPQP Q P}z}  s ܬ{yz y|~PQ Pت~QP~ S ~zS |z{ PQ~EQPQPQPQPQPQPQ P PQPNpp]PQPR}~ qr  |NPQ~PzS{|~z}S|y{|PثEDE PQ/PQPPQ ~ةSP  ܬr{z}PL} PQRQ P {z} }{}zS zz|}|}PD ER PQPQPQPQPP~ RP r rr r۟yyzzLz}PQP&Q٩{zzƚS}{}|}Srܪ|{PNP NE QPQ PQ PQPQ PQ PQPPQp ܪTPqr |}y|} PQ PL{z|zǙ |S|}K|PN}nED E PQ PQPQ+PQ PNPRq  ڝ {zz}P}PQ P(NLzKzzƛS}|}|S }zL{L{EERPQPQPQ#PQ PQPS P   ~z|~Pp|zzz|z{}S {{|EEpQPQPQ'PQPQ PQPNSP }~|~PMLM Pp~zzz S}Tz{|E ~QPQPQPQ PQ PPN  RPQ  ~~|z|QPMLMzzNPp}z z}SqT~{|  Q%PQ3P PQP~PQrܬz {S{z|P|yzKzz{Sr}| EDPQPQPRQPQPQPQ%P PQ P~SPT  ~z|S{z{| P p}K z{S |{zo QR  PQPrR PQ PQ!PQPQPPQ PQP ~RPQ z| S{z y{NMP}{zyz{S| {zopRPQTSR~PQ PQPQ+PP~ PT {|S{zz{P p}zzyتS~y| zz pR P T~ PQPQ=PP ~~P~ RP Tr Kz{S z{P~| z{S|  ۫z{opPQQP N PMN PQPQ PQPPQ PتכRPQ  Kz{{ S{ z|P(p}{z{zSz| S{K{pQREPE PMyM/PQPP N R  zz{{ {z|NQP~}{z${Sz} {pQPDE~PRE~P MzyMPQ%PQPPQت r S  { z{z{  }z|P~}{}zyةSz   {z{PQPEE]PMzy~PQPQ PPQP~    y{z{z{z~P~}}zSz} p{z{ ـp ~DEQPMzKzyM/P P r Kƛ }q{z{   z|P~~y ~Sz   o {ooNPMz zKz} PQ PQP P  T  |zz~zzz{K{ QP }zS }  p oo ppQPMzyMPNPQ PQP P~ rS |z z}{z{}z  pQ~ }zSz} 3oQ P Mzzy}'PQ P~ ܫRܬ{{}z{z zzƛzz{|zz  }yzSz}  ooooN PQ}zz Kzz|%PQ PNp ܭ R۫{z{|Kzzyzz{|Kzz  }yzS|}  rrrr {o ~PQPNz zKz}NPQPQ P~ܐ  Sܪ~{z{}zzKzzzz{|zKz  }KzS} {{ oopNQ PQ}z yK}NPQ PQ PQPQPNp S{{}Kzzzzz{~|yzKz }zzS {zy {K{o~ PNz}PQ PPQPܬ S {zz~ zz z|}zzKz  }zKzS ہz z|ךE~ PNz~PQ#PPpqܬ  R{zz&K{~KzK{Kz{zz{~}z   }S ۪}zKz{ ooQRQoED~PNzKz}~}zMPQPQPQPQPPQPQ~rܬ S|zzKzz~z{z zzz{Kzz||z |۪S}  zzz{ o DE]PNKz}yz~ PQ PQPQPPQPQ P Qة rS KzzzK{~zyzz{zzz{}~} |RSS| |z{|}|a DE~P MzKzz{MPQP PQPQ~S}z z{z|zzzz|}{K{  |S |z}{z|}QoPSQoENPMz}zKzzMPQP PQ PN~ SR~KzKzz| |} | }|{ S |z|{z|}PNq E~P~|z {z|PQP PQP ]ܪRSMR}|zKz Ky||ة|qq| {{ S{|{ƚ ۫ {|{z|~PQ ooE~ PNz{| z|}PQPQPQPp TzNRS~| {Kz{y|q  { z{  az}۪ |y|~PQooooDEN PMz |z|QPQPQP PQP] rzzMR~S~{yz|~{z TS|z{||z |~QP Noooo opENP QPMz| z|PQ P!P] s} {PQPMzzz~Kzz| r Sz{~{z{~PQoךoo DE]P }MLz|{pQPQPPQ PQ PN~p ܫzz|PQMyzz{r}zzz}r S}} |yz{~PQooP` ooQPNz|}{PQP%P~QN~p ܪ~z{NPPMzKz~ڍ~{yzz} QRSz{}{NQPQP  o ~EPMz {|~PQ PQP#P ~؜~ z{PSPMz { S"Sڏr~yyz}RRPR {ƚT}z{NQ P~o R  pP~~NP}{Q~PQP PQ PQP~  z{z{NPMzz ~~~y z{۪PQƛz|}zN PQ~׊ooq ׋oP~P}PQpQ~P%Pح r{zz{{NLzK{ }~zy  rSP Nz{|T }{NP Qoo p؜P~PQNP~QPQ PQPQP~P~z zKz {{ ~~zyz}QPNz|T}KzN P ~poמQq؛o ooQ]!PNP~z~PQ PQ PPQPQpP~ة zz z| r~~zyz}r۩QPNzz }}zNP ~o RP poPQ P~~PتzQPPQPQ~P~ةzzKzp  q~Ky}QPz|R}zKyNPNooN~pPQ PQPNp~zPتz|pQP PQP~Pr zz{zK,q~ ~yzP S TSQRz|STS ~zNP Nooo~P ~po~!P o~z~P Kz|QPQPQPPQPPzzKzKzz~ ~$~zRTzƚbNQ~ P Npoo oo~P~o~#P~Ky}P~zQPQPQPPp~Pz zzzzSSr~yR Sz|S PQP NoNP׊N/PQp}zMPN z PQPPQPQp ~ P~z z~ ~zTrz{Rp PQPN QPQ~PQPQ PQP~z~QP~zQPQPPQ PQ PpP]N]zzz z&~qpٛ~ }zTrr{{ PpPQPNoQ PoNPQPQPQPQP~~zNP~z}pQPQPPQPQ pPةzz z ~~  ~ُ"R}zٛrz|PQPQPQP׋PQPQ PQ PQP ~z~Q P}PQPQPQP PQPQPQPQPتzz {ٜp܂ܐܫ,NPMKzrrۏ{|PQPQPQPQPQP~}zN P NpQPQPQPQPPQPQ PNPQP {z{~rr p}rNPM{}r rr{z{PQ PQ%PQSPQPQP}NPQPQ PQPQPPQPQRsR PQPث{zz{} r,r}rTpQMK{} ہ{z{uPQPQPQPQ PQ PQPPQ PSRP~ |Kz{| r~~q r p]PM{}rrz|}#PLz} PQ%PN%PQ~pPQPQ PQ PQPPRrQPQP  Kzy|}rrqpqqpqqqR PMKzr r|| PQPLK|PNK{NPMzMP~ pQPQPQPQ PQPrSPQPoz{| {~qqq؝q ~PQQPLzrrr||} PQPQP L|~PN{Kz}QPQPQ PKz}PQP~pPQ PQ PQPQ PQPR}rsRN Pت z|}~zrq~qq~P~pQPLzrr{ {|}PQPLz} PNLKy{zNP}z|}PQPQP~PQPQQPQPP RrPQث|}~{ z|r qq~~ P~QPLz{{{|{|~ PQPLz{{NP NLKzz{zQPLKN P}|PQ PQP~rpQPQP QpQ PQPQPPQ Pr RPQث&{zKz~~r ~~P]~ P~ت P}{y|{|{zy}Q PQPN| {zMLzKzKz{zyL|PNz~ P~P  P pQPPQ PSbsRPQث ~{z{"~q~QPN~P ~N P}| {z|{z}#PQPQ{z zzKz KK z|Mz{NP~  PQNPQ PPQPRbrNPQت|zKz| ~~r~qQ+PQ PQN{QN{{NPQ PMzz{zz{ z{}{| {~|NP~r؜~P~qPQ PPQPQPQRPQ~~z{~~~~qRQ PQ+PQPQ{K}'PMzzzz{z{|{z|}{|{|~z|NP QPor~PQp~ PQPQPQPQPQ PRss rڐR PQ~z$z|~~؏~qQRPQPQPQPQ{}PQPNzzzzzz{K}~zyz zz{MNPQP Np ٛت~NpN~QPQ PPR ېPQPQ | z {~~~SRPQPQPQPQPQPQPQ P Nzzzz{}~{yzz| PQ P تrة~ PQPP QsrrPQPN|K{~r PQ#PQ+PQPNzzz{z ~{z zzz|P Np q~PQPPQ PQRsRPRSNQPQ|z{  NPQ PQPQ PQ5PN{zz{z|} z{ z{z|P ~QتN PQPP Rsr QNRs PQ{z{ ~} ~ PQPQPQ PQPQ PQPN zz|~z{{ zz}{|P prq ~PPQ sbsR PQ |zKz qrq~'PQPQ=PNP Nzz z|۪~|zz|P ~ PQPPQ PQPRܞېܞ PQ{ { PQPNPNPQ~QPQ;PNyMPQzzKz{{ ~{zƚz| P ~  QPPrېrsRPQPN|{ rq~ P pp~PQPQPQ3PNzNPzzz{SP ۪~z{z}~{z{P~ NPPRrs P~{{ QPQPNP~~ PQPQPQPNy~Pzz{SP~zKK{}QPR{|N PQP PQ P PQ PR rڐq ܐrQPS|{ت QPQppNPQP~PQPQPNzzNPzKKz${SPQ~zzKKz} P~NP~ r~PPQssQP~  p PQppNPQPQPQPQPQPQPQPQ} y}~z z}P}KzKzz}~QPQ Pجrq ~P PQ PQs srܐbP~ r P QPQNp~PQPQ PQPQPQ PNzz}P~{zz{QMz{Kzz}Q PL| PQ P~rr~PQ P PQPQs rssP~ܭ  rQNQ Pp~PQPQ PQPQPQPQ PQPQPQ}zzMP~zzz{QM z}Q P {|~{K|Pتrp~PQ P PQPR r QP~{| rRQp P QPQPQPQPQ/PQ}KMP~}~{z{~PN|Kz}Q PK|{z{Pr  ~QتNP PQPQs PQPQ~ {}rS r PQ~PQ PQPQPQ PK}#P }yM P~}PN}Q PQz}}{ PQPجQPQ P  PQPQ PRs  PQP~z| S rrNP qqPQ PQ PQ PQPLzK|PQP}zz}!PQ PQz׊{ PQP~pQ PQPQP  PQ PQPRsP~z Srq~Pت~ PQPQ PQPQ P NPLzzKy|PQ PQP}~!PQ P}}PpN PNPQPPQPQRPQ P~|| S}{ r۞ت PQPQPQ P Kz{y{z| PQPQ!PQ%P{z~P ~~QQPo PPQPQP~|}~Q}z PQPQPQ PQ PLzzz{z}PQPQPQ PQPQP|}{}P ؏rPQPQ PPQPQ PQ PQ Pzz~Pp{z Sr PQPQ PQPQPLzzKz|}{y}PQ!PQPQP}P r QPQ P)PQPQPNpz|RP p}y|rp PQPQPQPN|PLzz |{y|}{yM|PQPQPQPQPQ!PQP~ ~PQ)PQPQP~||}~P}z{zrqr PQ PQPQPNLyLz|q Kz| |Ky{PQPQPQPQPQ%PQP NPQ PPQPQPQP~}zǚRP{y|۝~'P ~}{z|y{ |{|{zMPQ+P~N1PQPQ۞r]N~PQ P%PQPQ{{}qQPMz|{z P~pPQP(p}z|{yةq|}}yMPQPةN7PQتrP ~~PPQ!PNzǚqQPNLz~y} P ~ P Q P~}z ~|rr}{zQ/PpN'PQPQ؝ro~PR]PQPQPQPQ PQPNzƚNPMz~{yPPQPQp|z~{|r }}yM PQPQ PQPp~RPQP~pP~~ PQPQPPQPQPQ PQ PN{zƚ~PLz{~yT P NppQP~|z{~  q}KzN PQPppS5PQتQP~P~Q PQP-PQ P QKzǚQPLz ~y}~ PNpPQ P|z }{NPQ'PpPQ!PQPQتpQ PQpQ~QPQP9PQ{|qQPMz~z z}~QPNRPQPQ|z&pة}z{NPQPQ P~~PQP Qت~ P~ة~PQPPQ PQPQ PQPQ PRKz|N~P|{~zyz}~PNQPQP|z{qrQP~|{N)Pq~;P a~~ P~QPQP)PQPQz |Np~PQ~z zz۞QNp~PQp|Kzr~ PMz{NPQ P~q~?PQ~PP ~r~PQP PQ/PQz$|N~qPכ~۩pQPopNPQP~|zr~ ~PQPM{PQ PQP~NPQ!PQP~pQP ~ PPQ PQ PQPzƚN]Pp~zyz}rP~NPQPQ p|Kz~{rPR P|{PQPQ~PQ!PQP]QP~r~PQPQPPQPQ%Pz|~QNPp~zzz}~PQ}|z~z rQP}~'P~ ~GPQpQPpQPQPQPAP"z~qNPp~zƛqPQP ~|Kz QSQPN~ PNP~ PQ PQ!PQPQQPQpܪ~ P PQPQPKƙ~pQNpܪ}zzƛ ~PQ PQ }zy~NPQ}zNPQPQp rPQPQP ت~ PQP! PQPQ PQ PMP~z}NQPp~zy~PQPQ}zyqQPQN }zNPQP~ =PQPتpNPQP"!PQPQPQ PQzMPK|QPp}yzy} ~p~PQPQp}z}zQP ~zNPQPQ  ~PQPQPQ PQPQPRPQP#PQPQPQPQPQPQPQPQ~}NP ~|QPQPQp zKzƛqPQPQ PQPQp]QPQ}zz PQت|zNPQPQ PN~PQPQ!PQPQPQPQPQP$PQPQPQPQ PN P}pQ oQPQp zyy} r~PQPQPQ P~ }ƛ pRPMPQ؝}z}Q PQP~ q~1PQPQP%PQPQPQP}QoRP zzƚ  ~ P~PQ PQ}~z {K|P QP؞} PQ P q~CPQ PQ PQP&PQPQ PQPQ PQPMP~ PQ}z{z rqq~P~PQPQPQ PQ~PRQ}z {z|~P QP|z{Q PQ P ~ت~PQPQPQPQPQPNPQ PQ'PQPQPQPQP} PM PQpzz qqq~P~PQPQ PQP|}z|} PMz}QP~Qة~PQPQPQPQ P QPQpN PQPQ(PQPQPQ PQPQP}|}~P~PQNP~zzƚ rq~P~PQ)P |~ PN|}| PQPQPN~PQ]PQPQ?PQP NpQ PQPQP)PQPQPQ P}|MP"ت~PQت|z|qqq~P~ PQ PQ1PN}|PQ P~ ]PQPQPQPNP QتP*1PQP}|}PNpPQp| } qqr~P~pPQ PQ PQ'PQ PQPQPN ]'PQPM}P QPQ P+PQ PQPQPQPQPQPQ P~PN}~ Pث  qqۍqPQPتp PQPQPQ PQPQPr rAPQy}P Q~|PQPQP,#PQ)P} P~|}qqq~SPتp-PQ1Pr ]?PM}PQzpQ PQP- PQ-PQP ~QPQp {rٝP ~~_P~q~PQPQ PM{}PR{zpQPQPQP.PQ PQ PQ'PQpPQp ƛڪٝ~P ~p PQPQPQPQPQPQP ~PQ)PQ PN{~ P{{]PQP/PQPQPQPQPQPQ~ P}~P{ܪqq QPNppQ'PQPQ PQPQPQ PQPQت r~'PQPM} PQP |KzPQ P0)PQPQ PQت~ P }QPQP~  qq~PNpPQ PQEPت ܪةpN PQPQPQPNz}PQ PQ|K{QPQPQ1PQPQ PQP~~PQP}QPQPrqqۜ~P~PQPQPQ PQPQPQPتrN~r ~PQP Nz}P |{~PQP2 PQ-P~{~ PQ PNqQP NpPQ PQ PQPQ PQPN~PQ؜pQ1PN}{}PQp{z~ P3 PQPQ PQPQPQPQPQة{QPNܫqqqQPQ~?PQPQ PتQP~ ~PQP QPNp}NPQP{zQPQPQ4PQ PQPQ P Qت|QP ~ ~QPQPQ PQPQ PQPQ PQP~PQp Q#PQ P zzQPQPQ{z{~ P5 PQPQPN}PNppQ PQPQPQ  PQ+PQPQ+PQp q-P ƛ P~|Kz~PQP6PL{PQPQ PNp~PQP ~oPQPQP -P~} PR|z{~PQP7QPNKz{~PN~PQ PQp pQPNP~z  PQPQPQ!PQPQPةPQPQPNל} PR|z Kz{~PQP8PQP Lǚ~PQP QppQpN PQP~ƛ PQPQPQPQ PQPQP ~p+PNz}NPR|zNPQP9PQ P N{|PoNQPQ PQQP PQPKy} PQOPQPQPQP rٍ+PMzP~|zQPQP:PQP~z|pE QP~P~QP pQ Pz} ~ PQPQPQGPQPrq~PQPNM zƚpPQp~ P; P{ NpNPQp~P~Q P N~PQ P~z} /PQPQPQPQPQPQ P~~'P MzQNzz}P~|~Q PQ< PQ~~PpNQPQP~NQN~ppQP~z}p~p~ PQ PQPSPQ%PQ PQPQ PQP~p~PQP(MzKz}pQP|{|}QPQPQ=QP ~p] PQ P~P q؛ٝRP~zKz}pQNp PQ PQPR'PQPQPp~~QPQPQPQPQPQPMzKz }~{K{PNPQP>QPNpPQP~rqpRQ PQPNz} PNp~;PQPQP ة~p~ PQPQ PQPQPMzzz }{}P? P~QPN P~P~rpQPQP Nzy} pQP ~PQPQPQ PQP QpqPQ PQ PQ!PMKKKz}z z{~QPQ P@PQPRQPMK{NP~P~pNP Nƨ pQPQp~PQ PQ PQPQPت ~PQPQPQP؛|z{}}|}zƚ }{pQPQ PAP~p PMz|}PQت~P؏  PQ P N}|RPN]PQPQPQ PQPQ PQPP~PQPQ PQ PQ PQPQPQ}zzyzƚ z{}] PQPBQP~QPM,|PQשqr~P~ NoQPQPQƛpQPQ~PQPQPQPQPQ PQ PQp~Q~PQPQPQPQ Pp}z|q}{}z|~ PQPCQP~8pzzNةqrq~Q~rڛ~PNƛ p Pت~PQ PQ PQPQPQ PQPNppPQ PQPQPQ PQp{z{|q z| z]PNPQPDP~|{|pq rR ڛp~] PQP N{pPQr~P~~P~PQPQPQPQ PNpQPQ PQPQ PQPQ Pة}{|z{z{~P ~~PQPEP ~Dz{ PQp PQP N|{|P~ܫ~PتP~PQ PQPQPQPQPQPQ PNp~PQPNL|%P~} {rq|{|K|P~PQPQPFPتEz| pRPQ~]PQPQPQzƛp P~~P~ة~PQPQQPQPQ P R~PQ~QPQPQPQP NLzQ PQ PQ P}{~q|{}{zM| PGP~D|QPQ]PتNPQPN{|pQP~pNQ Pت]PQPQPQPQ+PQ PQP NLz{zMPQ PQ P~~{ Q ت~{{|~PQPQPQHQPت} ~Q PQتQ~QتNPQ PQ{}p P&~pNQ~جܩQלQEPQPQPLzyM!P~}|~ P QqPN zK{PQPQPI P PQ~NQةN PQ PN{ǛQP$~pNP~Qت ~P]ל PQ PQPQ)P LzKzKzyNPQP~Q~QPQPRSPz{~PJ P NP~~Q PQ~PQPQ{}~PQNP~ P~QNp~NP~Q~PQ PQ+PNMNPLz{zQ~~)P QSQP{zz|PQPQKPQPEP~QPQ~P~}RPNQ}Q|ש PN~p P~ ~P~ة;PNK|PL z{ zpP~QPNPQ z|QPQ PL P~E }{~QتP~{QPQPQ P N~pQ|Q~QP PQتP~ %PQPQ PQKz|PLzzK z{ ~P~|NMyN PQPKzz| PQPMQP~تE}z P~ }+P~PQ} ~QP؜ PQ~P QלQ~ PQ#PQPR{ zKzKzz  PQ P ~}zyN PQKz{z|N PQPQN PQpDE{}zKzP Q}RPQ PQP|ة~PQ؛P~ p~] PN}PNPR{z|~|zK z p] PQP~}zKzNPNKzz|QPQ PO P~DE{zyzyzzQPQةpPQ PQ PQ PQ} ~PQ PQP ~q rpQPL zPQ P ~}؝|zz ]P}yKyNQKz| PQPQPPPQP~E|zpQPQ~QQ PQ+PQrqP pNPQP~  rPLzz{P NPQP~}Kz~PQPN~}zKz~ z|N PQPQ P ~EDE |zKzy#PQ PQP Q}|~}~ P~ pP ـ~pPK z zN P~}Kz PQp}z}|z K K|pQPQ PQRQPE }zz zy~PQPQPQ PQPQPN~PQ~}~PQ}| PpPzz KzzyN P~}zpPQPQ}{zz|pQ PQ PS PQPNppp|z zQ PQPQPQPQPQ PQzPN r ~pP{zKzzzz}P~  ~KzrpQPQPت}~ {zNPQ PQPTPQPQPQة}zz z}Q PQSP PQPR P~ܬP~{ zKzzNP~ٛ}zypQ P~}zzNPQPQU P~QP} z} PQPQ PQPQ PQPQ PQ P ~rSP~ ܬpQPLzz z{zNPُ~zP QPQp}Kzzƛ~Q QPQPQ PQVQ P ~EQPQت} zypp PQPQ PQPQPQ PQ P~p ڜ~ P ~pPLKzKKKzN P~ q}z}pQ Pp}zyz}}zp~NPQ PWQ PNQPp|~|zQ~pQ9PQPQPQPLz~PQ~QPz{}QPQP r }QPQp~ت~zzyzNPXPQ P ~QPNp|~PN}|yP~PQ PQPQ PQP~zz{z{z{~P~ PQ P K{q PQP~r  pQPQPQRQPQ؜}z}~}yzpPQPYPQ P~PPNz}~P~oPQ PQPQ PQ PQPQ P R}|}{{Q~ PQP}|rR P QPQPNrq pQPQPת}~}z|~Q PQ PQPZ PQP~pQE}PN|PQ PQPQ+PQ P QR~QP~| ~pPQPQP~QqrRQ PQPQP~r ~Nت PQPQPQتQPN} |Q PQ P[ PQ PNQPQE~P }WPQPRPN ~PQ PQrQ PQP~r~PQp~pQP QP ~PQPQPQ P\PQP Q~P~QQPQPQ#PN|}QPQ PQpqQ PQP~ ~ PpQP~pQP QP~qp~pR PQ P]P}]PQQ PQPQPQPQPQPQPQ PQPQ PQP NةQPQ PPQP~rq~ PQتrQ PNPQ PQ~P~QP]~NP^PQPQ}PQ+PQPQPQPQ PQ PQQPQ PQ PRPQ P] PQPQ~QPQPQ~Q%PQ P_PQ PQ P wPQ#PQ PQ#PQPQ-PQPQPQPQPQPQ PQPQPQP`PQPN~PQPQPQ PQPQPQPQPQ PQPQPQPQPQ PQ PQPQPQSPQPa+PQPQ PQPQPQPQPQ PQ PQPQPQPQPQPQ PQPQPQ PQ PQPQPQPQ PQ PQPQPQ PQPQPQ Pb'PQPQPQ-PQPQ!PQPQPQPc PQ/PQ PQPQ PQPQ PQPQPQPQ PQPQ PQPQPQPQPQPQPQPQPdPQPQPQ PQPQPQPQPQ PQPQPQPQPQPQ!PQPQPeffeefPQPQ PQPQPQPQPQ PQPQPQPQPQPQ)PQPQAPQPQ P PQPQ3PQPQPQ3PQPQ!PQPQ PQPQPQPQPQPQPQ!PQP5PQ~NPQiPQ PQ PQAPQPQ PQPQ+PQPQP PQPQPQP~]iPQ+PQPQ PQPQWPQ/P5PN~NPN~PQ~PQPQPQ PQIPQ)PQPQPQPQPQ+PQ P7P] PNp~PoQ;PQP QPQPQPQ)PQ!PQ'PQPQPQP PQPQPQP~PN~PQ!PQPQPQ/PQPQPQPQ7PQPQP+PQ P]pQPN~P Q PQ%PQ3PQPQ PQPQPQ PQPQPQ PQ PQ!PQPPQPQP QPp~PNQ7PQPQCPQ'PQPQ#PQ%PQ P9P~ܫQNܪNP Q PQRPQN PQPQPQ PQ PQN P}PQ!PQ PQPQPQPQ7PQ P3PQ~ N~P ܬ P NppPQS MPQ PQPQMP~P~PQ PQPQPQ PQ PQPQ PQ PQP PQPQP PQP QP~QګNPQP p PNp~݁N PQP R}Ps PQPQ PQPQPQPQPQPQPQ P ~}PQPQP PQPNpp]P~ ~PQPQpQPQp ݃ڜ۟N PQP RMQutN PQPQ PQPQPQPQ)PQۜ}~}PPQp ] P~ ~ P~ QPQہNP S.upN?PQPQPQ}PP]P~  TNP~  Q}۝ N PQPS..t.upQPQPQ#PQ%PQPQ P Q} PQP PNpNP~P~ rQS  ۞~ PSutuu~~PQPQ PQPQ PQPQ PQPQ PQP PNp~PQSRܬPQ  ߟ۞ ~PQP.uݝ٩ڂuۄpNPQiPR} PQPQ P~ NPQTrS SrܪRPS RPSߟۀ ~PQ PUt݂qr۟pQPQPQ PQPQ PQ'PQ P QuSQPQ P P~p ܬ P ~QPrۀrܪ ~PQPQPQPQPQPQPRRPS }QPQ P P ~r r ڞT RPQPQݞ~ PQPrr pQPQPQPQPQPQPRRPNPR }Q PQPPQP ܞ ۫ PS u~P} rrr s~PQPQ PQPQ PQTPQ}P }QP Pت ܪ r  rrRPS ~PQ P Q qr ܐQPQPQPQPQPQ PQPQPStPQPQ}PQ P PQث ۪ ܫRPQ P ~PQP ~rqqr sQP Q~Q]APR P}QP P~  ۟PQP  }Prێrrr r~ PQ PQتت PQ PQPQ'PSsPQ}QPQPPQP~  RPQQs}PQ PQprrqr QP N#PQ PQPQ P$RuNPQߟڞQPQ P P~  RPSS uPQP~ qrt~P QتN PQ PQPQP Su~~PNQP PQ qr   PQ  PQp|rQPQ~NPQت~APR } P NRQP PQpqr ~  RPQ  p}PQ P~ rܫڪP~]PNq Q PQPQ PQPQ PQ P ~QPN PQPPQ PQء PT }QPQP rrܪ ~Pت]P~} PQPQ!PQPQPQP  ۪RPQSMPq r tS}|~Pث Q#PQPQ!PQ PP NtڪSQSuu} Pp ruu}}| P~  ~Q PQ)PQPQPQPQPQPPQ PVt t S ~PQrstݛـS۩Srܫ QPQPQ PRQPQPQPQPQPP~uu t    r~ Pt۫ۑۨSPP R'PQPQPQ PPNPRrs  rݞ݅u~ PQګrrS  PQNP~RQPQCPQPPQ!P   ~PQ PR؀ ߒr ۑۨSr  Pة~PQ PQPQPQ PQPQPQ PQPQPPQPQ P Q P   s  P~QP~ S ېrS  PQ~EQPQPQPQ PQPQ P PQPNpp]PQPQܫ r ہNPQ~PS sSPثEDE PQ/PQPPQ ~ةSP r ܬr۟P PQRQ Pu~ ܨS  PD ER PQPQPQPQPP~ RP rrr r۟~PQP&Q٪u..~St Srܪ}PNP NE QPQ PQ PQPQ PQ PQPPQp ܪTPrr P$Quܑ |RPN}nED E PQ PQPQ+PQ PNPRr  ~PPQ PQuuuSs|S T~EER'PQ+PQ P S P ڪ  ޝ~Pp.u.S݁EEpQ PQ'PQPQ PQPNSP sڪٜ~PS Pp"Sڜ T E ~QPQ7PQ PQ PPN  RPQr  ٪QPuNPp"ߒST  Q%PQ3P PQP~PQܬ S~~P uS EDPQ PQQPQPQ'PP~SPTr S֝ PpuS  o QR  PQPR9PQPQPP ~RPQ   S RNP$ܒSopRPQTSR~PQPQEPP~ PT r ~SݑPp.tتS~  pR P T~ PqQPQ=PP ~~P~ RP Tr SsuP~ S~  ۫ ~}opPQQP N PN PQPQ PQPPQ PتכRPQ  } SsP(psS~ S ׀pQREPE PS/PQPP N R rܬ u~ DܐNQP~tsS pQPDE~PRE~PS~PQ%PQPPQت r S  ~~  }܅~P~ةS~  ~PQPEE]PS u~PQPQ PPQP~    r~P~} S p ـp ~DEQPSuuM/P P r}q   ~P(~~S   o ooNPS} PQ PQP P  TS qs} QP ݨSt  poo ppQPSMPNPQ PQP P~ rS s}  pQ~ ܜS 3oQ PS~'PQ P~ ܫRܬ ߝ~   ܨS~  ooooN PQ ~%P PNp ܭ"R۫~,~߀~  S  rrrr ݁o ~ PSQPQPQ P~ܐ  Sܪ}u(}~   ߅rS} rܐۛ oopNQ PQu~NPQ PQ PQPQPNp S  ~~ ~ ttS  rۛo~ PRݟ}PQ PPQPܬ S ~uu  S ہstݠٛE~ PR~PQ#PPpqܬ  R6 ~   S ۪}u  ooQRQoED~PR ~PQPQPQPQ PQPPQPQ~rܬ S8~u~} |۪S} u.u o DE]PR~ PQ PQPQPPQP Qة rS}~ }~ |RSS a DE~P ݝPQPPQ~JS~   |S ߂~u QoPSQoENP ݁~PQP PQ PN~ SR~ S uuuPNq E~P~PQPP ]ܪRSNR qq ~ S u ۫ uߒuPQ ooE~ PS۟ݠ~PQPQPQPp  STRSq  u  a۪ ~PQooooDEN P ݟQPQP PQP] rS~R~S ~ TS ~QP Nopooo opENPQP PQ P!P] PQPS } r Sܠu~P Qo؝pqoqoo DE]P } ݞpPPQ PQ PN~p ܫPQrrSےt~PQooP`p ooQPSPQP%P~QN~p $ܪ߂QPP~r QRS۞NQPQP o o ~EP ~PQ PQP#P ~؜~ PSPQR SR  RRPRssT NQ P~o Roq pP~~NPQ~#P PQ PQP~  QPQ ~۪PQsN PQ~ oq poqoP~P}PQpQ~P%Pح rQ~ فڪ rSP RsTNP Qooqo pP~PQNP~QPQPQP~P~ ہQPRsTN P"~poo؞Qpo ooQ]!PNP~~PQ PQ PPQPQpP~ة *؜߁ r~r۩QPRܝ}NP~qr RPpr poPQ P~~PتܝQPPQPQ~P~ة؝ qrrڝr}QPu RNPNr qpqpqN~pPQ PQPNpPتtpQP PQP~P.rفrP S TSQRSTSNP Nooqpo~P ~po~!P o~P ݒQPQPQPPQPP~$uRTq܂bNQ~ P Npoqo oo~P~o~#P؞s}P~ݒQPPp~PSS R~R SrssS PQP NoNPpيN/PQpsMPN ݒ PQPPQPQp ~ P~   TrsRp PN QPQ~PQPQ PQPQP~tQPPQ PpP]N]߃~qqځqpqr qrrs PpPQPNoQ PoNPQP QP~sNP~pQPQPPQPQ pPة  ~q܂rڝ~ ,RUr۞r܀PQPQPQP׋PQPQ PQP ؞sQ P PQPQPPQPQPQPت ڀq ~܂ܐܫNPVrrsPQPQPQPQP~N PNpQPQPPQPQ PNPQP  rq~rrrNPTrrPQ1PQS1PQPRNPQPQ PQPPQ PRsR PQPث rq~rTpQS qrtuPQPQPQPQ PQ PQPPQ PNSRP~ ۟߂ r~ ~qrp]P ۫rqrrrs#P~3PN%PQ~pPQ PQPPRrQPQP rp~p ٝ R PSqr rs PQPS~PRNPTRP~pQPQPQP۞rSPQPo ~~~q~ ڪ~PQrQPrrq PQPQPuPRusQPP~qrpPQ!PQ PQPRrsRN Pت ~~~~~P~ pQPrr  ۟PQP  PRrNPPQPQP~rq PQQPQPPRrrPQث  r~~ P~QP ݢۑ.۞ PQP.QPRuQPN P~PQ P~qrqpQPQP QpQPQPPr RPQث q~~rqq~P]~ P~ت P ..~Q PQPQ2uTtstuށPRt~ P~P  P pQPPQ PSbsRPQث ~~ڝ QPN~P ~N P r~#PQPQ. s TQP~  PQNPPQPRbrNPQت  ~~ ٝQ+PQ PQ SrQRr N)P S..utcsu usQP~۫؜~P~PQ PPQPQPQ sRPQ~~~~ڝRQ PQ+PQPQܠ~'PS uނsutuQP QPorr~PQp~PQP PQP RssR PQ0q~q~rqrQRPQPQPQPQs~PQPR"STuuۃuRNPNpr rr~Np۞N~QPQ PPR sېPQPQ r~~~rSRPQPQPQPQPQ PRRceTUu. .~P r۩q کة~PP QsrPQPNu}~r PQ#PQ+PQPReUUuuQP Npr q~PPQ PQR rsRPRRNQPQ ~qr NPQ PQPQ PQ5PRsUܐtܞQP~Q N PQPPRsPNRs PQ ~} ~ PQ5PQ PQPQ PQPRtcUbbu ~Ppqrq ~PPQ sbsR PQ  rڪrq~'PQPQ=PNPNTSTc(۪ssttPۀr ~ PQPPQ PQ PRܞېܞ PQ PQPNPNPQ~QPQ;PRMPQRSdcUrܒ~ P~ QPPrېrsRPQPN rq~ P pp~PQPQ9PRsNPcWSP ۪s tݒ~ P~ NPPRrs P~߁ QPQPNP~~ PQPQPQPS~P dUT SP s tܑ~QPRrQ PQP PQ P PQ PR sq ܐrQPS QPQppNPQP~PQ9PSNPst RP st~ PNP~ qr~PPQssQP~  p PQppNPQPQ PQ%PQPQs~sr݅~Pu t~Q!Pجr r ~P PQ PQs sܐbP~ r P QPQNp~PQPQ+PQPR}PsuޝQtQ P PQ P~rr~PQ P PQPQs rssP~ܭ  rrQNQ Pp~PQPQ!PQ1PQ~P"tssQtsQ P ~sPتrp~PQ P PQPR r QP~~ rrRQp P Q-PQPQPQ/PQr~PcPRrrQ PrsP  ~QتNP PQPQs PQPQ~ trS r۪ PQ~PQ!PQ PQ P#P P PRQ PQ܀܀ PQPجQPQ P  PQPQ PRs  PQP~s S rrrNP qqPQ#PQPuP ~!PQ PQs׊r PQP~pQ PQPQP  PQPRsP~s Srr~Pت~ PQPQ PQPQ PNPu..sPQP!PQ P~P rqpN PNPQP!PQRP~ܑ~ Sr ت PQPQPQ PQ  PQPQ!PQ%P~P~rq~QQPo PPQ3P~ ܑ~QrrPQ PQPQ uu܀PQPQPQ PQP~}PrPQPQ PPQPQ PQ PQ P~Pp rSr PQPQPQ .s܀PQ!PQ#PP r QPQ P/PQPNpRP prp PQPQ PRPQtܜsT/PQ5PQP~ ~PQ1PQP~~P؁ r PQPQPR܁qs .PQPQPQPQPQ)P NPPQPQPQP~RPpr~'P~tۨrtܜ s܀3P~N1PQPQr]N~PQ P%PQPQ~qQP~ r P~pPQPpsܞةqqr1PةN7PQتUrP ~~PPQ!PQqQPQ~~ P ~ P Q P~ r rQ/PتpN'PQPQo~PR]PQ PQPQ PQPQ~NP }~PPQPQp"۩rܛr }rR PQPQ PQP p~RPQP~pP~~PPQPQPQPQs ~~P~T P NppQP~ۑr~ r N+PpS5PQتQP~P~QP-PQ P Q~QP ~ PNpPQ P  NPQ'PpPQ!PQPQتpQ P QpQ~Q P9PQݑqQP~QPNRPQPQ؟pةېNPQ PQ P~ٞs~PQP Qpت~ P~ة~PQPPQ PQPQPQ PRt~N~P~~PNQPQPܒ.rqr QP~؞N)P~;P a~~ P~Q P)PQP6Qt~Np~PQ}~۞QNp~P Qprr rr~ PsNPQ P~qr~?PQ~PP ~~ P PQ/PQ~N~qPכ }۩pQPopNPQP~ڪ rr~PQPPQP~ ۫NPQ!PQP~pQP ~ PPQ PQPߓN]Pp~rP~NPQPQ pu tڎqPR PPQPQr۫~PQ!PQP]QP ~r~PQPPQPQ%Pt~~QNPp ~PQ}ےs qrQP}'P~~GPQpQPpQ PAPs~qNPp qPQP~݀ QRQPN~ PNP~ PQ PQ!PQPQP Qpܪ~ P PQPQP*~~pQNpܪ~ ~PQ PQ ~NPQNPQPQp rPQPQP ت~ PQP! PQPQPMP,sNQPp}~~PQPQsqQPQN ؞NP~ YPتpNPQP"%PQPQ PQNPQPp  ~p~PQPQp~ srrQP ۃNPQPQ  ~PQPQPQ PQPQPNPQP#PQPQPQPQPQPQPQPQ}NP }QPQPQp qPQPQ PQPQp]QP s۫ PQتNPQPQ PN~PQPQ!PQ!PQPQP$PQPQPQPQ PN P}pQ oQPQp ~ r~PQ PQPQ P pRPMPQpQP~ r~IPQP%PQPQP}QoRP   ~ P~PQ PQ}~ܜ ۟~PQPp PQ P q~CPQ PQ PQP&PQPQ PQ PQPMP~ PQ~ qq~P~ PQPQ PQ~PRQrs PQ PQ P ~ت~PQPQPQPQPQPNPQ PQ'PQPQPQPQP} PM PQp~~ qrqqrک~P~PQPQ PQP. PTQP r~Qة~PQPQPQPQ P QPQpN PQPQ(PQPQPQ PQPQP}|}~P~PQNP~ rq۝~P~PQ+P PS PQ PNr ~PQ]PQPQ?PQP NpQ PQ P)PQPQPQ P}|MPت~PQت~qq۞~P~ PQ1PNPQ P~]PQPQPQPNP QتP*EP}|}PNpP Qp ߢ qr~P~pPQ PQ3PQPNqܐ rr]'PQP}P QP+PQ PQPQPQP~PN}~ Pث qqڏrPQPتpPQPQ'PQPrr rAPQ~P Qq}PQ P,#PQ)P} P~}qr rۜ~SPتp_Pr r]?PS~PQpQ PQP- PQ-PQP QPQp ~rٜP ~~_P~rr~PQPQ PS~PRpQP.PQ PQ PQ'PQqPQp ۝~P ~p PQPQ!PQP r~PQ5PQ~ P~]PQP/PQPQ%PQ~ P}~P"ܪqq QPNppQ+PQ!PQ PQPQتqr~'PQPS~P P0;PQت~ P }QPQP~ q q~PNpPQOPت ܪةpN PQPQPQP Rt~PQ PQ~Q PQ1PQPQ PQP~~PQP}QPrqr~P~PQPQPQ PQPQPQPتrN~r ~PQP Rݓ}P ؀~PQP2 PQ-P~~ PQ PNڝqQP NpPQ PQPQ PQPN~PQقpQ1P N~t~PQp~ P3PQ PQPQ PQPQةQPNܫqrqQPQ~?PQPQ PتQP~ ~PQPQPNp.~NPQPށQPQPQ4PQ'PQ P Qت|QP ~ ~QPQPQ PQPQ PQPQ PQP~PQp Q#PQ P VQ PQށ~ P5 PQ PN}PNppQ PQ PQ  PQ+PQ!PQ+PQp rr-P P~~PQP6PPNp~P ~yPQP -P~ PR~ P7PNܐ~PN~PQ PQp pQPNP~  PQPQPQ!PQPةPQPNמ  PR~PQP8PQP ~PQP QppQpN PQP~ PQPQPQPQP ~p+PSu NPR N P9P NPoNQPQ PQQP Ps PQsPQPr+PSu۞~P ~Q P:P~~pE QP~P~QP pQ P ~!PQPQOP ؏r~PQPNSu۞}pPQpu P; PNpNPQp~P~Q P N~PQ P~ /PQ%PQPQP~~'PSQSߢP~u Q PQ< PQ~PpNQPQP~NQN~ppQP~TR}p~p~ PQ PQPRPQ%PQ PQPQP~p~PQP tpQP~QPQPQ=QP ~p]P~PqqٝRP Uc pQNp PQ PQPR'PQPQPp~~QPQPQPQPQPtu~PNPQP>QPNpPQP~rrqpRQ PQPRbU PNp~;PQPQP ة~p~ PQPQPQPT }P? P~QPN P~P~rܪpQPQPRbs pQP ~PQPQPQ PQP Qpq3PQ!Pߞu.u ~~QPQ P@PQPRQPT~NP~P~rrpNPR pQPQp~PQ PQ PQPQPت ~PQ PQPQP؜ܒt t pQPQ PAP~p PTPQ~Pqr  PQ P RTRPN]PQPQPQ PQPQ PQP P~PQPQ PQ PQ PQPQPQۑt ~]PBQP~4QPTPQpqq۪~P~rr NoQPQPQpQPQ~PQPQPQPQPQPQp~Q~ PQPQPQ Pp t~ PQPCQP~&psNتrqr~Q~r~PR p Pت~PQ PQPQPQ PNpکpPQ PQ;PQputq]PNPQPDP~spr Rr~]P RpPQr~P~~P~PQPQ/PNpQPQ PQPQ PQPQ Pة~P ~~PQPEP ~DtݜrPQ܏pPQP RUڨP~ܫ~PتP~PQ#PQPNp~#PQ%P~rܐڢP~PQPFPتErpRPQ~]PQPQSQR~p P~~P~ة~ PQQPQPQ P R~PQ~Q PQPQP QQ PQPr~݁S~ PGP~D~QPQ]PتNPQPQSUpQP~pNQ Pت] PQ PQIPQPQSPQ P~ ڐ Q ت~~ PQHQPت} ~Q PQتQ~QتNPQp P&~pNQ~جܩQלQEPQPQPQ!P~~ P QqPN ۢ PQPI P PQ~NQةNPQQP$~pNP~Qت ~P]ל PQ PQPQ+PNPQP~Q~QPQP RSPq~PJ P NP~~Q PQ~PQPQ~PQNP~ P~QNp~NP~Q~PQ PQ+PQRNPQuQ~~)P QSQPٝr PQKPQPEP~QPQ~P~}RPNQ}Q|ש PN~p P~ ~P~ة;PQRPQ pP~QPNPQdSQPQ PL P<~Eة~QتP~QPQPQ P N~pQ|Q~QP PQتP~+PQ PQQ  ~P~}QSN PQPsSbܜPMQP~تE ݜ P~ }+P~PQ} ~QP؜ PQ~PQלQ~-PQPRut r  PQ P ~sN PQS RN PQPQN P QpDEsP Q}R1P|ة~PQ؛P~ڝڞp~] PN}PNPR~ r p] PQP~strNPNQsQPQ PO P~DEt.sQPQةp PQPQPQ} ~PQ PQP ~qڝrpQPPQ P~}ت r ]PܑtsNQss PQPP P~E~u.pQPQ~QQ5PQ}P pNPQP~ rPuP NP~ڞ r~PQPN~tssssݒNPQ P ~EDE uܛ-PQP Q}|~}~ P~ pP pPu uN P~ڝr PQptޑ~sܝpQPQ PQR PE ےt~PQPQPQPN~PQ~}~PQ}| PpP . N P~߃pPQPQ۩rpQPS PQPNpppڟ. ܩQ PQPQPQPQ PQPN r ~pP uu}P~ r ܛrpQ Pتܠ~NPQ PQPTPQPQPQةQ PQSP PQPR "rۏP~ܬPu uNP~qrځspQ P~ ~NPQPQU P~QPu PQPQ PQPQ PQ PQ PQ P~ rSP~ ܬpQPU uNPr۪  PQp ۞s~QQPQ PQVQ P ~EQPQتpp PQPQ PQPQPQ PQ P~p~ P ~pPsuN P~r ۫rr}pQ P*pݡܞ}}ssp~NPQ PWQ PNQPp|~Q~pQ9PQPQPQP ~PQ~QPQPQP rrrrqQPQp ~تsr ssNPXPQ P ~QPNp|~PRިP~PQ PQPQ PQP~P~P~ PQ Prq PQP~rr  pQ PQRQPQ؝r~sۜpPQPYPQ P~PPR~P~oPQ PQPQ PQPQ PR PQ~P rQ P QPQPNrrq pQPQPת~ܡs~Q PQ PQPZ PQP~pQE}PRPQ PQPQ+PQ P QR~QP~p PQ P~QqrR PQPQP~ r ~Nت PQPQPQتQPNQ PQ P[ PQ PNQPQE~P }WPQPRPN ~PrQ PQP~ r~PQp~pQ PQPQP ~PQ PQ P\P Q~P~QPN|}QPQPQpqQ PQP ~ڝr~ PpQP~pQP QP~qp~pR PQ P]P}]PQQ PQPQPQPQPQPQPQPQP NةQP%P~ٝqrp~ PQتrQ PNPQ~P~QP]~NP^PQ}PQ+PQPQPQPQ PQQPRPQ P] PQPQ~QPQPQ~Q1P_PQ PQP ؛PQ PQiPQPQPQPQPQPQ PQPQPQP`PQPN~PQPQPQ PQPQ PQPQ PQPQPQPQ PQPa+PQ-PQPQPQ!PQPQPQPQPQPQ!PQPb'PQPQPQ!PQPQPc PQ=PQPQ PQPQ PQPQ PQPQ PQPQ PQPQPQPQPQ!PQ PdPQPQPQ PQPQ!PQPQPQ!PQPQPQ!PQPQPefexult-1.2/data/bg/great_dagger.shp0000644000175000001440000000105207256474661012641 *   ~ ~} }{ {z x x{ ~    ~ ~      ~}|zx   ~  |~  ~    v         exult-1.2/data/si/0000777000175000001440000000000010062225327007601 5exult-1.2/data/si/flx.in0000644000175000001440000000005207314712471010642 ../exult_si.flx SImap.shp defaultkeys.txt exult-1.2/data/si/defaultkeys.txt0000644000175000001440000000524107570007754012614 # default key bindings Alt-KP+ resolution_increase Alt-KP- resolution_decrease KP+ brighter KP- darker Esc close_or_menu right walk_east left walk_west up walk_north down walk_south KP7 walk_north_west KP8 walk_north KP9 walk_north_east KP4 walk_west KP5 center_screen KP6 walk_east KP1 walk_south_west KP2 walk_south KP3 walk_south_east Shift-right walk_east 1 Shift-left walk_west 1 Shift-up walk_north 1 Shift-down walk_south 1 Shift-KP7 walk_north_west 1 Shift-KP8 walk_north 1 Shift-KP9 walk_north_east 1 Shift-KP4 walk_west 1 Shift-KP6 walk_east 1 Shift-KP1 walk_south_west 1 Shift-KP2 walk_south 1 Shift-KP3 walk_south_east 1 Alt-right scroll_right Alt-left scroll_left Alt-up scroll_up Alt-down scroll_down home center_screen Del delete_selected Ctrl-right move_selected 1 0 0 Ctrl-left move_selected -1 0 0 Ctrl-down move_selected 0 1 0 Ctrl-up move_selected 0 -1 0 Ctrl-pageup move_selected 0 0 1 Ctrl-pagedown move_selected 0 0 -1 Ctrl-C copy Ctrl-x cut Ctrl-v paste F2 cheat_screen F3 map_teleport F4 toggle_fullscreen F10 show_endgame F11 show_si_intro Alt-F4 quit Alt-Enter toggle_fullscreen Alt-1 sound_tester Ctrl-B shape_browser B useitem 761 # Show spellbook INSERT create_item -1 # Create last shape C toggle_combat SPACE pause_combat Ctrl-D delete_object E toggle_eggs F usefood # Feed G useitem 675 11 # Use abacus Alt-G toggle_god_mode Ctrl-G change_gender H help Alt-H toggle_hack_mover Ctrl-H cheat_help Ctrl-Alt-H party_heal Alt-I toggle_infravision I inventory J useitem 555 # Show Jawbone K useitem 485 # Use keyring Alt-K try_keys Ctrl-L party_increase_level Alt-L skiplift_decrement L combat_stats Ctrl-Alt-M toggle_map_editor Ctrl-M create_item 644 -1 100 # Create gold Shift-Alt-M play_music -2 # Previous song Alt-M play_music -1 # Next song M useitem 178 0 # Show map Alt-N toggle_naked Alt-P toggle_petra Ctrl-P repaint P useitem 627 # Use lockpick Alt-Q quit Ctrl-R quickrestore R face_stats Ctrl-Alt-S screenshot Ctrl-S quicksave Alt-S change_skin S save_restore Ctrl-Alt-T map_teleport Ctrl-T next_time_period Alt-T cursor_teleport T target_mode V about Alt-W toggle_wizard_mode W useitem 675 21 # Use watch Alt-X quit Z stats Ctrl-Alt-G grab_actor Ctrl-Alt-P pick_pocket Ctrl-N npc_numbers 1 inventory 0 # Show inventory for Avatar 2 inventory 1 # Show inventory for character 2 3 inventory 2 # Show inventory for character 3 4 inventory 3 # Show inventory for character 4 5 inventory 4 # Show inventory for character 5 6 inventory 5 # Show inventory for character 6 7 inventory 6 # Show inventory for character 7 8 inventory 7 # Show inventory for character 8 exult-1.2/data/si/SImap.shp0000644000175000001440000016117407312457552011267 | ]hfeefPWU QNMNMuQU%sss!CPWPNPW U QMQMNMNMNMNMNQMN QNQNPQNPQNPN Q NQNQNQNQU%s؀~ ~qpq'ϻrPWPNPWs tU QNQNQMQNP QNQN QNMNQNQN PMNMNMNM NMNMQPQU s؜~~Pqqِ'~p׺bPW PPW tU QNQMNMNQNPQMQM QP QPNQPNQNQNQMNQU qsכRq'؛лpPu WVPQV uUQNMNMNMJKMQ NQNMNQNQPQPNQNQPNQUrqs p'prQP;PQRVTRQNQMJJJKMNPQPLMNQP QNQNPQN QNQPNPQU  r q )V; PQPQPMJIJKLP QNPQNMNQNQN QNMNPQNQNMNQPQN QU q Eqr?P QPQKJJJPQN Q PKLNMN LMNMNPQPLMQPNPQU s|r qp E?PqqPQN LJIJKPQNPQNMJJKMKJ MLNQN QMNQU sL|Lr qq Euu?P`ہPQ NLJJKLPNPQPQPQLJJJJJNPQPQPNPU s}}؜o؛ppq ' ~[P `rPQNMJKNQNPQPQ PKJJJ LMPQN QU  rq r  ' {~z[P RqqPQNM IKPQ NLI KJMPQNQPQPNQU  r  'K|ǂ[PR SRPQNLKJKPQM#IJL QNQPQPNQU   ''3!PQPN QMNPMJNQNK#I JMQPQ PQMQU   uU!TurWTU 3!PQNPQPQMKNQNP Q PLJJIMQPQPQNQU  uR!PߢUPQ U9!PQNMQMNMNP QPQLJKJI JKM QN Q NQU  qR!P!UPU3U!PQPNQN#QMJJI JLQP QPNQUq q S!P!UTRW1#PQNQNQN QNQPQNP QLJJIMNQ PQNQU pqr S%QPQS?#PQNQN QNQPKJ JJIIIIIIJLQM QMNQUpq  SQNKN QNRMLNM LNPQS?[#PQNQNQPQPKLJJKKK KKKN QN QNQUqq qpqpr dRQPNMNQNQ~LM{|}LMLJKMPN PNQS?[#PQMQNQNQNPQN QL JKJ JLQNMPQUq RPQNPNPQPN {|}| JKP QS?[#PQNM'QPLMKJ JKLML M NMLNMN QMQPQ UR QNPNQNM|{ JKNQPQS?[#P QN QNQN QNPQNQN LMLKJJLQMNQPNQNQU p  SQNKLMNQNJ  JNP QS?[#P QNQNQN)QLMKNLMN%QN QMNPU qpqS QNLLMLMLMJJL } |JKL NMNQS [#~}[#PQNQNLPQNPNQ PNQMQMQN QNQNQNQNPU   pSQ MPNJ JJ KJLMNQS [~#[#PQPNQNQN;QNP QNQLNM QNMNMNQU  S QKKƁ KMNMPQS [~#[#PQPNMQM QNQNPQ PLMQNQMQN QNPQPNQNQMLNQNPNPQRGSQN JKKƂKJKMLKMNS [~#[#P QMQNQPNQMNQP%QNMN MNQNMNMNMQPQNMLK! KJKNPNS [~#[#P QNQMQN5QNQNMNPNQNQNQNMQNJJLQ NMLJNIQ NPNPNĄKJMPQS [~#[#P QM QPQNP!QM QPQ NML{MN QNPQM JNMKJLMNMNMNMN-QNPNPNLNMKJ Ä JKL NQS [~#[#P QMQPQNPQLz}LMPQNQNPQMJJKPN~{J{ JL+QM NJJ JĄ KKLMNPQS [~#[#P QNQNQPQN QPQ NQNQPQNKKLN QMJJNPJ|r~Jz{zKJKMNMNPQNLJJJNPQS [~#[#PQPNQMNQNQN+QP QNPNKLN QNPKJJKPJ|J{֚||JJ NQPM NM QMJJƁ JNP QS [~ [#PQPQPNPQNQP Q N QNQPQNKNQNQNQN,KPQN|J{{JKNQNKJM QLKJJƁ%JM NQS [~#[#P QP NQ PNKM QN QPQNQN QN QPQPQNM JPQ PK{J{zJNQP NK JL NMJJł'JKM KNQS [~#[#P Q NPQ NJMQPN QNQPQPQNQ NM JKNPJz|{|{JJKPQPMJ J JJKJŁu JKMNMQS [~#[#PQPQPMQ NMQNQNQPNKJM NPQNQP QPQPNQNNMNJJLNJJJJLPNKJJJń-JNQS [~#[#PQPQNQLNQNQNKJ LKMQPQPQPQNQNNPNLMNLKJKJJJ JKMKJ!- KNQS [~#[#PQNP NQPQNPNPN QNK JN QP QN QNMKKKJ|KJI JJNMJƀO}yKNQS [~#[#PQNQPQPQNQN QPN JLNQN QPQ MPQNPQJJJJJރKJJJN ƀ۟ڢ JJNPQS [~#[#PQNMNQ NPNMJ MPQNQNN QNK}ޝׅKJKJIJ JKN؜sכ݃tuJMNPNQS [~#[#PQPMNQNQNQPQP QLKMNP QNQPQN Q NMą KJI  JJKMJ#JKNPQS [}#[#PQN QNQNP Q PNLMNQPQN QKą~I| KzJI JKNŀsܢ # JNPQS?[#NQNQ NQNQNP QPQPQNMN QPN QLM QPQN|I|KJJ IJ Jz{NJ s׀#JMNQPQS3[LZ{[!I KQNPMN QMQPQPNQMQPNKLK Ă| I|}KJJ IJ Jz LNJKK JKLPQS1[Lz|{zL!IKQN QMNP)QNQMQNLJJă~{x I| |J IJJ LPMJ JJ psu J MNQS1[Lz~zL!IKQNMN QMQNMQNP QPQPNQPNP QPLJ|Iz~ |J IJJLPMJ|߂|z s۟KJ JLNMLNPQS1[Lz}zL!IKQNQ MNMQNMNPQNPQMQP NJKĀ~|J IJ JKLNz y{K# JJLNLMNQS1[Lz}|zL!IKQNQ NQNQMNQMNP#QNQNQMQNPQPN JKŁ |JJ I J KLPL zz!uJKJMNLJLQNP QS1[| {L!IKQNPMQMQNQNQMNPNPQNQPQPQ NLMLJKKŀ |JJIJJKLJJ JJ JJKMMP QTM!IKQNQNMN QPMQNMLML JJ~ }JIJJJJKKKK{}KJJKz JPNPQT+SP IMP QNQ PNPQPNPQPMLM QMNMQPJJ JJ~ |J IJyzJJ {}Jz{zJLLMPQT SP IN5Q PNPQNM NLMLMNQMNMNQNMJ JJJ~ { J IJJ JJJz} J zL{JMNPQTuڞ؞ ڞSP INQNMNMP QMNMNQPNMNQMNQNMNMNMJJJJ {JJJIJJ J JJJ{zM|zMLMNMQTW  SP INQM JJM Q NJJPQPSVQNJ}ۜ{JJ JIJJyz JJJ JJ{zKzLMNPQTW %SP I NQPJL NMJKNQRW | RQNJŁ uuٞ { JLKJJJJyz JJJ!J Jz JJM Q U%SP INQN~JJJJPQSzK|uRQMJƂ% LJJNQKJ JJJJJ JJyzJJJLKLNQU} SP INQP JJ NQS~{DŽRQN KKL{ ؟|JNQLJJJJ J|JJJ J JL LNQNPQ U} ܟ SP INQNK{JJNQSVRQNJ KJK{~  |JMNM JJ  JKJ zJJLMN PNQPQPRV  SP INQN J J NQTu RQNJ JKJ"~~}|JKzKJ JKLNKJzJNMNPNQNQ PRV# SP INQPKJ JJNQT NQPM J J J}}~|JJz JJJ | KLPNKMNQ P QPR SU#SP IKNQPN|KJJNRVQN PNJJJ}~|J|~zy JJ {}} }L NJM NPQPQ~NQ PR#SPIKNQKKJ}|KJNQSuRNPQNJJJ6J|~~}}J~zJJ z KNPQPKMPNQ P~QPR#SPIMQ KJKJ}uKJKNQSRQNPNJK ~}~~~~ J J{ }LNQPNKLNPQ P~ QPR#SPIMQNJ KĄ~ }KNQSRQNǃ } q}}}JzٛyDžMQNQ NPQN P~ r oQPR#SPIMPQNMKJĄKJNQRURQMK }~q} u ~J J~{ MPNMPQNQPQNP~ r~PR#SP{NP QN K~ JNQTRQNǂ~~ٛr }  ~JJ}{ٛMNP~ NPRUV URT RQLKłJJKMNQUQNQPK~u}~}p}r} ~ { ٛ|}PQ  pQPR .u   UQLJJJ}JJLNPQTVQN{u} } }׍}q} qIy tހ{}|!P ~ PRR ut  sUQN MKKK JLN QTQNQMJ ך}} q}}z~}Iy { N!Pr qQPRuTRrru  ruU QJ JLN QT Q MJKJ y ך } r}Iyu{| {ǀu|{Kzz}|}|~N#P~  ~PR us  rru urU Q NLNLMNLMN QPTQNJKKā }pq}z|q{z{|{z}z{ }y%P NPR. urr usquU#QPSQMLJJ ăs}ooq }}|~{pr|{| {yNPNPNMNP QPR rr rqu VQPSQMLJ ă~ ךq}~ ~{ }{~NPQ|NK|P ~pٜPR  uru ru VPQRNPQS QPJJăڛٛ}~ } r}|{   PQKz{|P NPR uؐ tt ܏u VPQP~ǃz~PQ NMQMN J K ƃ܁} ݠп{] PNǨ{| NP~ َ PR u ߑ [~WPR~zƚ~PMQMLJJru }|  ٩] PRK{zz{P~ NPR u u[~ WQPS~K{~ QNz}NJ%{ qoQP{}{{ PQة  ~PRu  u[ ~QPQ~z|~KJ}u ߀{   PNK|K{ P Qت PRu. t [QP~z}ƙ J z   ~P{ K{} P~PRutss[QP~z}}{ rr}J ~z  QP R{|{PQ P~qQPR%uܜ [QP~z}} rr|}JPQ~z  Q#PQPQP~ppQPQRV uuWߑ [QPNz~~ƙruJQ~z   qت~%PQPQPQP~p~QPNبQPQPUuuu ruu[UQP~z|{rr8qqr}}J~z   ب~%PRQ PQN PQ PQPQRPU prq[RPz|~{rqrqr{}{Jz  ~N PQKz|NQ PQPq~ PQPNQ PQ~PUuuߐu  q u qru[QPQNz| ~{rqrrzJܞ܂|zS ب ~ PQ}~K|qqp]PQP}{NQ~~~QNpq~QPUu uqp   r uQPNz }{rrqr}KJ܅z} ب~ P zroQ P}zq |{q~PUutuqu uuuTQP~}z~Lƙrqrq zKJz q ~ PQzٞqpRPQPQ}{q z{z{z{z{~P Uuupq uuRPz|~{}rqrq~Kz z}   } PK{~ǚpNPQPz z{~ ~z~PUߓ uuRP~z|~{ rqrqr qz~ {|}| q ب ~ PQ}|}Q PN{z| z{~z~PRVu uu uq~rRPQpz|~yrqrqr| {{     ~ P Q~]PQPLz|ƢzP Uu ߅u  L}RPNz|}y| r qr| ~{~~~ rr }~P ~~NQ PMƢ | z~PUuuuu{|$RPN}z{|zrqrqܩ{|~QP]NPr  }~ PQPQ PNLK{u y| |. z~P Uur ~q|z#RPN|K|}zrqrzz|  ~QP Q~ ۪ ~}~ PQP MLMK| y|} z~PUqqސ |zRP z{z|rqqr{| ~%P NPp  PQPK{~{z| zNPUur}q|z~|RQت z{{r qrq}y ~PQP] ڀ PN~PQPQPz|yz| ypNPUuq ڐ ~|Rz{z r}zǚ~PQPQ Pت8 ~ PQPQPNK|{ }}| |zت~PUr qu1RPz{Kz }z{~PQPQP~  ~QPQ P Q~|z| u}~{r{}~ zr~P Uuq~ q/RPz{z{}z{~ PQSQPQ PQP~   PQP N{|{~ zQPUuq?RP{}z}}z{~PTQPQ~ PN  !P Nqz|z} {QPU7RPz{u{ z{~ PTQP~~{8 NP ~z|z K} z~PU)ڃRPN{zz zQPTW uQP  PQPzz{ơ zQPU')~ RPQ|zzo~PU ۞ uQP~r r   P QPةKzyzKzQPU݅-RPQت|zK{~ PU!RQ~rqrqNo؛QQP ~Kzzr ǃKzPU-RP N ~ PU UQ RRPrr QPQo#P Q~z~ zzK zKz~PQ PU/VRQ PU U QPRP~ rr p~1PNz~K{ |yu zQPUqu ! SPQPQ PQ RQPbQPש}QPN!P~z}~{%q|yu z~P Urq ߀!  VUSPةqPQb QP~ שPNpQP|{|{||K{%r|z z~PU  u VSPQרq~ PQ~r|{|QP  NQ P~~P~ K|%r|yuz~PU ߀  VSPQ~ PQNQN|qz|pQP! N~ PR~}q 3|zuzPU  u VTSPQت~ PQNLMLp~}{}|z{ ~QP~ P ~ٝqqrrrq%|z{ z~PU ߀ }}߁'VSPQةp~ P QPQNLM qpp{qpQP~ #NP~rr #|{ |zPU  } sUPQRQPQN|p|q|oQP ש N PQP~r rqqq{z| }|z}~PSV  UP QPQPQPQPQPQ.Npq{z|~|z|{~{QP~qp   ~QPrrrrrq|}z}~PU }~} uU PQ PQ PQNp qט|QP~r  NPqrqrqqqz}z~PU u V UTQ PQ ~p؛PQN|qpq{ٚQP~ ~PQP~r q}} z~PSUV ISP~poP"QNqqNMao{ٛzP1~ Prrqr qq z} {|~PRU GVSQQP~N~ QP"QN}qqar{p{P~3NP ~qr۪qrqqqr|}{~{~PU GTQp o PQ{}| qzP/ QPQr rrq|{z|~PU ISP~pPQaQ|}{|z |MP~ r ~~PQتکrr rqpr|{}| ~PU ISPQ NPQq{{ NQ|}| P~ ~Q P~~PQٝrrrۏr~rqpPU ISPQ ~PQq {ٙNQ} ٚq|P؛p  ~]~QP~ ~PQPqrrr~~ q~P]!PU I SQR  PQN{|{Nqqq|P ~PN~QPN~ ~PQP ~r RS~r~R'PU ISQP~rqPQ|ؙ|P QP ~PQPNp rqrq qQaQ~ ٜQ'PU ߀KTPQ PQ|}{|P QPN P Nrڪ QPrr qqrQpr~ ~~)PU KTPQp ~ PN{QP~ ~PMK |}PNQPNpr כ~Q بQ~Q)PU ߀MTP~ ~P}{ QPN~~P}~ } P Q P rq qqr~PQ~~R)PU M TPQrpQPQLQP~QPM~ } P Q Pq٪rrqPQPQP~~~pQ)PU ߀MTPQ  NPLP~ب QP}~ } PQ PQ~prک rpNQPQ~ Prr~)PU MTP ~}|~  PM~ K|PQprr P~P~R'PUu ߀)cTeTP q  Q PN} z{}P Q~prrqrqrpNPQP~p]PQPR'PUu   )uRTUQPQ  QP Tߢߢuz }|{ P prqrr qrqq~PQPQ P רy R'PU؅ ߀!)uRTSPQ۪ Q רQPTuK| Prrrrq~PQPQP~y~rqR'PU "-SPQ ~zQP| P qrrr ~R Pzy~R'PU #=T SQPQ~P~ z{z| QP}){ Prq٪rqrrr~N}~Nz z~QPQPQPQ PQ PU%$1 QP QPة~P~z~{ QPL){ Prq qr |z{qzz} NPQPQPQPQPQPQ PU%%/~ QPQ~QP~z}|y RPL }{Q PQ r|K {r}zz~N)PU%&/ QPQب~ P Qרy{z ל QP~}||}~N Pqrrqr |z{} z{{z|~PQPQPQU%'/ QPQPQ P~z~ |yם Q PN||N PQq|{ }z|{| {| 'PU%(/~ QPQPQ P~{u |y  R PMz|zN PQrr|{%{ PQ PU%)/{ Q+P yu |zqQPQP~|{zN Prqrz|){ QPQPQPQU%*/u Q+P uߠ|z rqqpNPQ PN~{zQPqr|}-z NPQPQPU%+=Q+Pyu݂|zqQPQPM|~  ||{|QPQت|}- K{|pQ!PU%,%WVQ+P~}{|بq~Ra P~|z K|}|K||zQ PQ؜|ǀ- {|oQPU%-%U=PQPzݟ{|ب qS P~zK}|}{yM P~|ǀu { QPU%.%U=PQP]{|{z~}{ q QP~ K{|zQ PQة|ǀ }z{|}|{pQPU%/%U;PQP~{|~|{|ب ٩Q P~ {|{}zyM PQ؜|{|} {|~{ q~PU%0%U;PQPQة {|بq QPQ PN {|~ }KyMN P Q~{zK{ }q qQPU%1%U%PQP QPQ P Q~ة  rRPN{}P~، }{Ky{NP QPRPQq  { ~PU%2%U)PQPQ~  תqqPN~~Q P~כ~N}{NQPQ q؜r ~PU%3OP~PQ PQ P~ PQP~QPQNPNqrrqrכ~9P4GPQPQ PQP N~PQPQ1PQqr ~P~Q9P5KP ~~PQP~  ר~PQ~QPQPQPQPQPQPQ rqrr~ P~Q;P6GPQR ~ P  ~~QPQPQPQ PQPQP QPQPQ rrr ~P~QPQ7P7IPQQPQP+ب~N P NQ PQQP~ N~rN PQ9P8IPQ|{oQP r}y|zPN y}!P~pQPQPQ;P9GPQ{z{ PQ P~  ר! }zyzzzK | } PQPQPQ~ ~EP:KPLzzQP]p ||ߞz ~ } PQ PQP~ NopNPQ/P;3PQLKNPLKP{ zzQPר  |}ۜܠ u܃} PQ PQPQPQP~pPQppQPQPSRP<3P(~}MN}zNPQ{zzQPQ P~ר "|zƃruu  ր}PQPQP Q PQPQ%PUSP=3PyM~zNPQ{zzQPQP~{z}qpٛ ߙ ր} PQPQPQPQPQPQ PQPQ PUSP>3P*MNzNPQq|zz~RQ P~ ٩ |z}(qߞׄלؚu֛؀}PQUPUSP?5PMP~zNP]{zz ~ P~ ةz{ rrک{z}s۞}rמuכu} ؛} P }~|YPUSP T@5P~MPzNPQ{zz~P~  ƛ rڜr(|z}}uآ}}}} P }PQ PQ#PQ PUSPQST A5P~MPzNPQ|zz ר~Q~ {  |z| r}آ}}}P Q؜PQSPUSTB5PMPzNPRp{zy|oٝ z{}{ y|q}u }}~ P~PQ PQPQ'PQ PU%C5PMPzNPQ{~y| q ٝKz{|{ {}ݻq}r} ܞݞ  }}{N PPQ!TSRV%D5P~|MPN|QPQך{Dž~y|{|ت؝ ٝ yz{|zz|zq}}r}}߅}'PQ31E5P~MPRPQ|z~|~ٜq  z$K}~qpqrr}֚qq ƚ~%PQ31F7PNP~R P~}|{z~yqq|  |~rrprq rq}؛}ٻrƚ~!PQiG5PQ~RP]R PQ}z |  z zz ~~qqrpq }r}QPQiH7PQQPQ P~||}{zq  {z }}q}qrrq}r}~}rq|PQPQ+=IKPQPQ}Kz ƚq  ~z}}r~}r}rq}Qqr}}ƚQPQiJQP~}y ƛٝ٨} ~~~qrڜ۝ٛ} z~PQiKMPQP}{Kzƨq z z~~r s ڞz|~PQQLOPQP~}Kz߄} ~Kz z~}~}rrs}~ }|QPQiMOPQP~} z rz zz~~r z zǀrٓ|z|QPQiNQPQP ~ר  zK zKzK~~}Kz{yz|zrqܡ{|QPQ't)OQPQP~؋  z {KKKzة{ǀ ~Ksqrt||QPQ't)PSPQ P~ר pqpQP~רة |K{ oPQ{ zKz Kzpu{z|QPQ'tr ׏)Q]PQPpSS P~Po؋~PQ ר~PQة{z|QPQ'r ֏)R_PQP QPQSQPQPQPQ PQPQ z{zQPQ' tr ׎)SkPQPQPQPQ PQ#PQP Q Pש{ǚQP'tq׊)TCURsP Q9P~ }P'r׊֏)UGR!P!USqP~ QP'tr)VGR!P!UCP!TSPQ~ Q#P'tr)WGR!P!UAPT!UPQ-P'trr)XGR!P!U!PRT#UCP't s )YGR!P!U!PUAUCP'u  +ZGRPQSR P!U!PUAUCPEu[GRPQSU W P!U!PUAUCPE\GTRU}z W P!U!PUAUCP)}]G|z{W P!U!PUAUCP'  ^G |{|zzW P!U!PUAUCP5/_G|}|Kz W P!U!PUAUCP5ܟ/`G||z W P!U!PUAUCPiaG| {z W P!U!PUAUCPibG|{{ W P!U!PUAUCPicG~{}{{ W P!U!PUAUCP]WPNdI~ | WKPU'uUCP[WPNeffeefPWU QNMNMuQU%!CPWPNPW U QMQMNMNMNMNMNQMN QNQNPQNPQNPN Q NQNQNQNQU%؀~ ~qpq   ϻrrPWPNPWs tU QMQNQMQNP QNQN QNMNQNQN PMNMNMNM NMNMQNQU ؜~~Pqqِ u upغbPW PPW tU QNQMNMQNPQMQM QP QPNQPNQNQNQMNQU qכRq .. ..؛uڟлpPu WVPQV uUQNMNMNMJKMQ NQNMNQNQPQPNQNQPNQUrq֌op pu|۞rQP- PQRVTRQNQMJJJKMNPQPLMNQP QNQNPQN QNQPNPQU   p uu.ڜuzݜV ؅qq PQPQPMJIJKLP QNPNMNQNQN QNMNPQNQNMNQNQN QU q  .u }qr ~؄tpss!PQKJJJPQN Q PKLNMN LMNMNPQPLMQN PQU |}|pq  u.uT $~ۅu١܅ PR RPQN LJIJKPQNPQNMJJKMKJ MLNQN QMNQU L|Lrqpqْ u..uuuu }ءءuPRہPQ PNLJJKPNPQPQPQL I JJJJJNPQPQPNPU }ך؜ pq . ~)ס׃s P QRځPQNMJKNPNPQPQPKJI JJ IJ JLMPQN QU rqrpq r   ... {~zr  ޡuuPRځPQNM IKPQNLII JMPQNQPQPNQU  r  ..K|ǂuu ut PR SRPQNLKJKPQMJJIJI JL QNQPQPNPU    % u ߁!PQPNQMNMJNQNKJI I JMQPQ PQMQU   uU!TݠWTU څۢuu !PQNPQPQMKNQNP QPKJII MQPQPQNQU  uR!PUPQ U  փ !PQNMQMNMNP QPQLJ I I IJKM QN Q NQU  qR!PUPUuu U!PQPNQPNQPQMJ IIJLQP QPNQUqq S!P!UTRW1#PQNQNQN QNQPQNP QLJ JJI MNQ PQNQU pqr S!QPQP QP QS?#PQNQN QNQPKJ I IIJLQM QMNQUpq  SQNKN QNRMLNM LMNPQS?[#PQNQNQPQPKLJIJ JJJN QN QNQUqq qpqpr dRQPNMNQNQMLMK|MLMLJKMPN PNQS?[#PQMQNQNQNPQN QL JJJ JLQNMPQUq RPQNPNPQPNL}~| JKP QS?[#PQNM'QPLMKJJLML M NMLNMN QMQPQ UR Q NQNpq pכ|{ JKNQPQS?[#P QN QNQN QNPQNQN LMLKJJLQMNQPNQNQU p  SQNKLMNQN Jy JJNP QS?[#P QNQNQN)QLMKNLMN%QN QMNPU qpqS QNLLMLMLMJ ߢߢJKL NMNQS?[#PQNQNLPQNPNQ PNQMQMQN QNQNQNQNPU   pSQMPNJJu~uJKMNQS [![#PQPNQNQN;QNP QNQLNM QNMNMNQU  S QK}~u؅zKMNMPQS [#[#PQPNMQM QNQNPQ PLMQNQMQN QNPQPNQNQMLNQNPNPQRGRQN}ustuuuzJKMLKMNS [ ء  [#P QMQNQPNQMNQP%QNMNMLMNQNMNMNMQPQNMLK}tuzJKNPNS [ ۅ٠ݡ [#P QNQMQN5QNQNMNPNQNQNQNMQNJJLQ NMLJNIQ NPNPN}u u KJMPQS [ ڟ[#P QM QPQNP!QM QPQ NML{MN QNPQM JNMK~ }LMNMNMNMN-QNPNPNLNMKJ |. JKL NQS [ޅܡߢ[#P QMQPQNPQLz}LMPQNQNPQMJJKPN~{J{ JL+QM NJJJ{ KLMNPQS [ لܢ[#P QNQNQPQN QPQ NQNQPQNKKLN QPMJJJNPJ||Jz{zKJKMNMNPQNL}u  NPQS [ څu[#PQPNQMNQNQN+QP QNPNKLN QNKJIJKPNJ|s}J{ך||JJ NQPM NM QMJJ} su {KJNP QS [۠ڠ[#PQPQPNPQNQP QP N QNQPQPNKNQNQDNQNMJIzKPQN|tr|Jz~{JKNQNKJM QLJ Ju܁u JM NQS [uuu[#P QP NQ PNKM QN QPQNQNPQN QPQP QNMJJPQPKu~J {כzJNQP NK JL NMJ} }s ڃ؝ JKM KNQS [ u[#P Q NPQ NJMQPN QNQPQPQNQ NM JKNP{}zJ|{|{JJKPQPMJ J JJKJ  s݄tuJKMNMQS [ uuڟܠ[#PQPQPMQ NMQNQNQPNKJM NPQNQP QPQPNQNNMNJ}~JLNJJJJLPNKz!~ s܅ uJNQS [ۃޠu[#PQPQNQLNQNQNKJ LKMQPQPQPQNQN NPNMLMN LKJ}u ~KJ J JKMKz sݡuםqٜ݅KNQS [s[#PQNP NQPQNPNPN QNK JN QP QNQ PQNMKK KJ JJJ NMzރ؞ۜ߄uuܠut߅yKNQS [ ܡ [#PQNQPQPQNQN QPN JLNQN QPQ MPQNPQ|ރ{JJJN~ޢ٢Trrڞݟs JNPQS [ ۄ  [#PQNMNQ NPNMJ MPQNQPQ PQNN QNK|uu ޝ{JJJJ JKN~~٢ޡٛכJMNQS [#[#PQPMNQNQNQPQP QLKMNP QNQPQNPQ NM|٢{JI JJKMJ~ٛ~١  מؠݡJKNPQS [![#PQN QNQNP Q PNLMNQPQNQK|u۟۟{zJ I J KN~uۜ r JNPQS?[#NQNQ NQNQNP QPQPQNMN QPN QLM QPQ N|u ܜ}z J Jz{N|ߝ~ؚ֚uJMNPQS?[!I KQNPMN QMQPQPNQMQ PNKL{؟s |JJJ Jz LNJ|u ֚r JKLNQS5[}|}[!IKQN QMNP)QNQMQNLJJzݟ ۜڟu| JJ LPMJJJz  J MNQS3[|[IJIKQNMN QMQNMQNP QPQPNQPNP QPLJ؝|J IJJLPMJ{ J JLNMLNPQS3[|[IJI KQNQ MNMQNMNPQNPQMQPM NJǡs؞| JJ JKLNzy{ ڃpuu݃JJLNLMNQS3[|[I"JJIKQNQ NQNQMNQMNP#QNQNQMQNPQPN JDŽ |JJJ  J KLPL z{ zƅ uٞuݞ١ JMNLJLPQNP QS?[IIIKQNPMQMQNQNQMNPNPQNQPQP QNLMLJ ޞ؅| JJ JJJKLJJ{J ܞuڟJKMMP QTM!IKQNQNMN QPMQNMLML JJܜu| JIJJJ{J  JKz JPNPQT+SPIJIMP QNQ PNPQPNPQPMLM QMNMQPJJJJsم|JJIJyzJ{J Łu} Jz{zJLLMPQT SPI IN5Q PNPQNM NLMLMNQMNMNPNMJ JJ J م| JJJJJzJ } J zL{JMNPQTuڞ؞ ڞSPIINQNMNMN QMNMNQPNMNQMNQNMNMNMJ}{JJ{۞|JJI Jz J J }JJ{zM{zLLMNMPQTW  SPIJJINQM JJM Q NJJPQPSVQNJ~. ؞ڜ|J J J JzIJJyz JJJ JJzKzLMNPQTW %SPIJ INQN} |L NMJKNQRW |RQNJ~. .uٞ { JLKJ IJJyz JJJ!J JzJJLPQ U%SP INQNޟ~JJJJPQ:Sߟ~zK|uRQMJ. {JNQPKJJJJJz  JJyzJJJLKLNQU} SPIJINQPsޡJJ NQS $~{DŽRQNKu. ف{JNQLJJJ|  J J JL LNQNPQ U} ܟ SPIJINQN  ݅JJNQSVRQNJK {KuK{| ~  |JMNM JJ~#JKJ zJJLMN PNQPQPRV  SPIINQNK{ܞۡ  JNQTuRQNJ J{|KJ|~~}|JKzKJ J~#KLNKJzJNMNPNQNQ PRV# SPIJINQPKJ~ uݠ J NQT~ NQPM J J}r}~}}|Jz~|K JJJ{!|KLPNKMNQ P QPR SU ܟtSPI JJIKNPN~ڞ؟ܠpJNRVQN PNJ J~|Jqr~}|J}ߜ JJ JL NJM NPQPQ~NQ PR sr SPIIKNQK JNQSuRNP QNJ{ }}~qr~~}}ם}|J ڝJKNPQNKMPNQ P~QPRs؟ SPIJJIMQ KJK~qrzJKNQSuRQPNPNzqr~~~} ؞ J J rr٩~LNQPNKLNPQ P~ QPR ޢ SPIJIMQNJK~؝۝ޡzKNQSu RQPNu } q}} }ڞ{J{| rrبMQNP NPQ P~ r oQPR rSP I"IMPQPNMKJ{۟١|NQRUuRQ,MK}~q} } |J{rڝrبMPNMPNP~ r~PR tSP{NP QNK{t߃ڡJNQT߁RQNz|~~ٛr }  | ۝rrTSNP~ NPRUV URT RQLK١KMNQUQNQPƀu}~}p}r}s uurr~PQ  pQPR .u   UQLJJ JLNPQTuVQNƀ}} } }׍}q}כٞ؞.trrq!P ~PRbR ut  UQNMK JLN QTuuQNQMJך}} q}}.. qN!Pr QPRuSRrrܬu  ruU QJ JLN QPT QMJ~uך }r}}ڞu~N#P~  ~PR us rrru urU Q NLNLMNLMN QPTQNJ~ }pq}q۞ ؝r٠%P NPR. urr usquU#QPS QMLJJKs}ooq}}}~0ڠrr}NPRQPRNP QPR rr rqu VQPSQMLJ~ ךq}  ~NPQRP ~rPR  uru ru VPQRQPS QPJJzڛ}~ } r   PQP q NPR uؐ tt ܏u VPQP~~PQ NMQMN J}܁}۞ru] PNQNP~ r PR u ߑ [~WPR~~PQMQMLJ~ uٟrڜم߅  ٩] PRurP~ rNPR u u[~ W QPS~~Q~N J~u ۞۞ڜ؜ڜ qoQPڝ PQة  ~PRu  u~[ ~QP~r~J ٜۜݜ   PNڝ P Qت PRu. t }{[QP~~ Jt uڟ   ~P} P~PRutssܒs[QP~ rrJ~u  QPRRPQ P~rrQPR%usܓ [QP~~}~ rrJsPQ~uب  Q#P RQPRQP~ppQPQRV uuWߑ [QP N}r JsQ~۞ڛ   qت~EP~p~QPNبQ'PUuuu ruu[UQP~ r rr zJ~ ۞ۃ ܫ  ب~%PRQ PQN PQ PQPQNRPU prupq[RPr~}zJןڟr  ~N PQ}NQ Pq~ PQPNQ PQ~PUuuߐu  q u qru[QPN~r rrru}Js۞S ب ~ PQpqp] P٨NQ~~~QNpq~QPUu urpq   r uQPN}}~rrJܫ ب~ PqroQ P؞rq |q~PUuturu uuuTQP~urrr uJܝٛ r  PQqpR PQ؞sqrܠ~}~P Uuupq uu RPr}ڞ   PQݞpN Pstu.sڞ~PUߓ uu RP~r~r ب z~ PQ}بQ P Rݏtus۞~PRVu uu uq~r sRPQp r      |~ P Q~] Pu. ܞP Uu ߅u  L} RPN}u} r~u~~~ rr ݝ|~P ~~NQ Pu uu.uۨ~PUuuuut} RPN} r ܩ~ ~~~QP]NPr }|~PQ PR ߛ . ߓ.~PUur ڞq RPN~rr   ~QP Q~   قz~P Suu~PUq܁qސ ؟ RP~rr~~ ~%P NPp ܜ{Pܓ  uNP UurqٟuRQت  r ~/P] q PN~Pr s pNPUuqpݠܝq  p R~ r~7Pت8 ~ PQ PRܓ  ت~PUrquuRP ~PQP~  ~QPQ~u sܨr~P Uuqq/RPr~~ PQSQP~   !PN utQPUuq?RP ~PSQPQ~ PQ  !PNqr ur uQPU7RP ~ PT ~QP~ ~|8 NP~ܒ.r  .~PU)ڃRPN QPTW}ׂuQP  Puuۨ .QPU'u ~ RPQuo~PU ۞uQP~rr   P ݓ .r tQPU݅RP Qت~ P UuRQ~rqrqNo؛QQP~ݑ.urr PUuRPN ~ PUuUQ RRPrr QPQo%P~.uۡs~PU rVRQ PU UQPQPRP~ rr p~1PN~~~ u.ܨQPUqpq ~u  cSPQ PQ RQPM{|QPש}QPN!P ~t t%q.ܨ~P Urq [ ٟ  cQVUSPةP Q~q} QP~ שPNpQPܒܒ%uܨ~PU  [ u  VSPQר~ PQ~}}~M~QP  NQ P~~P~ܐ%r~PU  [    VSPQ~ P QNQN|~|p}z{QP! N~ PR~q 3uPU [ u  }VTSPQت~ P,NLML|}|z||z{z}|QP~ P ~q٩qqrr%ۄur~PU [ }}߁VSPQةp~ PQNLM$o{{}{y{z{QP~ #NP~rr #suuPU [ } s uuuUPQRQPQN||y|z}zٛQP ש NP~r rq.~PSV [ u  QVU#PQNz{|z|z}z}QP~ ة   ~QPrrrrrޅ ݞ~PU [ u}~} u uVUPQ PQN{z{ z|QP~  ۞ NPqrqrqڪ߄uu~PU [ u  uuV UT PQ ~p؛PQN||~{QP~ ~ P~rq rru~PSUV  [ /ߡSP~poPQN{NM}{qzP1~ Prrqr ۡu.ݝ~PRU  [   uVSQQP~N~ QPQN}|z|}{zי{P~3NP ~qrqqrrutu.~PUu [ r؜څTQpo P QMzz{ |~{~zP/ QPQr r ڛ t~PUuߟ߅ [ u۟ݞ٢ }~~ SP~PQNQ~{|{|{z |MP~ s ~~PQتکrrrr~b ~PUtu [ rp SPQrNPQ{{ NQ|| P~ ~Q P~~PQٝrrrq ~qPUtu [ ۢSPQ~PQ}{|{NQ|ؚ|P؛ש  ~]~QP~ ڝڝ~ Pqrrq~~{|}qٛ~P]!PUtqu [ ڞ SPR  PQN{|{N~ל|Pqq ~PN~QPN ~ P ~rQR~ q{|~~R'PUtqu [  ֝u SQP~ٜPQ|ؙ|Pq QPڜ~PNp rqrq qrQRqQ~q~}~Q'PUtu [  آ TPQ PQ|}{|P QPQRQRQR P Nrڪ QPrr qqrQprqR~ ~~)PUt [ ۝ u uaSV TPQp ~ PQLQP~ ~PSp}PNQPNpr כ~Q بQq~|Q)PUt [ ؟p SqT TP~ ~PM| QPN~~P} P Q P r۩ qqr~PQ~q~z{R)PU [ ڛآ SRU TPQrpQPQLQP~QPS } P Q Pڎ٪rrqP~~~pQ)PU [ ٢#TPQ  NPLP~ب QP~ PQ PQ~prک rpNQPQ~ P r ~)PU [  sآ TP ~}|~  PS ~PQprr P~P qR'PU٢ [ ڟע cTe TP pr  Q PSP Q~prrrqrpN P~p]P ۞R'PUsס [ ٞuuRT } UQPQ   QP Tߢu  u P prqrr qrqq~ PQ P רߛ qR'PU [!  ڞu uRT SPQ۪ Q רQPTu   Prrrrq~P~u~qpR'PU [" sؠ SPQ ~~QP u P qrrr ~R P~pR'PU # ל ۄT SQPQ~P~ QPuU% Prrrqrrr~N}~N~Q'PUܟ$ uu۝ڞuQPة~P ~ QP.aU% P rqr qr }qqs۝ٛN)PU ٝ % ܜٞٞۡ ߃~QPQ~QP~  RP'Q PQ r~r}~N)PU١ٝ& ל u QPQب~ PQר ש QP  N Pqrrqr u ބ ڟ~'P Uݞٞۢ' ڟrq۞  QPQ P~߁ ם Q PSN PQqst.u۟u.u t 'P U܄݃۟( ޡٞrqsڞ ~ Q)P~۰ߞ  R PTN PQrr suu. 'PUڞ ۡ) ٟrqr u{Q+Pߢݡ qrqQ PN Prqrstss .u Q%P Uuݢل* s r sڟء uuQ+Puuݠߠ  qڌqpN PS!QPqr۟ts Ssuu N%PUڝ ܞ + ٟsݠۜQ+Pu  qQ P  QPQتۂSu u.u. ܝSRpQ!PUםڟ܃ , ܟWVQ+P~ ب rq~Ra P~ݒ.ܬܠQ PQ؜Uu.ts. oQPUݝڟܟ - uكUCPݟبqrqS P~rr P~ܑursu sUS~ QPU  . ١UAP]  qrrQ P~  ۑuQ P*Qةܑtuݢ.s܄u .pQPUܞ۠۟ /   ١UAP~ݟب qQ P~sݑst.R PQ؜܃s .s~ q~PUٞܢ 0 ܞ UAPQةr بrq QPN s}~ tR P Q~susݛq qQPU ݞuu 1%UCP Q~ة  qrNPN~P~ssN PRPQq s ݛq~PU%2%UCPQ~  תqqqPN~~Q P~כ~NNQPQ q ؜r ~PU%3OP~PQ P~+P~QPQNPNqrrqrכ~9P4MPQP N~SPQqr ~P~Q9P5KP ~~ P~  ר~PQ~QEPQ rqrr~ P~Q;P6IPR ~ P  ~~QAPQ rrr ~P~Q=P7IPQQ P+ب~N P NQN PQQP~ N~rNCP8IPQoQP quPSu}!P~pQCP9IPQP  ר! u ל ڞ}%PQ~ ~EP:KPQP] u u }+P~ No qNCP;3PQU PTUQP QPר   ۜܠ  u܃}-P~pPQppQ!PSRP<3P~ QPNRPQQP~ר ruuq}/P Q PQPQ%PUSP=3PQP~RPQ ߠQP~ }qpٛ ߚq}mPUSP>3PQPNRPQ٩~ Q P~ڝ٩}8qߞׄ؛upכ؀}mPUSP?5PQP~RPNu ~ P~ ؝٩ڝ r۪s۞}rמu uכ} P }~|YPUSP T@5P~QPQPQ~P~ r۪r  rr(ڞ}uآ}}}}} P }YPUSP QSTA5P~QPRPQu ר~Q ~r$ڞrڝڝڝ r ڞ r}آ}}}P Q؜YPUS T}B5PQPRPRpoٝ۞ڝڝ ݠrq}u }} ~ P~]PUuC5PQPRPQ qqUqrrڄݻq}r}ݡ  }} N PPQ!TSRV  ߅D5P~RQPNQPQםتrqrrqrruu~r} }r}}}'PQ   u ~ }E5P~RPRP Q~ rq ~}} qr}qq~%PQ ؚךכ؞~ }F7PRP~R P~uٟqrqqr߂~r rq؏rqrq}}ٻr}~!PQ  u ~ G7P~RPR PQߝ    ~qٛqrqpqr!PQך pq.}}~ ~}H7PQQPQ P ~qrېsڝ r  }q}qrrq}r}~}rq!PQ  usu}u uIOP Qu qrrܞڐs }}r~}r}rq} Q}q؛}} QPQ עؚךךusu  u uJQP~~ ٝ٩}~~qrڜ۝ٛ } ~PQ    KSPuqrڜڞr۝ ~~~r s  ڞ ~PQ9qLSP~ }rrڜ ڀrq}~}rrt} QPQ u u ߠMUP~u r٩ sq}~~~rٝ~~ rr ~QPQ   ~}NWP ~ר  ~ s~~~ڜ}~u~rqqr~QPQؚ u uO[P~؋   ~~u ةrrqrqr~QPQ כۓ ݡPaP~ר pqpQP~רة oPQ ݜqpqpr~QPQ  urp o׏ ݡuuQePpSS P~Po؋~PQ~ ר~PQة ~rqprQPQ  @u؋p~ݡ߃~~RgP QPQSQPQPQPQPQ rqrQPQ آ &uqp׎}߁SkPQEPQ#PQPQP QPrqrQP  uup׊)TCURsP Q9P~P uq׊uuuu U   R!P!USqP~ QPu ۟.r.uuV  } } ~R!PUCP!TSPQ~ Q#Pusr ׎u.W  ~}}R!P }UAPT  UPQ-Puuuqpq'X  } }~R!P~U!PRT~uuUCPu u s  Y~ "}~} ~R!P}߃uU!PU! u} סUCP uuq}}Zu u u}RPQSR P~}}U!PUt uUCP١p qu}~~}[uu }} RPQSU uW P}}U!PUׄ u ~|~| UCPڟܡ u.u.u.u.u.u }~\ u}~TRUuuW P}U!PU ֟ }~} UCPߓu} ]  ߂uu߀ uuW P~~U!PUuޅ u}UCPtߟ ~~^u~uW P ~~}}U!PUu~UCP؜ ڡ܃߅ u _ u~W P}}U!PUp۟u u UCPu(u׃pspܟ~}~`u W P}~u}~}U!PUۢuuqs UCP oكu ؞۠u~~~}a}  ~ W P~}}U!PU stۅ UCP r  b *}u}~}~W PuU!PU uu/UCPu uruc܁ W P!U!PUAUCPurWPNd_WKPU'uUCP ڝu=WPNefexult-1.2/data/black_gate.shp0000644000175000001440000000721407241747101011702  S[(((  ( # (((-(2(=(A( D ( I (((( %(% #%(%((,( 1 (=(A( D%(% I%(%(((($'((('('('( 0'(%'(=(A(E'(J'('('('('($'('%'%'0'4'='(A'(E'J'''''$'('+$-' 0 '='A'E'J'''''$'('-' 0'%' =& '&E'J' % ' % '' # '('-'0'4' >%'% D ' I ' $%$ $%$ # $($-$0$4$?$ D $ I $  ( ( (  (  (" (* ( 0 (6 (: ( B (J ( O ( V (  %(% ( (  (%$%  (%(" ( ) ( / (%(6 (9 (% A (%$% I ( O %(% V (%$% ( '( '( '( ( (" ( ( '(%'(/ (3 % 6 (%A (' H '(%'(Q (V '('(  '  ' '('('%"'((','/'( 6'('A'H'L'Q'( V '' '%$' '%$% '%'"' ( '/' 6'$'A'D' H 'Q' V'%$%'' ''''"' ('%'/'3'6'9$'A'D%' H'%'Q'V''' '(  '  ' "% '(',' /% '%6':$'( A% 'H'L'Q' V '$$ $  $  $ #$%($,$ 0 $6$;$ B$%$H$L$Q$ V $[%%%  % # %(%-%2%=%A% D % I %%%% $%$ #$%$(%,% 1 %=%A% D$%$ I$%$%%%%$%(% 0%$%=%A%E%J%%%%%$%(%$%$%0%4%=%A%E%J%%%%%$%(%+#-% 0 %=%A%E%J%%%%%$%(%-% 0%$% =$ %$E%J% $ % $ %% # %(%-%0%4% >$%$ D % I % #$# #$# # #(#-#0#4#?# D # I #  % % %  %  %" %* % 0 %6 %: % B %J % O % V %  $%$ % %  %$#$  %$%" % ) % / %$%6 %9 %$ A %$#$ I % O $%$ V %$#$ % % % % % %" % ( %$%/ %3 $ 6 %$A % H %$%Q %V %%  %  %  %$"%(%,%/% 6 %A%H%L%Q% V %%%$ % %$#$ %$%"% ( %/%6%9%A%D% H %Q% V%$#$%% %%%%"% (%$%/%3%6%:%A%D$% H%$%Q%V%%% %  %  % # %(%,% 0 %$6%:$% A$ %H%L%Q% V %## #  #  # # #(#,# 0 #6#;# B#$#H#L#Q# V #exult-1.2/data/quotes.txt0000644000175000001440000000506607452146653011207 \CEXULT QUOTES \C"Feel free to release without me." \L- Tristan \C"Heh. New law of physics: Actors are not \Csupporters." \L- Dancer \C"Code is now less 'Dubious'" \L- Colourless \C"All this stuff is driving me to Java!" \L- Jeff \C"I haven't touched the original in a while \CExult is so much better" \L- Tristan \C"The few crashes just made it \Cfeel more authentic!" \L- Jeff \C"Holy S!*@!" \L- Jeff \C(on Horizons Tavern \Cafter seeing a screenshot \Cof Exult with 2xSaI) \C"Working on Forge (but Love broken now)" \L- Jeff \C"Paladin reproduces infinitely" \L- Dominik \C(on Jackchaos) \C"Oh Wow. Boom! \CIt crashed good an proper for me." \L- Colourless \C"Exult - X-windows Ultima7 map browser." \L- Top of exult.cc \L(Alpha version) \C"Luckily the world is not a donut, \Celse Homer Simpson might have eaten it." \L- Max \C"It's not our fault, the data files \Care telling us what to do!" \L- Dancer, \C(explaining things clearly) \C"If we stack kids, \Cwe should use a proper stack!" \L- Max \C"I know what a stack is. \CBut what's a `kid`?" \L- Tony \C"A young person..." \L- Willem Jan \C"Damn, we're probably popular enough to \Cwin a US presidency election." \L- Dancer \C"Only if we release on punchcards." \L- Jeff \C"BTW I don't stack kids anymore, \CI now put them into a queue." \L- Max on ##exult \C"Uh oh, Iolo is upset at me \Cfor moving a tree." \L- Willem Jan \C"You guys rule !!!" \L- Chimera on ##exult \C"Yeah, we do :-)" \L- Willem Jan on ##exult \C"Anybody home? Exultbot?" \C"Ah, well, guess I'm in the wrong timezone" \L - Jeff on ##exult \C"We leave it any longer, \Cand I could become more difficult" \L - Ryan, \L on world-wrapping \C"On a more positive note, \Ctry dying in SI. \CIt's working much better now." \L - Jeff on Jackchaos \C"Say, maybe we could make some money \Cselling tours to Britannia" \L - Jeff, \L replying to spam \C"Using missing functionality to \C work-around a bug? Clever." \L - Amy \C"Hmm, 'stumbled' is an apt description \Cof my development process in Exult. \CMaybe I should write a software-engineering \Cbook about it :-)" \L - Jeff \C"There are two types of people. \CExult Developers and everyone else" \L - Colourless \C"There are definitely bugs to be \Cfound on the List Field." \L - Jeff \C"I love freedman" \L - Fingolfin on ##exult \Cusecode = -1; // Let's try this. \L - actorio.cc:89 cvs 1.1 \L (jsf 13-May-00) \C"a comment to inspire confidence :-)" \L - Wumpus on ##exult \C"People will love this" \L - Dominus on April \L Fools 2002 \C"and hate us" \L - Colourless on April \L Fools 2002 exult-1.2/data/midisfx.flx0000644000175000001440000006135407201062614011270 0hr& 2 B ~D V b2`n6$,lfnDnrx& ~&!~!~"""(##H$$\%B'<)Z**+l,--$..H//R00`11n22x334556778899(::^;;<=>>6??F@A<JCCdDDlE<G^IIfJKK:MZNNlOOrPPrQ<SzTTzUVV:WWX^YYpZ[[]$^_(`>fbFORMXDIRINFOCAT XMIDFORMXMIDTIMB>BAEVNTY@Qz#@XnnrBrA> P@@ss @ @ssO]J_-EY< Tb Nz CURkNE JU NzKknNEJU SUGUPk SUKk KkSUPk GUSUJU NEKkNz JU NERk CUNz n/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBtEVNT>Y!@Q '@Xnt@s @s0d7n/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBvEVNT>Y!@Q '@Xnv@s @s0d)7n/FORMXDIRINFOCAT lXMIDFORM`XMIDTIMB|EVNTHY!@Qz#@Xn|@s @sbu1_g2g[32n/FORMXDIRINFOCAT pXMIDFORMdXMIDTIMB}EVNTLY!@Qz#@Xn }@s @s!,n/FORMXDIRINFOCAT pXMIDFORMdXMIDTIMB}EVNTLY!@Qz#@Xn }@s @s!,n/FORMXDIRINFOCAT zXMIDFORMnXMIDTIMBEVNTVY!@Qz#@Xn[@s @s@UIo9U tAY \~n/FORMXDIRINFOCAT hXMIDFORM\XMIDTIMBMEVNTDY!@Q '@XnM@s @s$U6 0U7zn/FORMXDIRINFOCAT hXMIDFORM\XMIDTIMB|EVNTDY!@Q '@Xn|@s @sZoaon]/FORMXDIRINFOCAT nXMIDFORMbXMIDTIMBxEVNTJY!@Q '@Xnx@s @sDdHdPdn/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMB~EVNTBY!@Q '@Xn~@s @sx!)xizn/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMBvEVNTBY!@Q '@Xnv@s @sddn/FORMXDIRINFOCAT `XMIDFORMTXMIDTIMBiEVNT>n/FORMXDIRINFOCAT hXMIDFORM\XMIDTIMBEVNTDY!@Q '@Xn@s @sHUEVNT\Y!@Q '@Xn>@s @s g& H9NJRZVbXRT@n/FORMXDIRINFOCAT rXMIDFORMfXMIDTIMBvEVNTNY!@Q '@Xnv@s @sU UUU n/FORMXDIRINFOCAT lXMIDFORM`XMIDTIMB_EVNTHY!@Q '@Xn_@s @s-[ EX0n/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMBxEVNTBY!@Q '@Xnx@s @sUUn/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMB(EVNT>Y!@Q 'Xnp(s @slB1Cn/FORMXDIRINFOCAT XMIDFORM XMIDTIMB}EVNTY!@Qrp@Xn}@s @sdt*/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMB+EVNTBY!@Qz#@Xn+@s @s((Jn/FORMXDIRINFOCAT XMIDFORMXMIDTIMBzEVNTY!@Qz#@Xnz@s @s CUHU       & + 1 6 < A F K P U [ _ d h k o r t x { } & { w s o k g c _ ] Z X V Un/FORMXDIRINFOCAT zXMIDFORMnXMIDTIMB|EVNTVY!@Qrp@Xn|@s @s U Y /FORMXDIRINFOCAT XMIDFORMXMIDTIMBxyEVNTY!@Qz#@Xnnx (@ys@ @ss @sBU+@U >c ;U8DU ?Q CT, DAA%<;:5nn/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBpEVNT>Y!@Q '@Xnp@s @sTuun/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMB_EVNTFY!@Qz#@Xn_@s @snUgUn/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMBEVNTFY!@Q '@Xn@s @sY!@Q '@Xn:@s @s$Fn/FORMXDIRINFOCAT dXMIDFORMXXMIDTIMBEVNT@Y!@Q '@Xn@s @s4u n/FORMXDIRINFOCAT `XMIDFORMTXMIDTIMBsEVNTY!@Q '@Xns@s @s0d n/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMBYEVNTFY!@Q '@XnY@s @sPgCPg%nD/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBBEVNT>Y@Q '@XnrB@s @s7U,0U,Bn/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMB~EVNTBY!@Q '@Xn~@s @s5T2UXn/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMBUEVNTFY!@Q '@XnU@;s @s?B DGIKLMOR UWXYZ[]^_`acdefghjlnprs v xyz}~n/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMByEVNT>Y!@Q '@Xny@s @s<22n/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMBvEVNTFY!@Q '@Xnv@s @sMrEHeE0rEEn/FORMXDIRINFOCAT XMIDFORMXMIDTIMBw|EVNTjY!@Qz#@Xnnw|@@ss @ @ssUwUwUwDgn,n/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMBwEVNTFY!@Qz#@Xnw@s @sUwUwwn/FORMXDIRINFOCAT XMIDFORMXMIDTIMBmEVNTY!@QrpXnm@s @s Uu Uu+/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMBEVNTBY!@Q '@Xn@s @s22^n/FORMXDIRINFOCAT nXMIDFORMbXMIDTIMBzEVNTJY!@Q '@Xnz@s @s+UZ$UZnD/FORMXDIRINFOCAT hXMIDFORM\XMIDTIMB~EVNTDY!@Q '@Xn~@s @s0>-E5(An/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMB'EVNT>Y!@Q '@Xn'@s @s>--n/FORMXDIRINFOCAT hXMIDFORM\XMIDTIMB"EVNTDY!@Q '@Xn"@s @s;,Un/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMB|EVNT>Y!@Q '@Xn|@s @s Yn/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMB~EVNT>Y!@Q '@Xn~@s @s U!!n/FORMXDIRINFOCAT XMIDFORMXMIDTIMBmEVNTY!@Qrp@Xnm@s @s uu+/FORMXDIRINFOCAT XMIDFORMXMIDTIMBzEVNTY!@Q '@Xnn]P]P[P[Pzz@@s; @ss @s#U%V-U.Q %_ .V9f#pnn/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBsEVNT>Y!@Q '@Xns@s @sZ n/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBsEVNT>Y!@Q '@Xns@s @sR n/FORMXDIRINFOCAT pXMIDFORMdXMIDTIMB|EVNTLY!@Qz#@Xn|@s @sez\T2\n,\i\]n/FORMXDIRINFOCAT XMIDFORMXMIDTIMB}EVNTnY!@Qz#@Xnn}@@ss @ @ss FL f) f-/$).$9n)n/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBEVNT>Y!@Q '@Xn@s @s0z!n/FORMXDIRINFOCAT XMIDFORM|XMIDTIMBtEVNTdY!@Qz#@Xnt@s @s(u$r !u /$j kU$V]#jn/FORMXDIRINFOCAT XMIDFORMXMIDTIMB*>EVNTY!@nQ '@XnF*l;>H\!@s @sCUGU#LU"!JUO[MVBH[?@LUBGUB@M_hH[dcOVJVM`H]O_oGVknnn/FORMXDIRINFOCAT vXMIDFORMjXMIDTIMB EVNTRY!@Q '@Xn @s @sHU MXOUQUTbn/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMB~EVNTBY!@Q '@Xn~@s @s3P0Pn/FORMXDIRINFOCAT pXMIDFORMdXMIDTIMB>EVNTLY!@Q '@Xn>@s @s U U U U n/FORMXDIRINFOCAT XMIDFORMXMIDTIMBxEVNTfY!@Q '@Xnnx@@ss @ @ss!n*2 + n/FORMXDIRINFOCAT jXMIDFORM^XMIDTIMB~EVNTFY!@Q '@Xn~@s @seo ]|n/FORMXDIRINFOCAT XMIDFORMXMIDTIMBzNEVNTY!@Qz#@XnnzN@@ss @ @ssJUQU BDF H)J1L9NAPJRRTZVbX jZs\{^ s\E-"M-<jZbXZV RTJRAP1L HFDB@B?v=n;f9^7U5M3E1=/?4-v=,+n;$)f9^7U5 ,+M34-=/E1M3U5^7f9n;?@=/4-,+$) '4-^7@n#BDF H)J1L 9N AP9N 1L)J HF D B@n/FORMXDIRINFOCAT pXMIDFORMdXMIDTIMBaEVNTLY!@Q '@Xna@s @s7ADCFF[GEn/FORMXDIRINFOCAT bXMIDFORMVXMIDTIMBzEVNT>Y!@Q '@Xnz@s @sGndAd^XB D F H)J1L9N AP JRRTZV bXjZs\{^a ceg$i,k4m =o4m,k$ig ca{^jZbXZVbXjZs\{^a ceg $i ,k$ige ca{^s\jZbXZVJRAP9N)J HFDB @n/FORMXDIRINFOCAT fXMIDFORMZXMIDTIMBEVNTBY!@Q '@Xn@s @skUAU!-n/FORMXDIRINFOCAT  XMIDFORMXMIDTIMBwEVNTY!@Qrp@Xnw@s @s :.$0<(.-$':0<309.:0$X:/0.2"3<H."p06$. PHI J OPDTDRTR;T0R$MHPT HHTJ R@OGTDQDOTRBQ@OJR\QEOLMGQ`ON MKIOXHIKXHlHN\JDHPKJJHMEKXKE(M4JIKLHHJ@FGH\?(:N >4W <H?T<@AT ?XCXA(C|C^0FXCVP:K>\\<8?W > >V$?0>W<L?V>HAW?HAhA^R?X?Z>$>W?<D:T<$^?`P<>JXX:V<tCR:C,CWPDVC\FWD@FKQTKJN`KZ JDFWKdF8Ff F,FQ`HW FTHJWPHPJ\FUHW<X?W>PAW ?\CZA8AX CCXA@A\CD?XA(>X?@

d>W<@l:V<4>W :0<4R<D?W >TAQ?TC^A AXCU$?8`:R<$>X:h@:Q< W?T?R>PAW?LAdA\8?TAL>T?T?^>AQ?D?NA@>P ?0>F<DD:Q<QAd:P>dP <L8?Q<DAT ?PCW ALAPCL?QAL>Q?L?W>H>Q?`

`:N<HW<\>\>\@X:N<PU<H,:Q<(,#66?#J #66H#Il#4#E# 6D#F6E$# 66D#I(6#6G#I0#6@#I6A(6#6F#I$6#6G#KX#H6#E#L#Q6D,# 66D#K(6#6I#O86#H#K6I,# 6#J6D,# 66H#IX#H6#D#L#S6I(#66G#I#66I#I6 #\6E#E4#6#N6E(#66F#I<#6D#E6E# 6#M6D(6#6E#O`#@#I6#L#Q6J(#6#Q6D(#6#J6G$6#X6F#N(# 6 6@#J(6#6H#I`#P6P6I<66H#I,#6#M6IH#64#I6I,#66G#I,#66I#Id#<#G6#H#N6I<#66I#J06#6I#K4#6D#M6GH6 #l6H#K,#6 6J#NL# 6,6E#K$6##I6F(#66I#K<#6@6G#M$6#6H#K$6#6I#ID6#<#M6J,#66H#J 6#6I#N0#6H6G#K$6#6D#M$#66I#Mh#8#M#60#S6H(# 6 #O6C,#66K#QD6#8#N6I(#66F#I$6#6I#Ol#4#I# 6<6I#O,#6 6H#Q(6#6I#N ##M6(#,6J 6 6H#N #66I#N0# 6D#J6J 6#6G#N #66F#N##F #6(#M6I,#66J#N(6##N6JD#6<6I#N$6#6I#K$6#6J#Q0# 6D#O6H(#66G#K #66I#OD#6,6I#O(6#6I#J #66J#K`#@#G#6L#S6D(#66I#N06#6K#O8# 6<#M6G(6##K6H(6#6K#K@#68#M6I$6#6I#K(6#6J#K4#68#M6H$6#6I#I(6#6J#J8#6@#K6E(6#6H#J$6#6I#M@6#@#K6G 6#6F#K(6#6I#J8#6D#E6F,6#6F#J,6#6I#MT#L#M6#<#K6I,#6 6D#J4#6#O6Ip#(6#H#P6J#N4#66F#I0#6#S6IX#6 #I6J #66G#E(#66M#H8# 6<#J6D0#6#I6D(6#6I#H0#6<6G#F,#6 6I#G06#6I#O6#/MTrkViolin0Y|OV O4ON`PIOXRFP RRI`TKRXRITHPERLOVP0PT OR<PPPKR0OO$POMIOKMPMFO\KH$M`QIRXQOL`QK OPQMH@OHM,MI O KNMKMIKHTM$K@JO@FF J4HF FJKHIHLJHH@JK`KKJHKMFPMpMKhKF`JCM KhJFPJHHXHBJLF@HOU?OU@OUAOUBOUCOUDOUEOUFOUGOUHOUIOUJOUKOULOUMOUNOUOOUPOUQOUROUSOUTOUUOUVOUWOUXOUYOUZOU[OU\OU]OU^OU_OU`OUaOUbOUcOUdOUeOUfOUgOUhOUiOUjOUkOUlOUmOUnOUoOUpOUqOUrOUsOUtOUuOUvOUwOUxOUyOUzOU{OU|OU}OU~OUOUOUOUO9O O   O  O  OO  O   O     O ͪO   O  ͪO  O O  O O O   O  O  O  O   O  O  O 7O 9  O   O   O  ͫ  O  O   O  ͫ  O ͫO  O 9O UOUOUOUQUWexult-1.2/data/serpent_isle.shp0000644000175000001440000001034307241747101012317  l(((  (  ((($(/(3( 6 ( ; ( F (O( T ( [ ( h (((( %(% %(%(( # (/(3( 6%(% ;%(% F(%( N ( T(%( [%(% g(%$%((((('(('('('( "'(%'(/(3(7'(<'(F(J(& M'(%'(T(X(&](g%k('('('('(''%'%'"'&'/'(3'(7'<' F'('('%M'Q' T'('('%]'( h'('(%''''''$' " '/'3'7'<' F'%$% M ' T '%]' g'%''''''' "'%' /& '&7'<'F' M'%' T'%']'g' % ' % ''  '''"'&' 0%'% 6 ' ; 'F'M'Q'T'W%']' g ' $%$ $%$  $$$"$&$1$ 6 $ ; $F$M$Q$T$X$]$ g $  (  (  ( $ ( + (2 (7 ( : ( F ( L (R ( Y (  (%$%(  (%$%  (%( $ (%( + (%$%2 (7 ( : %(% F %(% K (%$%(R ( Y (%$% ( % '( (! (&$ (( (&+ '( 2 ('(7 (< (G '(K (P %R '(Y '( %('('  ' '('('% $'('('% + '2' &('('<'(G' K%('('R' Y ' %' '%$%  '% $'%$% +'%$%2' 5&'<'G' L%'R' Y'%$%''' '%'$'+'2'6%'<'G'K'O'R'Y' % '%  '' %'$' + '2'7'<' F ' K% '% R ' Y '  $  $$!$$$ + $2$7$<$ F $ L $ R $ Y $l%%%  %  %%%$%/%3% 6 % ; % F %O% T % [ % h %%%% $%$ $%$%% # %/%3% 6$%$ ;$%$ F%$% N % T%$% [$%$ g%#$%%%%%%% "%$%/%3%7%<%F%J% M%$%T%X%$]%g$k%%%%%%%$%$%"%&%/%3%7%<% F %$M%Q% T %$]% h %$%%%%%%#% " %/%3%7%<% F%$ M % T %$]% g%$%%%%%%% "%$% /$ %$7%<%F% M%$% T%$%]%g% $ % $ %%  %%%"%&% 0$%$ 6 % ; %F%M%Q%T%W$%]% g % #$# #$#  ###"#&#1# 6 # ; #F#M#Q#T#X#]# g #  %  %  % $ % + %2 %7 % : % F % L %R % Y %  %$#$%  %$#$  %$% $ %$% + %$#$2 %7 % : $%$ F $%$ K %$#$%R % Y %$#$ % $ % %! %$$ %( %+ % 2 %7 %< %G %K %P $R %Y % $ %  %  %$ $ %$ + %2%$ %<%G% K$ %R% Y % $% %$#$  %$ $%$ +%$#$2% 5$%<%G% L$%R% Y%$#$%%% %$%$%+%2%6$%<%G%K%O%R%Y% $ %$  %% $%$% + %2%7%<% F % K$ %$ R$ % Y %  #  ##!#$# + #2#7#<# F # L # S # Y #exult-1.2/data/font.shp0000644000175000001440000002217507201541133010570 }$ q  *4>HR\fpzd"{]"~ /}; R  i ; u  4 U)J} rnFi\`eE_4vr7CW _ >!!!W""#W###E$                                                                                                                                                                                                      exult-1.2/data/exult_quotes.shp0000644000175000001440000000404207153222317012362 " ^  ( ((((( " ( 0 (6(:( > ( D ( K ( S ( (%$% ((((( "%(% /(%(6(:( =(%( D%(% K(%$% R(%$%('( %((%((($(/(3(6(:(=(A(F(K'(R(W%  ' &'('&'('('($'(/'(3'(6'(:'(='(A'(F'( K ' R%('(' '%$% '&''''$'/'3'6':'='A'F' K'%$% S%'' '%%''''$'/'2'%6':'='A'F'K'R'V'  ' '' % ' % '$' /%'%' 6% ' =% '%F' K ' R% '%  $ $$ $%$ $%$$0$3$ 7$%$ > $F$ K $ S $^  % %%%%% " % 0 %6%:% > % D % K % S % %$#$ %%%%% "$%$ /%$%6%:% =%$% D$%$ K%$#$ R%$#$%% $%%$%%%$%/%3%6%:%=%A%F%K%R%W$  % $%$%%%$%/%3%6%:%=%A%F% K % R$ % %$#$ %$%%%%$%/%3%6%:%=%A%F% K%$#$ S$%% %$$%%%%$%/%2%$6%:%=%A%F%K%R%V%  % %% $ % $ %$% /$%$% 6$ % =$ %$F% K % R$ %$  # ## #$# #$$#0#3# 7#$# > #F# K # S #exult-1.2/data/credits.txt0000644000175000001440000000556210012745361011310 \CEXULT ACKNOWLEDGEMENTS \CTHE CODING TEAM \CJeff S. "DrCode" Freedman \C \CThe man who started it all: from usecode \Cto map browser to usecode to animation \Cto usecode to ExultStudio to usecode. \CHe's the leader ! (Did we mention usecode?) \CDancer Vesperman \C \CMusic, sounds, XML configuration, usecode... \Cwhat more could you possibly ask for ? \CWillem Jan Palenstijn \C \CPorting to obscure OSs (Windows) and less \Cobscure ones (BeOS), cheats, autoconf, \Cexultbot and lots more ! \CTristan "Nadir" Tarrant \C \CIntro, ending, menus, autoconf/automake, \CGIMP plugin, FLEX packing, CVS config, \CFree Software advocate, Forum police \CMax "Fingolfin" Horn \C \CPorting to MacOS, error handling, \CC++ standard police, the webpage \CLuke "Coder Infidel" Dunstan \C \CHunter of lost info in U7's data files, \Cweapon animations, bits of combat. \CRyan "Colourless" Nunn \C \CXMIDI meister, endings, roof removalist, \CSI Intro, NPC flag IO, Avatar identity, \CBG Paperdolls, "Big Commits(tm)" \CPatrick Burke \C \CUsecode decompiler/disassembler/docs \CDominik "Dominus" Reichardt \C \COur trusty FAQ maintainer \CChristoph "Jameson" Reichenbach \C \CPorting to Alpha \CRuediger Hanke \C \CPorting to MorphOS/AmigaOS \CDerek Liauw Kie Fa \C2xSaI scaler \CSuperEagle scaler \CSuper2xSaI scaler \CAndrea Mazzoleni. \CScale2x non-blur scaler \CChristian Ohm \C \CGameplay Options menu, fast mouse, \Cmiddle mouse button support \CMark Siewert \C \CExult Studio for Windows \CSimon Quinn \C \CAudio enhancements \CAurelien "Artaxerxes" Marchand \C \CZaurus port and Exult Studio tools \COTHER CONTRIBUTORS \COlivier Marcoux \CGary Thompson \CMatthias Ho \CMichael A. Cornelius \CTroy Forrest \CByun DongHo \CMaxim Shatskih \CJakob Shonberg \CWouter Dijkslag \CMark Winterrowd \CAlex Botero-Lowry \CPaul Hebble \CRobert Bihlmeyer \CARTISTS \CAdam Delman \CPhilip Gottschalk \COblivious \CJoseph Applegate \CWishStone Dragon \CSam Matthews \CTHANKS \P0 \CSourceForge & VA Linux \CFor making it easy to code together. \CJackchaos.com \CFor hosting the old Exult message board \CTravis "Kirben" Howell \CFor making daily Windows binaries \CSam Lantinga \CAuthor of SDL, for making porting easier \CMatt Kimmich \CFor giving us permission to use his MIDI \Ctracks \CJoseph Morris \CFor the digital SFX packs \Cand... \CORIGIN Systems Inc, \CRichard Garriot, \CWarren Spector \Cand the Ultima VII & Serpent Isle teams for \Cmaking these great games in the first place exult-1.2/data/exult0.pal0000644000175000001440000000300007153425502011016 ***********????????????;;;444---'''  :<?149)+4"$/' 5:?+2:"*5"0+& !   ***********????????????;;;444---'''  :<?149)+4"$/' 5:?+2:"*5"0+& !   ***********????????????;;;444---'''  :<?149)+4"$/' 5:?+2:"*5"0+& !   ???????????????????????????????????????????????????????????????????????????????????????????????????????????????exult-1.2/data/estudio/0000777000175000001440000000000010062225326010641 5exult-1.2/data/estudio/new/0000777000175000001440000000000010062225327011433 5exult-1.2/data/estudio/new/fonts.vga0000644000175000001440000003624510054030555013207 Written by ExultStudio<<,@Th|  . B V j~0DNu/Y=(-Q D})2A I!!5""^##'$$'%%&6''Z((j))z* ++9,,&--.u....H//!000f11z22E33744#556662778l88;99 :|::S;; PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP PPPPPPPPP PPPPPPPP PPPPPPPPPPPPPPPPPP P PPPPPP P P  PPPPPP PPP PP PP PP PPPPPP  PP  PP  PPP P P PPPPPPPPPPPPPP P PPPP P  PPPPPPPPPPPP PPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPP PPP PPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP P PPPPPPPPP PPPPPPPPP P P PPPPPPPPPPP P PP  PPPPPPPPPP  P P PPPPPPPPP P  PPPPPPPPPPPPPPP  P PPPPPPPPPP PPPPPPPPPPPPPPPP P  PPPPPPPPPPPPPPP  PPPPPPPPPPP PPPPPPPPPP PPPPPPPP PPPPPPPPPP  PPPP  PPPPPPPPPPPPPPPPP  P PPP  PPPPP  PPPPPPP PPPPPPP  PPPPPPPPPP  PPPPPPPPPPPP  P PPPPPPPPPPPPPPPPP P PPPPPP  PPPPPPPPP PPPPPPP  PPPPP P  PPPPPPPPPPPPPPP  P PPPPPPPP  PPPPPPPPP PP PPPPPPPPPP PPPPPPPPPPPP P PPPPPPPP  P  PPPPPPP PP PPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPPPP PPPPPP  PPPPPPPPP  PPPPPPP  PPPPPPPPPPPPPPPPP  P PPPPPPPPP  PPPP P   PPPPPPPPPPPPPPPPP  PPP PPPPPPPPP  PPPPPPP PP PPPPPP P  PPPPPP P PPPPPPPPPPPPP  P PPPPPPPPPPPPPPPPPP  P PPPPPPPPPPPPPPPPPP PPPPPPPP  PP  P  PPPPPPPPP PPPPPP  PPP  PPPPPPP PPPPPPPP  PPPPP  P PPPPPPPPPPPPPP  PPPPPPPPPPPP  P PPPPPPPPPPPPP  PPPPPPPPPPPP  P PPPPPPPPPP PP  PPPP  PPPPPP PPPPPPPPPPPPPPP  P  PPPPPPPP  P PPPP PPPPPPPPP PPP  PPPPPPPP  P  PPPPPPPPPPP P PPPPPPP PP PPPPP  P PPPPPP  PPPPPPPPP PP PP PPPPPPP PP PPPPPPPPPPP  P PPPPP  PPPPP  PPPPP PP PPPPPPPPPPP PPP  PP  PP  PP  PP PPPPPPPPPPPPPP PP  PPPPPPPPPPP  PPPPPPPPPPPP  PPP  P PPPPPPPPP PPPPPP PP  PPPPP P PPPP PPPPP P PP PPPPPPP  PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPP  P  PPPPPPPPPPP  PP  PPPP  P PPPPPPPP  PPPPP  P PPPPPPPPP P PPPPPPPPPPPPP PPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPexult-1.2/data/estudio/new/shapes.vga0000644000175000001440000003433410054030555013336 Written by ExultStudio $(*,0111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222E                                                                                        E!*-             AAA=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=AAAAA=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=A=AAexult-1.2/data/estudio/new/gumps.vga0000644000175000001440000000033210054030555013175 Written by ExultStudioRRexult-1.2/data/estudio/new/palettes.flx0000644000175000001440000002073010054030555013703 Exult palette by Ipack   %0 8 65,611($6 9839=&>02 $ *((!)$% ( +*&+- .$%   222,,,$$$"""777"""555%0 8 65,611($6 9839=&>02((((?(6?25?1????????8??2????*.?6>?+.???  #!!" "$# $& ' #&!'# "(# (+ +((#?, ?3 ?1)?-?%?2 ?4/????,.%0 8 65,611($6 9839=&>02?1? -? ??)?????? ??/??1???.exult-1.2/data/estudio/new/combos.flx0000644000175000001440000000020010054030554013331 Exult Archiveexult-1.2/data/estudio/new/sprites.vga0000644000175000001440000000033210054030555013533 Written by ExultStudioRRexult-1.2/data/estudio/new/text.flx0000644000175000001440000001475010054030555013053 Text created by ExultStudio !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~avatarexult-1.2/data/estudio/new/pointers.shp0000644000175000001440000000234507717350542013745 ( Dh                                exult-1.2/data/estudio/new/faces.vga0000644000175000001440000000205010054030554013121 Written by ExultStudio22++55==MM##))                                               ++  '' %%   //''exult-1.2/data/scaling_method.shp0000644000175000001440000000470007242212113012572 ^  (  (((  (!(&( * (5(:( = ( D (K(O( S ( Y ( (%$%( (%$%(  (( %(%!(&( )(%$%5(9( =(%$% D%(%K(O( R(%( Y(%((%'( % '(%'(('( !('(&()('5 ('('('(='(F(K(O(R(V(Y'(]'( %('('''''('!'&('(')'5'%'%' = 'F'( K'('('(R'(V'(Y']' %''  '''!' $&')','5'8$:' ='%$%F' K'%'(R'V'Y']'''' ' '%'''!'%%')',%'5':'='F'K'O'R'V'Y']' % '% % '%'' % '  '!'&' )% '5':' = 'F'K'O'( R% '% Y '%  $  $$$ $%  $!$&$ *$%$5$:$ = $F$K$O$ S $ Y $^  %  %%%  %!%&% * %5%:% = % D %K%O% S % Y % %$#$% %$#$%  %% $%$!%&% )%$#$5%9% =%$#$ D$%$K%O% R%$% Y%$%%$% $ %$%%% ! %&%)%5%=%F%K%O%R%V%Y%]% $ %%%%%%!%$ %)%5%$%$% = %F% K %R%V%Y%]% $%%  %%%!% $$%)%,%5%8#:% =%$#$F% K%#%R%V%Y%]%%%% % %$%%%!%%$%)%,$%5%:%=%F%K%O%R%V%Y%]% $ %$ $ %$%% $ %  %!%&% )$ %5%:% = %F%K%O% R$ %$ Y %$  #  ###  #  #!#&# *#$#5#:# = #F#L#O$# S # Y #exult-1.2/data/sav_down.shp0000644000175000001440000000057607410762606011457 ~               exult-1.2/data/extras.shp0000644000175000001440000000517207206247100011130 z W-,%+,+7+,3+,     +      +  +   +-+   + " --- +  - -- --- -+-- ++ -,+-, ------ ++ - -  - +  ,-- +  ---- -+ + + ----$--+ ,-.-- ------+ + ,,- --- -+   .-  , - + + -  ----+ - .---- --. .-.- .-++  -.-+  .  ++ --"--++ -.--.-- .-.- ++ -,- - ++- + --+ - --++.- -.-+.- -. -.- +-,-+--+.- -+, -  ++ . . -  -- +-.-  - - +-+,+-++     -,.... . ....... . exult-1.2/data/savegump.shp0000644000175000001440000001661707410763324011467 D      SaSaS  U S SSSSSS U ! U#"]##        $   #%%    #&%     #'       ()*+,-./01234 56789:;<=>ˎ? @A BCDEFGHIJKLMN OPQRSTUVWXYZ[ \]^_`abcdefgh ijklmnopqrstu vwxyz{|}~ ˎ ˎˎˎˎˎˎˎˎˎ9ˎ ˎ   ˎ  ˎ   ˎˎ  ˎ   ˎ     ˎ ͪˎ   ˎ  ͪˎ  ˎ ˎ  ˎ ˎ ˎ    ˎ  ˎ  ˎ  ˎ   ˎ  ˎ  ˎ 7ˎ 9  ˎ   ˎ   ˎ  ͫ  ˎ  ˎ    ˎ  ͫ  ˎ ͫˎ  ˎ 9ˎ ˎˎˎˎˎˎˎˎexult-1.2/data/flx.in0000644000175000001440000000103207410761714010227 exult.flx exult_quotes.shp exult_credits.shp quotes.txt credits.txt exult_logo.shp exult0.pal black_gate.shp serpent_isle.shp meditown.mid font.shp setup.shp play_intro.shp full_screen.shp cheating.shp ok.shp cancel.shp pointers.shp exit.shp play_1st_scene.shp extras.shp midi_conversion.shp sfx_conversion.shp palette_fades.shp scaling_method.shp savegump.shp sav_downdown.shp sav_down.shp sav_up.shp sav_upup.shp sav_slider.shp sav_selected.shp gameplayoptions.shp gamemenu.shp audiooptions.shp videooptions.shp hp_bar.shp sfx_icon.shp exult-1.2/data/Makefile.am0000644000175000001440000000540410026506277011147 EXULT_FLX_OBJECTS = \ flx.in \ exult_quotes.shp \ exult_credits.shp \ quotes.txt \ credits.txt \ exult_logo.shp \ exult0.pal \ black_gate.shp \ serpent_isle.shp \ meditown.mid \ font.shp \ setup.shp \ play_intro.shp \ full_screen.shp \ cheating.shp \ ok.shp \ cancel.shp \ pointers.shp \ exit.shp \ play_1st_scene.shp \ extras.shp \ midi_conversion.shp \ sfx_conversion.shp \ palette_fades.shp \ scaling_method.shp \ savegump.shp \ sav_downdown.shp \ sav_down.shp \ sav_up.shp \ sav_upup.shp \ sav_slider.shp \ sav_selected.shp \ gameplayoptions.shp \ gamemenu.shp \ audiooptions.shp \ videooptions.shp \ hp_bar.shp \ sfx_icon.shp EXULT_BG_FLX_OBJECTS = \ bg/flx.in \ bg/hoe_of_destruction.shp \ bg/caddellite_helmet.shp \ bg/magic_boomerang.shp \ bg/great_dagger.shp \ bg/gorget.shp \ bg/magicgorget.shp \ bg/cleaver.shp \ bg/faces.shp \ bg/faces2.shp \ bg/amulets.shp \ bg/bgfiredoom.shp \ bg/fellowshipstaff.shp \ bg/BGmap.shp \ bg/defaultkeys.txt \ bg/dupre_face.shp \ bg/fem_av_face.shp \ bg/iolo_face.shp \ bg/male_av_face.shp \ bg/shamino_face.shp \ bg/greaves.shp \ bg/spiked_shield.shp \ bg/mr_faces.shp \ bg/mr_intro.shp \ bg/firesword.shp \ bg/greencloak.shp \ bg/greycloak.shp \ bg/ring_of_protection.shp \ bg/greentop.shp \ bg/orangedress.shp \ bg/bluedress.shp \ bg/death_scythe.shp \ bg/firewand.shp \ bg/knife.shp \ bg/starburst.shp \ bg/hawk.shp \ bg/musket_ammo.shp \ bg/shoes.shp \ bg/triple_xbow.shp \ bg/pants.shp \ bg/collar.shp \ bg/hoods.shp \ bg/musket.shp \ bg/custom_sword.shp EXULT_SI_FLX_OBJECTS = \ si/flx.in \ si/SImap.shp \ si/defaultkeys.txt ESTUDIO_NEW_FILES = \ estudio/new/combos.flx \ estudio/new/faces.vga \ estudio/new/gumps.vga \ estudio/new/palettes.flx \ estudio/new/shapes.vga \ estudio/new/sprites.vga \ estudio/new/text.flx \ estudio/new/fonts.vga \ estudio/new/pointers.shp flexdir = $(datadir)/exult estudionewdir = $(datadir)/exult/estudio/new if DATA_FILES EXULT_FLX = exult.flx EXULT_BG_FLX = exult_bg.flx EXULT_SI_FLX = exult_si.flx else EXULT_FLX = EXULT_BG_FLX = EXULT_SI_FLX = endif flex_DATA = $(EXULT_FLX) $(EXULT_BG_FLX) $(EXULT_SI_FLX) midisfx.flx \ exultmsg.txt if BUILD_STUDIO estudionew_DATA = $(ESTUDIO_NEW_FILES) else estudionew_DATA = endif CLEANFILES = exult.flx exult_bg.flx exult_si.flx *~ EXTRA_DIST = flx.in $(EXULT_FLX_OBJECTS) $(EXULT_BG_FLX_OBJECTS) \ $(EXULT_SI_FLX_OBJECTS) $(ESTUDIO_NEW_FILES) midisfx.flx \ exultmsg.txt exult.flx: $(EXULT_FLX_OBJECTS) ../tools/expack -i $(srcdir)/flx.in exult_bg.flx: $(EXULT_BG_FLX_OBJECTS) ../tools/expack -i $(srcdir)/bg/flx.in exult_si.flx: $(EXULT_SI_FLX_OBJECTS) ../tools/expack -i $(srcdir)/si/flx.in exult-1.2/data/Makefile.in0000644000175000001440000002432510061527052011154 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ EXULT_FLX_OBJECTS = \ flx.in \ exult_quotes.shp \ exult_credits.shp \ quotes.txt \ credits.txt \ exult_logo.shp \ exult0.pal \ black_gate.shp \ serpent_isle.shp \ meditown.mid \ font.shp \ setup.shp \ play_intro.shp \ full_screen.shp \ cheating.shp \ ok.shp \ cancel.shp \ pointers.shp \ exit.shp \ play_1st_scene.shp \ extras.shp \ midi_conversion.shp \ sfx_conversion.shp \ palette_fades.shp \ scaling_method.shp \ savegump.shp \ sav_downdown.shp \ sav_down.shp \ sav_up.shp \ sav_upup.shp \ sav_slider.shp \ sav_selected.shp \ gameplayoptions.shp \ gamemenu.shp \ audiooptions.shp \ videooptions.shp \ hp_bar.shp \ sfx_icon.shp EXULT_BG_FLX_OBJECTS = \ bg/flx.in \ bg/hoe_of_destruction.shp \ bg/caddellite_helmet.shp \ bg/magic_boomerang.shp \ bg/great_dagger.shp \ bg/gorget.shp \ bg/magicgorget.shp \ bg/cleaver.shp \ bg/faces.shp \ bg/faces2.shp \ bg/amulets.shp \ bg/bgfiredoom.shp \ bg/fellowshipstaff.shp \ bg/BGmap.shp \ bg/defaultkeys.txt \ bg/dupre_face.shp \ bg/fem_av_face.shp \ bg/iolo_face.shp \ bg/male_av_face.shp \ bg/shamino_face.shp \ bg/greaves.shp \ bg/spiked_shield.shp \ bg/mr_faces.shp \ bg/mr_intro.shp \ bg/firesword.shp \ bg/greencloak.shp \ bg/greycloak.shp \ bg/ring_of_protection.shp \ bg/greentop.shp \ bg/orangedress.shp \ bg/bluedress.shp \ bg/death_scythe.shp \ bg/firewand.shp \ bg/knife.shp \ bg/starburst.shp \ bg/hawk.shp \ bg/musket_ammo.shp \ bg/shoes.shp \ bg/triple_xbow.shp \ bg/pants.shp \ bg/collar.shp \ bg/hoods.shp \ bg/musket.shp \ bg/custom_sword.shp EXULT_SI_FLX_OBJECTS = \ si/flx.in \ si/SImap.shp \ si/defaultkeys.txt ESTUDIO_NEW_FILES = \ estudio/new/combos.flx \ estudio/new/faces.vga \ estudio/new/gumps.vga \ estudio/new/palettes.flx \ estudio/new/shapes.vga \ estudio/new/sprites.vga \ estudio/new/text.flx \ estudio/new/fonts.vga \ estudio/new/pointers.shp flexdir = $(datadir)/exult estudionewdir = $(datadir)/exult/estudio/new @DATA_FILES_TRUE@EXULT_FLX = exult.flx @DATA_FILES_FALSE@EXULT_FLX = @DATA_FILES_TRUE@EXULT_BG_FLX = exult_bg.flx @DATA_FILES_FALSE@EXULT_BG_FLX = @DATA_FILES_TRUE@EXULT_SI_FLX = exult_si.flx @DATA_FILES_FALSE@EXULT_SI_FLX = flex_DATA = $(EXULT_FLX) $(EXULT_BG_FLX) $(EXULT_SI_FLX) midisfx.flx \ exultmsg.txt @BUILD_STUDIO_TRUE@estudionew_DATA = $(ESTUDIO_NEW_FILES) @BUILD_STUDIO_FALSE@estudionew_DATA = CLEANFILES = exult.flx exult_bg.flx exult_si.flx *~ EXTRA_DIST = flx.in $(EXULT_FLX_OBJECTS) $(EXULT_BG_FLX_OBJECTS) \ $(EXULT_SI_FLX_OBJECTS) $(ESTUDIO_NEW_FILES) midisfx.flx \ exultmsg.txt subdir = data mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(estudionew_DATA) $(flex_DATA) DIST_COMMON = README Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu data/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: install-estudionewDATA: $(estudionew_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(estudionewdir) @list='$(estudionew_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(estudionewdir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(estudionewdir)/$$f; \ done uninstall-estudionewDATA: @$(NORMAL_UNINSTALL) @list='$(estudionew_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(estudionewdir)/$$f"; \ rm -f $(DESTDIR)$(estudionewdir)/$$f; \ done install-flexDATA: $(flex_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(flexdir) @list='$(flex_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(flexdir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(flexdir)/$$f; \ done uninstall-flexDATA: @$(NORMAL_UNINSTALL) @list='$(flex_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(flexdir)/$$f"; \ rm -f $(DESTDIR)$(flexdir)/$$f; \ done tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/bg $(distdir)/estudio/new $(distdir)/si @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(estudionewdir) $(DESTDIR)$(flexdir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-estudionewDATA install-flexDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-estudionewDATA uninstall-flexDATA \ uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-estudionewDATA install-exec \ install-exec-am install-flexDATA install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool uninstall \ uninstall-am uninstall-estudionewDATA uninstall-flexDATA \ uninstall-info-am exult.flx: $(EXULT_FLX_OBJECTS) ../tools/expack -i $(srcdir)/flx.in exult_bg.flx: $(EXULT_BG_FLX_OBJECTS) ../tools/expack -i $(srcdir)/bg/flx.in exult_si.flx: $(EXULT_SI_FLX_OBJECTS) ../tools/expack -i $(srcdir)/si/flx.in # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/data/setup.shp0000644000175000001440000000160107202011625010750  !  (  (  (((  ( (%$%( (%$% %(%(( (%((%'((((( (& %('('  ''('('( '('('% %' '%$%''' '%$%''''''' % '%  '' % ''  $  $$ $%$$!  %  %  %%%  % %$#$% %$#$ $%$%% %$%%$%%%%% % $ %  %%%%  %$ $% %$#$%%% %$%%%%%%% $ %$  %% $ %%  #  ## #$##exult-1.2/data/palette_fades.shp0000644000175000001440000000367107210425160012423  V ( ((  (  ( " ( ) ( 5 (>( C ( J ( R ( (%(  (( (%$% %(% "%(% )(%$% 5(%$% = ( C(%( J(%$% Q(%$%(((& '(%'(('(($()'(5'( <'(%'(C'(G'(J'(Q(V% '('('%' ''(  ''($'( ) ' 5 '<'@'C'G' J ' Q%('(' '%$%  '' '%$%'$' )'%$% 5'%$% < 'C'G' J'%$% R%'' '%''''$')'5' <'%'C'G'J'Q'U''' ' % '  ''$' ) '5'<'@' C '% J ' Q% '%$$ $ $%  $$$$ ) $5$<$@$ C $ J $ R $V % %%  %  % " % ) % 5 %>% C % J % R % %$%  %% %$#$ $%$ "$%$ )%$#$ 5%$#$ = % C%$% J%$#$ Q%$#$%%% %$%%%%$%)%5% <%$%C%G%J%Q%V$  %$% %%  %%$% ) % 5 %<%@%C%G% J % Q$ % %$  %% %$#$%$% )%$#$ 5%$#$ < %C%G% J%$#$ R$%% %$%%%%$%)%5% <%$%C%G%J%Q%U%%% % $ %  %%$% ) %5%<%@% C %$ J % Q$ %$## #  #  ##$# ) #5#<#@# C # J # R #exult-1.2/data/sav_up.shp0000644000175000001440000000057607410762606011134 ~               exult-1.2/data/play_1st_scene.shp0000644000175000001440000000463207206200300012522 e (((((  ( & ( + ( 3 ( 9 ( D ( K ( Q (X(]( ` ( (%((  ((( (%$% &%(% +(%( 2(%$%( 9%(% C(%$%( J(%$%( Q(%$%X(]( `(%$%((&( '(%'((('(''(+(/(&2(7%;(C(H%J'(O%Q'( X('(](`'( '('('%'( '' &('('&  ''' +'('('% 2%('(';'( C%('('J' Q 'X'&('(' ` ' '%$%'  ' %'% '%$%'' + '% 3%';' D%'J' Q'%$%X' [&' `'%$%'' '%''''' +'%'2'6';'C'G'J'O'Q'X'\%'`'' % ' '''' & '+'.%' 2% '%;' C% '% J% '% Q 'X']' ` '$ $% $$$$ & $+$/$ 3 $;$ D $ K $ Q $X$]$ ` $e %%%%%  % & % + % 3 % 9 % D % K % Q %X%]% ` % %$%%  %%% %$#$ &$%$ +%$% 2%$#$% 9$%$ C%$#$% J%$#$% Q%$#$X%]% `%$#$%%% %$%%%%'%+%/%$2%7$;%C%H$J%O$Q% X %]%`%  %$% %% $ %$  %'% + %$ 2$ %;% C$ %J% Q %X%$ % ` % %$%  % $%$ %$#$'% + %$ 3$%;% D$%J% Q%$#$X% [$% `%$#$%% %$%%%'% +%$%2%6%;%C%G%J%O%Q%X%\$%`%% $ % %%%% & %+%.$% 2$ %$;% C$ %$ J$ %$ Q %X%]% ` %#  # #### & #+#/# 3 #;# D # K # Q #X#]# ` #exult-1.2/data/exult_credits.shp0000644000175000001440000000413007153222317012475 X 6^  ( ((((( ( . ( 4 ( ; ( B ( I ( N ( V ( (%$% ((((( %(% -(%$%( 4(%( ;(%$% B(%( I%(% N%(% U(%$%('( %((%((("(-'(2%4(8(&;'(B'(F'(J'(P(U(Z%  ' &'('&'('('("'(-' 4'('('% ; 'B'F'J'P'( U%('(' '%$% '&''''"'-' 4 '% ;'%$%B'F'J'P' V%'' '%%''''"'-'2' 4'%';'B'F'J'P'U'Y'  ' '' % ' % '"' -% '%4'7%' ; ' B '% I 'P' U% '%  $ $$ $%$ $%"$ . $4$8$ ; $ B $ I $P$ V $^  % %%%%% % . % 4 % ; % B % I % N % V % %$#$ %%%%% $%$ -%$#$% 4%$% ;%$#$ B%$% I$%$ N$%$ U%$#$%% $%%$%%%"%-%2$4%8%$;%B%F%J%P%U%Z$  % $%$%%%"%-% 4 %$ ; %B%F%J%P% U$ % %$#$ %$%%%%"%-% 4 %$ ;%$#$B%F%J%P% V$%% %$$%%%%"%-%2% 4%$%;%B%F%J%P%U%Y%  % %% $ % $ %"% -$ %$4%7$% ; % B %$ I %P% U$ %$  # ## #$# #$"# . #4#8# ; # B # I #P# V #exult-1.2/data/sfx_conversion.shp0000644000175000001440000000511407206741124012670 L 5_  (  (((  ( # ()(.(1(5( 8 ( ? ( G ( M ( S (Y(^( (%$%( (%$%(( (%$%( "(%()(.(1(5( 8(%$% ?(%( F(%$%( M%(% R(%(Y(^((%'(%((%'( %"(&( )('(.(1(5(8'(?(C(&F(K%N'(R(V( Y('(^( %('('  ' &'('&'"'(&'()'&('('1'(5'( 8 ' ?'('('% F%('('N'R'(V'(Y' &('(' %' '%$% '&''"'&')' ,&'1'5' 8'%$% ? '% G%'N'R'V'Y' \&'''''%%'' '"'&')'-%' 1& '&8' ?'%'F'J'N'R'V'Y']%' % '%''' % '% "% '%)'.' 2%'% 8 '?'B%' F% '% M ' R% '%Y'^'  $$$$  $ # $)$.$3$ 8 $?$C$ G $ M $ S $Y$^$_  %  %%%  % # %)%.%1%5% 8 % ? % G % M % S %Y%^% %$#$% %$#$%% %$#$% "%$%)%.%1%5% 8%$#$ ?%$% F%$#$% M$%$ R%$%Y%^%%$%$%%$% $"%&% ) %.%1%5%8%?%C%$F%K$N%R%V% Y %^% $ %  % $%$%"%&%)%$ %1%5% 8 % ? %$ F$ %N%R%V%Y%$ % $% %$#$ %$%%"%&%)% ,$%1%5% 8%$#$ ? %$ G$%N%R%V%Y% \$%%%%%$$%% %"%&%)%-$% 1$ %$8% ?%$%F%J%N%R%V%Y%]$% $ %$%%% $ %$ "$ %$)%.% 2$%$ 8 %?%B$% F$ %$ M % R$ %$Y%^%  ####  # # #)#.#3# 8 #?#C# G # M # S #Y#^#exult-1.2/data/hp_bar.shp0000644000175000001440000000011207331266364011056 J ECEAEAEAECexult-1.2/data/ok.shp0000644000175000001440000000073207202011625010225    (( ( (%(( (%'('(  (%'' '(''' '$'''' $' $ '' $'(  $$ $   %% % %$%% %$%%  %$%%  %%%% %%%% % $ %$% $%  ## #exult-1.2/data/gamemenu.shp0000644000175000001440000000401307266404205011420 R      !"#$%&'()*%+9 %, %-   %.  %/ %0 %1  %2  %3    %4ͪ %5   %6 ͪ %7 %8 %9  %: %; %<   %=  %>  %?  %@   %A  %B  7%C 9%D   %E   %F   %G ͫ   %H  %I   %J ͫ   %Kͫ %L  %M9 NOPQRexult-1.2/data/exult_logo.shp0000644000175000001440000002527207231610125012005 * c?&'. .(--).-* -!+-#, -%---+-..-/-/.0.0.1-+1-2-2+-3.3+-44+- 5566+7+7-8 -8- 9-9.-: :-.;-.-<+.C=-+-C>- -?? .;@.-9A+-...-++B-+-B., B--C-C.-C-.D--E--F-+G-H-I-JKLM.N-O .P- -Q -R.S.T-.U+.V.. W -X.. Y-. nh &h&h&h&Ki&Zi&ni& }i &i&i& i & i & i &i&?i?&?Kj?&+nj+&-j-&j&'j'& j &GjG&?Lk?&'ok'&k&-k'&,!k!&k,k&GkG&Ml&]l,&,-pl#& ,l&1l,#& ,l& l ,l&,Il&,&,&,AMm&,&,+qm,& ,Gm& ,& ,Im,& ,&,Om& ,& ,&,CMn&,&,'rn& ,n&,'n& ,!n& ,#n&,On& ,& ,&,Mo&,bo,&,#so& ,o & ,%o& ,o& ,!o& ,7o &,&,o&,Mp&,dp,&,tp&,p & ,#p& ,p& ,!p& ,p & ,p&,p &,Mq&,fq&,tq&,q & ,q& ,q& ,q& ,q & ,q&,q &,Mr&,fr&,ur&,r & ,r& ,r& ,r&,r & ,r&,r &,Ms&,gs &,us&,s & ,s& ,s & ,s&,s & ,s&,s &,Mt&,ht &,vt&,t & ,t&,t & ,t&,t & ,t&,t &,Mu&,iu &,vu&,u& u ,u&,u & ,u&,u & ,u&,u &,Mv&, jv&,wv&,v & ,v&,v &,v&,v & ,v&,v &,Mw&, kw& ,ww&,w& w ,w&,w &,w&,w& ,w&,w &,Mx&,ex& lx ,wx&,x&x,x&,x &,x&, x ,x&, x ,My&,dy&my,xy&,y& y ,y&,y &,y&, y ,y&, y ,Mz&,dz&nz,#xz&,&z,z&,z &,z&,z,z&, z ,M{&,c{&h{,y{&{,{&,{ &,{&,{&,M|&,c|&g|,y|&|,|&,| &,|&,|&,M}&, b} &g},z}&},}&,} &,}&,}&,M~&,a~ &,#z~& ,~&,~ &,~&,~&,M&,^&,{&,&, &,&,&,9M3&,{&,&, &,&,&,9M3&,{&,&, &,&,&,9M3&,|&,&, &,&,&,9M& ,&,|&,&, &,&,&,9M&, &,}&,&, &,&,&,9M&, &,|&,&, &,&,&,M&,a,&,|&,&, &,&,&,M&, c&,#{&,&, &,&,&,M&, d&,#{!&,&, &,&,&,M&, d&, z &&,&,&,&,&,M&, e&,z&~,&,&,&,&,&,M&,g, y &!~,&,&,&,&,&,M&,g,n&-x & ,&,&,&,&,&,M&,h,m& x &},&,&,&,&,&,M&, l &w & ,&,&,&,&,&,M&, l &q,v & ,&,&,&,&,&,M&,k &,v & ,&,&,&,&,&,M&,j &,u & ,&,&,&,&,&,M&,j &,u & ,&,&,&,&,&,M&,i & ,t & ,&,&,&,&,&,M&,-h& ,& ,&,&!& ,&,&,L&,-g& , & ,&,G?& ,&,&,L&,/f&,& ,&,E;& ,&,&,L&,1e&,& ,&,C9& ,&,!&,#K&,3c&,&,!&,A5& ,#&,%!&,#K#&7a&,&,##&=1& ,%#&,'%&,eJG&,&,))&9-& ,''&''&gIg&+)&,5'&,++&)'&,iIg&,)& ,1,!&,//&%& ,GMG,q,)),-,&,- ,!&'',gLg,)),'',5,&'',gLg,,!!,],+&,,3,&%,&++,,,?&'. .(--).-* -!+-#, -%---+-..-/-/.0.0.1-+1-2-2+-3.3+-44+- 5566+7+7-8 -8- 9-9.-: :-.;-.-<+.C=-+-C>- -?? .;@.-9A+-...-++B-+-B., B--C-C.-C-.D--E--F-+G-H-I-JKLM.N-O .P- -Q -R.S.T-.U+.V.. W -X.. Y-. nh +h+h+h+Ki+Zi+ni+ }i +i+i+ i + i + i +i+?i?+?Kj?++nj++-j-+j+'j'+ j +GjG+?Lk?+'ok'+k+-k'+,!k!+k,k+GkG+Ml+]l,+,-pl#+ ,l+1l,#+ ,l+ l ,l+,Il+,+,+,AMm+,+,+qm,+ ,Gm+ ,+ ,Im,+ ,+,Om+ ,+ ,+,CMn+,+,'rn+ ,n+,'n+ ,!n+ ,#n+,On+ ,+ ,+,Mo+,bo,+,#so+ ,o + ,%o+ ,o+ ,!o+ ,7o +,+,o+,Mp+,dp,+,tp+,p + ,#p+ ,p+ ,!p+ ,p + ,p+,p +,Mq+,fq+,tq+,q + ,q+ ,q+ ,q+ ,q + ,q+,q +,Mr+,fr+,ur+,r + ,r+ ,r+ ,r+,r + ,r+,r +,Ms+,gs +,us+,s + ,s+ ,s + ,s+,s + ,s+,s +,Mt+,ht +,vt+,t + ,t+,t + ,t+,t + ,t+,t +,Mu+,iu +,vu+,u+ u ,u+,u + ,u+,u + ,u+,u +,Mv+, jv+,wv+,v + ,v+,v +,v+,v + ,v+,v +,Mw+, kw+ ,ww+,w+ w ,w+,w +,w+,w+ ,w+,w +,Mx+,ex+ lx ,wx+,x+x,x+,x +,x+, x ,x+, x ,My+,dy+my,xy+,y+ y ,y+,y +,y+, y ,y+, y ,Mz+,dz+nz,#xz+,+z,z+,z +,z+,z,z+, z ,M{+,c{+h{,y{+{,{+,{ +,{+,{+,M|+,c|+g|,y|+|,|+,| +,|+,|+,M}+, b} +g},z}+},}+,} +,}+,}+,M~+,a~ +,#z~+ ,~+,~ +,~+,~+,M+,^+,{+,+, +,+,+,9M3+,{+,+, +,+,+,9M3+,{+,+, +,+,+,9M3+,|+,+, +,+,+,9M+ ,+,|+,+, +,+,+,9M+, +,}+,+, +,+,+,9M+, +,|+,+, +,+,+,M+,a,+,|+,+, +,+,+,M+, c+,#{+,+, +,+,+,M+, d+,#{!+,+, +,+,+,M+, d+, z ++,+,+,+,+,M+, e+,z+~,+,+,+,+,+,M+,g, y +!~,+,+,+,+,+,M+,g,n+-x + ,+,+,+,+,+,M+,h,m+ x +},+,+,+,+,+,M+, l +w + ,+,+,+,+,+,M+, l +q,v + ,+,+,+,+,+,M+,k +,v + ,+,+,+,+,+,M+,j +,u + ,+,+,+,+,+,M+,j +,u + ,+,+,+,+,+,M+,i + ,t + ,+,+,+,+,+,M+,-h+ ,+ ,+,+!+ ,+,+,L+,-g+ , + ,+,G?+ ,+,+,L+,/f+,+ ,+,E;+ ,+,+,L+,1e+,+ ,+,C9+ ,+,!+,#K+,3c+,+,!+,A5+ ,#+,%!+,#K#+7a+,+,##+=1+ ,%#+,'%+,eJG+,+,))+9-+ ,''+''+gIg++)+,5'+,+++)'+,iIg+,)+ ,1,!+,//+%+ ,GMG,q,)),-,+,- ,!+'',gLg,)),'',5,+'',gLg,,!!,],++,,3,+%,+++,,,exult-1.2/data/full_screen.shp0000644000175000001440000000342007202011625012112  J (( ((( " ( ) ( / ( 6 ( = (D(I( (%$%( ((( !(%$%( ((%$%( /(%( 6(%$% =(%$%D(I('(( (((!(&%('(-%/(3(&6'(='( D('(I(  ''( '('('( !%('('(' /'('('% 6 ' = 'D' &('(' '%$%' ''' "%'(' / '% 6'%$% ='%$%D' G&''' '''!'%'('-' /'%'6'='D'H%'' % ' % ' % ' !% '% (% '%/'2%' 6 ' = 'D'I'$ $%$ $% $% " $ ) $/$3$ 6 $ = $D$I$J %% %%% " % ) % / % 6 % = %D%I% %$#$% %%% !%$#$% (%$#$% /%$% 6%$#$ =%$#$D%I%%% %%%!%&$(%-$/%3%$6%=% D %I%  %% %%% !$ %(% / %$ 6 % = %D%$ % %$#$% %%% "$%(% / %$ 6%$#$ =%$#$D% G$%%% %%%!%%%(%-% /%$%6%=%D%H$%% $ % $ % $ % !$ %$ ($ %$/%2$% 6 % = %D%I%# #$#  #  # " # ) #/#3# 6 # = #D#I#exult-1.2/data/sav_slider.shp0000644000175000001440000000023607266117651011766 \  exult-1.2/data/sfx_icon.shp0000644000175000001440000000125007375322303011431   $$""      "!       "$   $    "   " $"$ $ $ $"" $"   $"   "!     "    "$ "    $ "     $"     $"   $"$ $ exult-1.2/data/exultmsg.txt0000644000175000001440000000105207677445120011526 # These messages are used in the Exult engine, and follow the # game-specific ones. 2800:Put that chair back! 2801:Thief!! 2802:Thou scoundrel!! 2803:Not funny! 2804:Who moved my chair?? 2805:You look like you're doing fine. 2806:Everything okay? 2807:Ready for dessert? 2808:Enjoy! 2809:Specialty of the house! 2810:Avatar! Please restrain thyself! 2811:Hast thou noticed that this bed is occupied? 2812:The resident of this bed may not be desirouth of company at the moment. 2813:Thou shan't lose me so easily! 2814:Ah, there thou art! 2815:Found ye! exult-1.2/data/gameplayoptions.shp0000644000175000001440000000675507370550432013054 njǎǎǎǎǎǎ ǎ ǎ ǎ ǎ ǎǎǎǎǎǎǎǎǎǎǎǎǎǎǎǎǎǎǎ ǎ!ǎ"ǎ#ǎ$ǎ%ǎ&ǎ'ǎ(ǎ)ǎ*ǎ+ǎ,ǎ-ǎ.ǎ/ǎ0ǎ1ǎ2ǎ3ǎ4ǎ5ǎ6ǎ7ǎ8ǎ9ǎ:ǎ;ǎ<ǎ=ǎ>ǎ?ǎ@ǎAǎBǎCǎDǎEǎFǎGǎHǎIǎJǎKǎLǎMǎNǎOǎPǎQǎRǎSǎTǎUǎVǎWǎXǎYǎZǎ[ǎ\ǎ]ǎ^ǎ_ǎ`ǎaǎbǎcǎdǎeǎfǎgǎhǎiǎjǎkǎlǎmǎnǎoǎpǎqǎrǎsǎtǎuǎvǎwǎxǎ y9ǎ zǎ {  ǎ | ǎ } ǎ ~ǎ  ǎ   ǎ     ǎ ͪǎ   ǎ  ͪǎ  ǎ ǎ  ǎ ǎ ǎ   ǎ  ǎ  ǎ  ǎ   ǎ  ǎ  ǎ 7 ǎ 9   ǎ   ǎ   ǎ  ͫ  ǎ  ǎ   ǎ  ͫ  ǎ ͫǎ  ǎ 9ǎ ǎǎǎɐexult-1.2/data/videooptions.shp0000644000175000001440000000465507402652037012360 `UWUOUOUOUOUOUOUOU OU OU OU OU OUOUOUOUOUOUOUOUOUOUOUOUOUOUOUOUOUOUOU OU!OU"OU#OU$OU%OU&OU'OU(OU)OU*OU+OU,OU-OU.OU/OU0OU1OU2OU3OU4OU5OU6OU7OU8O99O :O ;  O < O = O>O ? O @  O A    O BͪO C  O D ͪO E O FO G O HO IO J  O K O L O M O N  O O O P O 7QO 9R  O S  O T  O U ͫ  O V O W  O X ͫ  O YͫO Z O [9O U\OU]OU^OU_QU`Wexult-1.2/data/sav_upup.shp0000644000175000001440000000062207410762606011471                  exult-1.2/data/pointers.shp0000644000175000001440000000016207204757664011502 r %#%# %#  %#  %# %#%#% # %# #exult-1.2/data/sav_selected.shp0000644000175000001440000000014707270555363012276 g         exult-1.2/data/cheating.shp0000644000175000001440000000273707202011625011405  5  (( (  ((  ( # (((-( 1 ( (%(( ( (%$%  ( %(% #%(%((-( 0(%$%(%( ('( '(%'(($'( (('(-(0(''( '('('(  ''''($'(' &('('0'' '%'( '%$%  ''$'(' +&'0'3'''' '' '%''$'(',%'0'3%' % '%' '(  '''' # '('-' 0% '  $$ $  $$$$ # $($-$ 1$%$5  %% %  %%  % # %(%-% 1 % %$#$%% % %$#$  % $%$ #$%$(%-% 0%$#$%$% %% %$%%$% ( %-%0%%  %  %%%%$%(%$ %0%% %#% %$#$  %%$%(% +$%0%3%%%% %% %$%%$%(%,$%0%3$% $ %$% %  %%%% # %(%-% 0$ %  ## $#  #### # #(#-# 1#$#exult-1.2/data/exit.shp0000644000175000001440000000130507206200300010554  i (( (  (  ( (%$%( ( %(% %(%'(%( (%'((  ' &'('&''( '%$% '&'''''% %'''  '' '  ''  $$ $  $$ %% %  %  % %$#$% % $%$ $%$%$% %$%%  % $%$%% %$#$ %$%%%%%$ $%%%  %% %  %%  ## #  ##exult-1.2/data/play_intro.shp0000644000175000001440000000571007204761025012005 o (((((  ($()( , ( 3 ( ; ( A (H(L( P ( V ( ] ( c (i(n( (%((  ((( %(%$()( ,%(% 3(%( :(%( A(%(H(L( O(%$%( V%(% ]%(% b(%(i(n(((&( '(%'((( '( $('()(.(3(7(&:(>(A'(E'(H(L(O'(T%X(^'(b(f( i('(n( '('('%'( '' &('('& '$' &('('.'( 3'('('%:'(>'(A'E'H'(L'(O'X'(^'b'(f'(i' &('(' '%$%'  ' %'% '$' '&'.' 3 '%:'>'A'E'H'L'O'X'^'b'f'i' l&''' '%'' '$'(%'.' 3'%':'>'A'E'H'L'O'T'X'^'b'f'i'm%'' % ' '''  '$')'.'3'6%' :% '% A '% H% ' O% '%X' ] ' b% '%i'n'$ $% $$$  $$$)$.$3$7$ ; $ A $ I$%$ P $X$ ] $ c $i$n$o %%%%%  %$%)% , % 3 % ; % A %H%L% P % V % ] % c %i%n% %$%%  %%% $%$$%)% ,$%$ 3%$% :%$% A%$%H%L% O%$#$% V$%$ ]$%$ b%$%i%n%%%% %$%%% % $ %)%.%3%7%$:%>%A%E%H%L%O%T$X%^%b%f% i %n%  %$% %% $ %$ %$%$ %.% 3 %$:%>%A%E%H%L%O%X%^%b%f%i%$ % %$%  % $%$ %$% '$%.% 3 %$:%>%A%E%H%L%O%X%^%b%f%i% l$%%% %$%% %$%($%.% 3%$%:%>%A%E%H%L%O%T%X%^%b%f%i%m$%% $ % %%%  %$%)%.%3%6$% :$ %$ A %$ H$ % O$ %$X% ] % b$ %$i%n%#  # ###  #$#)#.#3#7# ; # A # I#$# P #X# ] # c #i#n#exult-1.2/data/cancel.shp0000644000175000001440000000213407202011625011037 \ 7(  ( (((  (  ($( (%(  ((( (%( (%$%$((% '(%'( ('(((%'($('(' '' &('(''(  '$'('  '' &'' '%$%$''' '%''%''''$' % '%' ''' % '%  ' $% '  $$ $$$  $  $ %$%(  % %%%  %  %$% %$#$%  %%% %$#$% %$#$$%%$ %$%  %%%$%$%%% %%$ %%  %$%%  %% $%% %$#$$%%% %$%%$%%%%$% $ %$% %%% $ %$  % $$ %  ## ###  #  # % #exult-1.2/conf/0000777000175000001440000000000010062225325007200 5exult-1.2/conf/README0000644000175000001440000000201707427572047010015 What the hell am I? I'm a simple XML syntax parser. Not a real XML parser. Nothing to do with DTD's. Really speaking, what we do here is not XML. If it's anything it's a DDL (Data Description Language). In short the base syntactical rules are the same as XML, giving us a hierarchical file-structure of key-value pairs (just like the Windows(tm) registry). As a bonus, it's human-readable, and human editable as well as being a doddle to handle programmatically This lends itself very nicely to configuration files, and that's _exactly_ what we're doing here. ** Warning ** Just at the moment, I'm not supporting: * XML empty tags (I did, but I'm not right now) - Update: empty tags are back * Spaces,tabs,carriage returns, line-feeds inside entities (just because) - Update: I'm now supporting whitespace within the entity, but not leading or trailing whitespace * modifiers inside tags (eg: ) (and honestly, I'm not at all sure what we would do with them if we supported them anyway) exult-1.2/conf/Configuration.cc0000644000175000001440000001417210054030551012233 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "common_types.h" #include "Configuration.h" #include "exceptions.h" #include "utils.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #include #include #include #ifdef HAVE_SSTREAM #include #endif #ifndef UNDER_CE using std::atoi; using std::cerr; using std::endl; using std::string; using std::ostream; #endif // isspace could be a macro #ifndef UNDER_CE #ifndef isspace using std::isspace; #endif #endif #define TRACE_CONF 0 #if TRACE_CONF #define CTRACE(X) cerr << X << endl #else #define CTRACE(X) #endif void Configuration::value(const string &key, string &ret,const char *defaultvalue) const { const XMLnode *sub=xmltree->subtree(key); if(sub) ret = sub->value(); else ret = defaultvalue; } void Configuration::value(const string &key,bool &ret,bool defaultvalue) const { const XMLnode *sub=xmltree->subtree(key); if(sub) ret = (to_uppercase(sub->value()) == "YES"); else ret = defaultvalue; } void Configuration::value(const string &key,int &ret,int defaultvalue) const { const XMLnode *sub=xmltree->subtree(key); if(sub) ret = atoi(sub->value().c_str()); else ret = defaultvalue; } void Configuration::set(const string &key, const string &value, bool write_out) { // Break k up into '/' separated elements. // start advancing walk, one element at a time, creating nodes // as needed. // At the end of that, walk is the target node, and we // can set the value. // We must also properly encode the value before writing it out. // Must remember that. xmltree->xmlassign(key,value); if(write_out) write_back(); } void Configuration::set(const char *key, const char *value, bool write_out) { string k(key), v(value); set(k, v, write_out); } void Configuration::set(const char *key, const string &value, bool write_out) { string k(key); set(k, value, write_out); } void Configuration::set(const char *key, int value,bool write_out) { string k(key),v; char buf[32]; snprintf(buf,32,"%d",value); v=buf; set(k,v,write_out); } bool Configuration::read_config_string(const string &s) { string sbuf(s); size_t nn=0; while(isspace(s[nn])) ++nn; assert(s[nn]=='<'); ++nn; xmltree->xmlparse(sbuf,nn); is_file=false; return true; } bool Configuration::read_config_file(const string &input_filename, const string &root) { string fname; CTRACE("Configuration::read_config_file"); fname=input_filename; // Don't frob the filename if it starts with a dot and // a slash. // Or if it's not a relative path. if((fname.find("./")!=0) && (fname[0]!='/')) { #if ((defined XWIN) || (defined BEOS) || (defined MACOSX)) const char *f1=getenv("HOME"); if(f1) { // User has a home directory fname=f1; #if defined(BEOS) fname+="/config/settings/"; #elif defined(MACOSX) fname+="/Library/Preferences/"; #else fname+="/."; #endif fname+=input_filename; } else fname=input_filename; #else // Probably something to do with determining the username // and generating a filename in their personal setup area. // For now, just read file from current directory fname=input_filename; #endif } return read_abs_config_file(fname, root); } // read config from file, without pre-processing the filename bool Configuration::read_abs_config_file(const string &input_filename, const string &root) { filename = input_filename; CTRACE("Configuration::read_abs_config_file"); clear(root); is_file=true; // set to file, even if file not found std::ifstream ifile; try { U7open(ifile, filename.c_str(), true); } catch(exult_exception &) { // configuration file not found return false; } if(ifile.fail()) return false; string sbuf, line; // copies the entire contents of the input file into sbuf getline(ifile, line); while (ifile.good()) { sbuf += line + "\n"; getline(ifile, line); } ifile.close(); CTRACE("Configuration::read_config_file - file read"); read_config_string(sbuf); is_file=true; return true; } string Configuration::dump(void) { return xmltree->dump(); } ostream &Configuration::dump(ostream &o, const string &indentstr) { xmltree->dump(o, indentstr); return o; } void Configuration::write_back(void) { if(!is_file) return; // Don't write back if not from a file std::ofstream ofile; try { U7open(ofile, filename.c_str(), true); } catch (const file_open_exception &) { std::perror("Failed to write configuration file"); return; } if(ofile.fail()) { std::perror("Failed to write configuration file"); return; } ofile << dump() << endl; ofile.close(); } std::vector Configuration::listkeys(const string &key, bool longformat) { std::vector vs; const XMLnode *sub=xmltree->subtree(key); if(sub) sub->listkeys(key,vs,longformat); return vs; } std::vector Configuration::listkeys(const char *key, bool longformat) { string s(key); return listkeys(s,longformat); } void Configuration::clear(const string &new_root) { CTRACE("Configuration::clear"); if(xmltree!=0) delete xmltree; CTRACE("Configuration::clear - xmltree deleted"); if(new_root.size()) rootname=new_root; CTRACE("Configuration::clear - new root specified"); xmltree = new XMLnode(rootname); CTRACE("Configuration::clear - fin"); } void Configuration::getsubkeys(KeyTypeList &ktl, const string &basekey) { xmltree->searchpairs(ktl, basekey, string(), 0); } exult-1.2/conf/Configuration.h0000644000175000001440000000612107724430450012104 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _Configuration_h_ #define _Configuration_h_ #include "XMLEntity.h" class Configuration { public: Configuration() : xmltree(new XMLnode("config")), rootname("config"), filename(), is_file(false) { } Configuration(const std::string &fname, const std::string &root) : xmltree(new XMLnode(root)), rootname(root), filename(), is_file(false) { if(fname.size()) read_config_file(fname); } ~Configuration() { if(xmltree!=0) delete xmltree; }; bool read_config_file(const std::string &input_filename, const std::string &root=std::string()); bool read_abs_config_file(const std::string &input_filename, const std::string &root=std::string()); bool read_config_string(const std::string &); void value(const std::string &key, std::string &ret, const char *defaultvalue="") const; void value(const std::string &key, bool &ret, bool defaultvalue=false) const; void value(const std::string &key, int &ret, int defaultvalue=0) const; void value(const char *key, std::string &ret, const char *defaultvalue="") const { value(std::string(key), ret, defaultvalue); }; void value(const char *key, bool &ret, bool defaultvalue=false) const { value(std::string(key), ret, defaultvalue); }; void value(const char *key, int &ret, int defaultvalue=0) const { value(std::string(key), ret, defaultvalue); }; void set(const std::string &key, const std::string &value, bool write_to_file); void set(const char *key,const char *value,bool write_to_file); void set(const char *key,const std::string &value,bool write_to_file); void set(const char *key,int,bool write_to_file); // Return a list of keys that are subsidiary to the supplied key std::vector listkeys(const std::string &key,bool longformat=true); std::vector listkeys(const char *key,bool longformat=true); std::string dump(void); // Assembles a readable representation std::ostream &dump(std::ostream &o, const std::string &indentstr); void write_back(void); void clear(const std::string &new_root=std::string()); typedef XMLnode::KeyType KeyType; typedef XMLnode::KeyTypeList KeyTypeList; void getsubkeys(KeyTypeList &ktl, const std::string &basekey); private: XMLnode *xmltree; std::string rootname; std::string filename; bool is_file; }; // Global Config extern Configuration *config; #endif exult-1.2/conf/config.xml0000644000175000001440000000100507427572047011120 /home/dancer/projects/u7/ d:\ultima series\ultima vii - the serpent isle newstuff exult-1.2/conf/Makefile.am0000644000175000001440000000077007431011317011154 INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../headers -I$(srcdir)/../files $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) $(WARNINGS) if BUILD_TOOLS noinst_PROGRAMS = confregress endif noinst_LTLIBRARIES = libconf.la libconf_la_SOURCES = \ Configuration.cc \ Configuration.h \ XMLEntity.cc \ XMLEntity.h confregress_SOURCES = \ xmain.cc confregress_LDADD = \ libconf.la \ ../files/libu7file.la \ $(SYSLIBS) EXTRA_DIST = \ config.xml \ README CLEANFILES = *~ exult-1.2/conf/Makefile.in0000644000175000001440000002543510061527047011177 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../headers -I$(srcdir)/../files $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) $(WARNINGS) @BUILD_TOOLS_TRUE@noinst_PROGRAMS = confregress noinst_LTLIBRARIES = libconf.la libconf_la_SOURCES = \ Configuration.cc \ Configuration.h \ XMLEntity.cc \ XMLEntity.h confregress_SOURCES = \ xmain.cc confregress_LDADD = \ libconf.la \ ../files/libu7file.la \ $(SYSLIBS) EXTRA_DIST = \ config.xml \ README CLEANFILES = *~ subdir = conf mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libconf_la_LDFLAGS = libconf_la_LIBADD = am_libconf_la_OBJECTS = Configuration.lo XMLEntity.lo libconf_la_OBJECTS = $(am_libconf_la_OBJECTS) @BUILD_TOOLS_TRUE@noinst_PROGRAMS = confregress$(EXEEXT) @BUILD_TOOLS_FALSE@noinst_PROGRAMS = PROGRAMS = $(noinst_PROGRAMS) am_confregress_OBJECTS = xmain.$(OBJEXT) confregress_OBJECTS = $(am_confregress_OBJECTS) confregress_DEPENDENCIES = libconf.la ../files/libu7file.la confregress_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/Configuration.Plo \ @AMDEP_TRUE@ $(DEPDIR)/XMLEntity.Plo $(DEPDIR)/xmain.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libconf_la_SOURCES) $(confregress_SOURCES) DIST_COMMON = README Makefile.am Makefile.in SOURCES = $(libconf_la_SOURCES) $(confregress_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu conf/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libconf.la: $(libconf_la_OBJECTS) $(libconf_la_DEPENDENCIES) $(CXXLINK) $(libconf_la_LDFLAGS) $(libconf_la_OBJECTS) $(libconf_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) confregress$(EXEEXT): $(confregress_OBJECTS) $(confregress_DEPENDENCIES) @rm -f confregress$(EXEEXT) $(CXXLINK) $(confregress_LDFLAGS) $(confregress_OBJECTS) $(confregress_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Configuration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/XMLEntity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/xmain.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ distclean distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/conf/XMLEntity.h0000644000175000001440000000414507724430450011136 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef XMLENTITY_H #define XMLENTITY_H #include #include class XMLnode { protected: std::string id; std::string content; std::vector nodelist; bool no_close; public: XMLnode() : no_close(false) { } XMLnode(const std::string &i) : id(i), no_close(false) { } XMLnode(const XMLnode &n) : id(n.id),content(n.content),nodelist(n.nodelist), no_close(false) { } ~XMLnode(); XMLnode &operator=(const XMLnode &n) { id=n.id; content=n.content; nodelist=n.nodelist; no_close = n.no_close; return *this; } const std::string &reference(const std::string &,bool &); const XMLnode *subtree(const std::string &) const; const std::string &value(void) const { return content; } typedef std::pair KeyType; typedef std::vector KeyTypeList; bool searchpairs(KeyTypeList &ktl, const std::string &basekey, const std::string currkey, const unsigned int pos); void selectpairs(KeyTypeList &ktl, const std::string currkey); std::string dump(int depth = 0); void dump(std::ostream &o, const std::string &indentstr, const unsigned int depth=0) const; void xmlassign(const std::string &key, const std::string &value); void xmlparse(const std::string &s,std::size_t &pos); void listkeys(const std::string &,std::vector &, bool longformat=true) const; }; #endif exult-1.2/conf/xmain.cc0000644000175000001440000000724207676104167010565 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "Configuration.h" #include #include #include #include "common_types.h" using std::string; const std::string c_empty_string; using std::cout; using std::cerr; using std::endl; Configuration *config; void dump_stringvec(std::vector &vs,int expect=-2) { size_t n; cout << "vs is " << vs.size() << " entries" << endl; for(n=0;n(vs.size())==expect); } void test1(void) { cerr << "Reading config file: ./config.xml" << endl; config->read_config_file("./config.xml"); cerr << "Config file read." << endl; int n; std::string r; cerr << "Dumping config to stdout." << endl; config->dump(cout, "\t"); cout << endl; cerr << "Testing: config/audio/midi/device" << endl; std::string test_device("config/audio/midi/device"); config->value(test_device, n, -1); cout << "Returned from reference, \"" << test_device << "\". Got '" << n << "'" << endl; assert(n==5); std::string test_enabled("config/audio/midi/enabled"); config->value(test_enabled, r, "--nil--"); cout << "Returned from reference, \"" << test_enabled << "\". Got '" << r << "'" << endl; assert(r=="yes"); std::string test_spaces("config/disk/u7path_with_spaces"); config->value(test_spaces, r, "--nil--"); cout << "Returned from reference, \"" << test_spaces << "\". Got '" << r << "'" << endl; assert(r=="d:\\ultima series\\ultima vii - the serpent isle"); config->set("config/something/something/else", "wibble", false); std::string out=config->dump(); cout << out << endl; std::vector vs; vs=config->listkeys("config"); dump_stringvec(vs,6); vs=config->listkeys("config/audio"); dump_stringvec(vs,4); vs=config->listkeys("config/something",false); dump_stringvec(vs,1); vs=config->listkeys("config/somenonexistantthing"); dump_stringvec(vs,0); config->clear(); //cout << endl << config->dump() << endl; assert(config->dump()=="\n\n"); Configuration config_slash(string(""), string("root")); //cout << endl << config_slash.dump() << endl; assert(config_slash.dump()=="\n\n"); config->clear("foo"); assert(config->dump()=="\n\n"); Configuration confnew("./config.xml", "config"); Configuration::KeyTypeList ktl; string basekey("config/audio"); confnew.getsubkeys(ktl, basekey); cout << endl; for(Configuration::KeyTypeList::iterator i=ktl.begin(); i!=ktl.end(); i++) cout << "Key:\t" << i->first << endl << "Value:\t" << i->second << endl; assert(ktl.size()==7); } void test2(void) { config->read_config_file("exult.cfg"); config->dump(cout, "\t") << endl; } int main(int argc, char *argv[]) { config = new Configuration(); cerr << "Starting tests..." << endl; test1(); if(argc>1) if(strcmp(argv[1], "--exult-cfg")==0) test2(); return 0; } exult-1.2/conf/XMLEntity.cc0000644000175000001440000002153207724430450011273 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "common_types.h" #include "XMLEntity.h" #include using std::string; using std::vector; using std::ostream; using std::endl; static string encode_entity(const string &s); static string close_tag(const string &s); XMLnode::~XMLnode() { for(std::vector::iterator i=nodelist.begin(); i!=nodelist.end(); ++i) delete *i; } const string &XMLnode::reference(const string &h,bool &exists) { if(h.find('/')==string::npos) { // Must refer to me. if(id==h) { exists = true; return content; } } else { // Otherwise we want to split the string at the first / // then locate the branch to walk, and pass the rest // down. string k; k=h.substr(h.find('/')+1); string k2=k.substr(0,k.find('/')); for(std::vector::iterator it=nodelist.begin(); it!=nodelist.end();++it) { if((*it)->id==k2) return (*it)->reference(k,exists); } } exists = false; return c_empty_string; } const XMLnode *XMLnode::subtree(const string &h) const { if(h.find('/') == string::npos) { // Must refer to me. if(id == h) return this; } else { // Otherwise we want to split the string at the first / // then locate the branch to walk, and pass the rest // down. string k; k=h.substr(h.find('/')+1); string k2=k.substr(0,k.find('/')); for(std::vector::const_iterator it=nodelist.begin(); it!=nodelist.end();++it) { if((*it)->id==k2) return (*it)->subtree(k); } } return 0; } string XMLnode::dump(int depth) { string s(depth,' '); s+="<"; s+=id; s+=">\n"; if(id[id.length()-1]!='/') { for(std::vector::const_iterator it=nodelist.begin(); it!=nodelist.end(); ++it) { s += (**it).dump(depth+1); } if(content.length()) { s += string(depth,' '); s += encode_entity(content); } if(id[0]=='?') { return s; } if(content.length()) s += "\n"; if(!no_close) { s += string(depth,' '); s += "\n"; } } return s; } /* Output's a 'nicer' dump of the xmltree, one value per line the indent characters are specified by indentstr */ void XMLnode::dump(ostream &o, const string &indentstr, const unsigned int depth) const { // indent for(unsigned int i=0; i'; // if this tag has a closing tag... if(id[id.length()-1]!='/') { // if we've got some subnodes, terminate this line... if(nodelist.size()) { o << endl; // ... then walk through them outputting them all ... for(std::vector::const_iterator it=nodelist.begin(); it!=nodelist.end(); ++it) (*it)->dump(o, indentstr, depth+1); } // ... else, if we have content in this output it. else if(content.length()) o << ' ' << encode_entity(content) << ' '; // not a clue... it's in XMLnode::dump() so there must be a reason... if(id[0]=='?') return; // append a closing tag if there is one. if(!no_close) { // if we've got subnodes, we need to reindent if(nodelist.size()) for(unsigned int i=0; i'; } } o << endl; } // This function does not make sense here. It should be in XMLEntity void XMLnode::xmlassign(const string &key, const string &value) { if(key.find('/')==string::npos) { // Must refer to me. if(id==key) content = value; else CERR("Walking the XML tree failed to create a final node."); return; } string k; k=key.substr(key.find('/')+1); string k2=k.substr(0,k.find('/')); for(std::vector::iterator it=nodelist.begin();it!=nodelist.end();++it) { if((*it)->id==k2) { (**it).xmlassign(k,value); return; } } // No match, so create a new node and do recursion XMLnode *t = new XMLnode(k2); nodelist.push_back(t); (*t).xmlassign(k,value); } void XMLnode::listkeys(const string &key,vector &vs, bool longformat) const { string s(key); s+="/"; for(std::vector::const_iterator it=nodelist.begin(); it!=nodelist.end(); ++it) { if(!longformat) vs.push_back((*it)->id); else vs.push_back(s + (*it)->id); } } static string encode_entity(const string &s) { string ret; for(string::const_iterator it=s.begin();it!=s.end();++it) { switch(*it) { case '<': ret+="<"; break; case '>': ret+=">"; break; case '"': ret+="""; break; case '\'': ret+="'"; break; case '&': ret+="&"; break; default: ret += *it; } } return ret; } static string decode_entity(const string &s, std::size_t &pos) { std::size_t old_pos = pos; string::size_type entity_name_len = s.find_first_of("; \t\r\n", pos) -pos -1; /* Call me paranoid... but I don't think having an end-of-line or similar inside a &...; expression is 'good', valid though it may be. */ assert(s[pos+entity_name_len+1]==';'); string entity_name = s.substr(pos+1, entity_name_len); pos += entity_name_len + 2; // std::cout << "DECODE: " << entity_name << endl; if (entity_name == "amp") return string("&"); else if(entity_name == "apos") return string("'"); else if(entity_name == "quot") return string("\""); else if(entity_name == "lt") return string("<"); else if(entity_name == "gt") return string(">"); return s.substr(old_pos, entity_name_len+2); } static string close_tag(const string &s) { if(s.find(" ")==string::npos) return s; return s.substr(0,s.find(" ")); } static void trim(string &s) { // Clean off leading whitespace while(s.length()&&s[0]<=32) { s=s.substr(1); } // Clean off trailing whitespace while(s.length()&&s[s.length()-1]<=32) { s.erase(s.length()-1); } } void XMLnode::xmlparse(const string &s,std::size_t &pos) { bool intag = true; id = ""; while(posxmlparse(s,pos); nodelist.push_back(t); break; } case '>': // End of tag if(s[pos-1]=='/') { if(s[pos-2]=='<') { ++pos; return; // An empty tag } else { ++pos; no_close=true; return; } } else if((id[0]=='!') && (id[1]=='-') && (id[2]=='-')) { ++pos; no_close=true; return; } ++pos; intag = false; if(s[pos]<32) ++pos; break; case '&': content+=decode_entity(s,pos); break; default: if(intag) id += s[pos++]; else content += s[pos++]; } } trim(content); } /* Returns a list of key->value pairs that are found under the provided 'basekey'. Ignores comments ( and doesn't return them. Returns true if search is 'finished' */ bool XMLnode::searchpairs(KeyTypeList &ktl, const string &basekey, const string currkey, const unsigned int pos) { /* If our 'current key' is longer then the key we're serching for we've obviously gone too deep in this branch, and we won't find it here. */ if((currkey.size()<=basekey.size()) && (id[0]!='!')) { /* If we've found it, return every key->value pair under this key, then return true, since we've found the key we were looking for. */ if(basekey==currkey+id) { for(std::vector::iterator i=nodelist.begin(); i!=nodelist.end(); ++i) if((*i)->id[0]!='!') (*i)->selectpairs(ktl, ""); return true; } /* Else, keep searching for the key under it's subnodes */ else for(std::vector::iterator i=nodelist.begin(); i!=nodelist.end(); ++i) if((*i)->searchpairs(ktl, basekey, currkey + id + '/', pos)==true) return true; } return false; } /* Just adds every key->value pair under the this node to the ktl */ void XMLnode::selectpairs(KeyTypeList &ktl, const std::string currkey) { ktl.push_back(KeyType(currkey + id, content)); for(std::vector::iterator i=nodelist.begin(); i!=nodelist.end(); ++i) (*i)->selectpairs(ktl, currkey + id + '/'); } exult-1.2/docs/0000777000175000001440000000000010062225335007204 5exult-1.2/docs/expack.10000644000175000001440000000554507707254717010510 .\" -*- nroff -*- .TH expack 1 2002-03-23 Exult .SH NAME expack \- manipulate Flex files .SH SYNOPSIS .B expack -a .IR "FLEXFILE FILE" ... .B expack -c .IR "FLEXFILE FILE" ... .B expack -x .IR FLEXFILE " [" INDEX ] .B expack -i .I MANIFEST .B expack -l .I FLEXFILE .SH DESCRIPTION .B expack is a command-line utility that lets you extract and create Flex files. Flex files are archives (which means that they act as containers for other files, somewhat like directories) used by .I Ultima 7 to store most of its data. Note that the names of the original files are not stored in the Flex \(em files are only retrievable by their index. .SS Modes of operation .TP .BR -a " Add" --NOT IMPLEMENTED YET. FUTURE ENHANCEMENT-- This command adds one or more .IR FILE s to the end of .IR FLEXFILE . .TP .BR -c " Create" This command takes one or more .IR FILE s and bundles them into .IR FLEXFILE , overwriting it in the process. .TP .BR -x " Extract" Lets you extract the files contained within .IR FLEXFILE . If .I INDEX is given only the file at this position will be unpacked, otherwise all files are extracted. The created files will be named \fIindex\fB.u7o\fR. .TP .BR -i " Input" Similar to "Create", this command creates .I FLEXFILE from a number of input files. However, "Input" takes the names of the input files from .I MANIFEST instead of the command line. .I MANIFEST must be a list of file names, one per line. The first name is that of the Flex file that is to be created, the rest are the input files used in building it. .TP .BR -l " List" This command lists the contents of a .IR FLEXFILE . It gives you the number of files contained within the Flex file, as well as the length of each file. .SH EXAMPLES .TP .B expack -a animals.flx bee.wav Adds .B bee.wav to the Flex file .BR animals.flx . .TP .B expack -a animals.flx hamster.wav snake.wav donkey.wav Adds .BR hamster.wav ", " snake.wav ", and " donkey.wav to the Flex file .BR animals.flx . .TP .B expack -c animals.flx duck.wav cat.wav cow.wav dog.wav Creates a new Flex file .B animals.flx containing .BR duck.wav ", " cat.wav ", " cow.wav ", and " dog.wav . .TP .B expack -x text.flx 17 Extracts the file at position .BR 17 from text.flx into 17.u7o . .TP .B expack -x text.flx Extracts all files from .B text.flx into files named .BR 0.u7o ", " 1.u7o ", " 2.u7o ", etc." .TP .B expack -i wavlist With .B wavlist reading: jmsfx.flx .br ant.wav .br bee.wav .br cat.wav will create a new Flex file .B jmsfx.flx consisting of .BR ant.wav ", " bee.wav ", and" cat.wav . .TP .B expack -l text.flx Lists the number and lenghts of files contained in .BR text.flx . .SH BUGS The "Add" command .RB ( -a ) does not work yet. .SH AUTHOR This manpage was written by Robert Bihlmeyer based on a text by Marc Winterrowd. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. exult-1.2/docs/textpack.10000644000175000001440000000416107707254717011051 .\" -*- nroff -*- .TH textpack 1 2002-03-24 Exult .SH NAME textpack \- Pack and unpack Flex files containing text .SH SYNOPSIS .B textpack -c .I FLEXFILE .RI [ TEXTFILE ] .B textpack -x .I FLEXFILE .RI [ TEXTFILE ] .SH DESCRIPTION Text Flex files are used for the storage of strings by the games .I Exult supports. While .BR expack (1) can operate on such files, using .B textpack to pack and unpack them is more comfortable. The first parameter determines the mode of operation, .B -c stands for creation, .B -x for extraction. .SS Creation .I TEXTFILE (or stdin if it is missing) is read and must conform to the file format (see below). .I FLEXFILE will be created containing the strings from this input. .SS Extraction The strings contained in .I FLEXFILE are extracted and written to .I TEXTFILE (if given, stdout otherwise) in the file format documented below. .SS File Format Empty lines, and lines starting with a pound sign .RB ( # ) are ignored. Other lines must begin with a number, followed by a colon .RB ( : ). The number is the index of the string and may be given either in decimal, in octal prefixed with .BR 0 ; or in hexadecimal prefixed with .BR 0x . Anything following the colon belongs to the string and gets stored in the Flex verbatim. Lines are limited in length to 1024 characters. .SH EXAMPLES .TP .B textpack -x text.flx Writes all the strings contained in .B text.flx to stdout in the format discussed above. .TP .B textpack -c text.flx strings.list Reads .B strings.list and puts its contents into the Flex file .B text.flx .SS Example text file # An example .br 0:the zeroth string .br # strings may be empty .br 1: .br # holes are allowed, strings 2 to 16 will be empty .br 17:string seventeen .br # 13 hexadecimal == 19 decimal, 24 octal == 20 decimal .br 0x13:nineteen .br 024:twenty .br # numbers need not go up .br 18:eighteen .br # this will overwrite the definition from above .br 19:overwritten .SH AUTHOR This manpage was written by Robert Bihlmeyer. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. .SH SEE ALSO .BR expack "(1), " exult (6) exult-1.2/docs/exult.60000644000175000001440000000506607707266630010376 .\" -*- nroff -*- .TH exult 6 "July 22, 2003" .SH NAME exult \- an engine for running Ultima VII .SH SYNOPSIS .B exult .RI [ options ] .br .SH DESCRIPTION .B Exult is an engine built for running Ultima VII. It started its life as a map-browser for Ultima VII and has evolved from there, thanks to the open source-model and contributions of time and code from many people. .PP You cannot use \fBExult\fP without game data files. At present, the only finished games are Origin's Ultima VII: The Black Gate and Ultima VII, Part 2: The Serpent Isle. In any case, both Ultima VII's are some of the best computer Role-Playing-Games made to date. Check your local computer dealer's bargain bin or an online auction site. Ultima VII can still be purchased for only a few dollars. Run out and buy it! .PP There is a world editor available to create your own games: Exult Studio. Check the \fBexult\fP homepage (URL below) for more information. .SH OPTIONS .TP -h, --help Show the available command-line options .TP -v, --version Display (detailed) \fBExult\fP version information .TP -c \fIconfigfile\fR Specify an alternate configuration file to load .TP --bg Skip the main \fBExult\fP menu and run Black Gate .TP --si Skip the main \fBExult\fP menu and run Serpent Isle .TP --nomenu Skip the game menu for BG/SI .TP --buildmap \fItype\fR Create a fullsize map of the current gameworld. If \fItype\fR = 0, paint all roofs. If \fItype\fR = 0, skip second-floor roofs. If \fItype\fR = 2, don't paint any roofs. You also need to specify --bg or --si. .TP --nocrc Skip the CRC check of the .flx datafiles. Only use this if you modified them yourself without recompiling .B exult .SH FILES See the README supplied with \fBexult\fP for information on this (Note: you NEED this configuration file to set up and run the game). .SH NOTES For more help and information with \fBexult\fP go to: .IP http://exult.sourceforge.net/ .IP http://sourceforge.net/projects/exult/ .PP Ultima itself remains the property of Origin Systems, Inc. Ultima VII (The Black Gate) is copyright Origin Systems, Inc. Ultima VII (The Serpent Isle) is copyright Origin Systems, Inc. The Exult Team is in no way affiliated with Origin Systems, Inc., Electronic Arts, and those companies probably neither know nor care about \fBExult\fP. Don't go bugging them if you have problems. Bug the Exult Team instead. .SH BUGS There are always bugs. Please report them at: .IP http://sourceforge.net/bugs/?group_id=2335 (be sure to mention information about your operating system, and which version of \fBexult\fP you are running) .SH AUTHOR The Exult Team exult-1.2/docs/Makefile.am0000644000175000001440000000055307707254717011201 man_MANS = exult.6 expack.1 ipack.1 shp2pcx.1 splitshp.1 textpack.1 EXTRA_DIST = \ $(man_MANS) # FLI.txt \ # exscript.txt \ # items.txt \ # schedule.txt \ # u7combat.txt \ # u7edit.txt \ # u7eggs.txt \ # u7itemtypes.txt \ # u7monst.txt \ # u7playend.zip \ # u7ready.txt \ # u7tech.txt \ # unknown \ # usedis.zip \ # weapons.txt \ # wuc.zip CLEANFILES = *~ exult-1.2/docs/Makefile.in0000644000175000001440000002203410061527072011170 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ man_MANS = exult.6 expack.1 ipack.1 shp2pcx.1 splitshp.1 textpack.1 EXTRA_DIST = \ $(man_MANS) # FLI.txt \ # exscript.txt \ # items.txt \ # schedule.txt \ # u7combat.txt \ # u7edit.txt \ # u7eggs.txt \ # u7itemtypes.txt \ # u7monst.txt \ # u7playend.zip \ # u7ready.txt \ # u7tech.txt \ # unknown \ # usedis.zip \ # weapons.txt \ # wuc.zip CLEANFILES = *~ subdir = docs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu docs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: man1dir = $(mandir)/man1 install-man1: $(man1_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man1dir) @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ done uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ rm -f $(DESTDIR)$(man1dir)/$$inst; \ done man6dir = $(mandir)/man6 install-man6: $(man6_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man6dir) @list='$(man6_MANS) $(dist_man6_MANS) $(nodist_man6_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.6*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst; \ done uninstall-man6: @$(NORMAL_UNINSTALL) @list='$(man6_MANS) $(dist_man6_MANS) $(nodist_man6_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.6*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man6dir)/$$inst"; \ rm -f $(DESTDIR)$(man6dir)/$$inst; \ done tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(man1dir) $(DESTDIR)$(man6dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-info: install-info-am install-man: install-man1 install-man6 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-man uninstall-man: uninstall-man1 uninstall-man6 .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man1 install-man6 \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool uninstall uninstall-am \ uninstall-info-am uninstall-man uninstall-man1 uninstall-man6 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/docs/splitshp.10000644000175000001440000000407007707254717011073 .\" -*- nroff -*- .TH splitshp 1 2002-03-24 Exult .SH NAME splitshp \- Split Shape into frames or combine frames into Shapes .SH SYNOPSIS .B splitshp .I SHAPE .IR FRAME ... .B splitshp .I SHAPE .SH DESCRIPTION Shape files are used for storage of all visible elements (from UI buttons to terrain features) of the games .I Exult supports. Shapes contain one or more frames. .B splitshp can be used to combine frames into one file, or split a Shape file into its component frames. The mode of operation is determined by looking at the number of commandline arguments. Exactly one argument means splitting, more than one argument signals a combining operation. .SS Combining Each .I FRAME names a Shape file typically consisting of only one frame (i.e. subsequent frames are ignored). All these frames are concatenated and written to the Shape file .IR SHAPE . .SS Splitting .I SHAPE will be read and split into its component frames. Each of those will be written to its own Shape file. The names of these files are determined by splitting the name of .I SHAPE before the last dot \(em anything before this dot is the .IR STEM , anything else (including the dot) is the .IR PREFIX , which may be empty in case there is no dot in the name. The output files are then named .I STEM_nnSUFFIX with .I nn replaced by the frame number. .SH EXAMPLES .TP .B splitshp button.shp button-up.shp button-down.shp Packs the (first) two frames from .B button-up.shp and .B button-down.shp into the Shape file .B button.shp .TP .B splitshp grizzly Unpacks the frames contained in the Shape file .B grizzly into the (single-frame) Shape files .BR grizzly_00 ", " grizzly_01 ", " grizzly_02 ", etc." .TP .B splitshp boar.new.shp Unpacks the frames contained in the Shape file .B boar.new.shp into the (single-frame) Shape files .BR boar.new_00.shp ", " boar.new_01.shp ", " boar.new_02.shp ", etc." .SH AUTHOR This manpage was written by Robert Bihlmeyer. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. .SH SEE ALSO .BR exult "(6), " shp2pcx (1) exult-1.2/docs/shp2pcx.10000644000175000001440000000246507707254717010622 .\" -*- nroff -*- .TH shp2pcx 1 2002-03-24 Exult .SH NAME shp2pcx \- extract images from a Shape (SHP) file into PCX files .SH SYNOPSIS .B shp2pcx .I SHAPE PREFIX PALETTE .SH DESCRIPTION .B shp2pcx converts all frames contained in a Shape file into PCX-format image files. Shape files are used for storage of all visible elements (from UI buttons to terrain features) of the games .I Exult supports. .I SHAPE is the name of the Shape file acting as the source. Frames contained therein are saved as PCX files named .IB PREFIXnn .pcx with .I nn replaced by the frame number (counting from zero). All PCX files get their palette from .IR PALETTE . Before extraction the number of frames, and the Shape's origin coordinates are shown. Additionally, extraction progress is communicated by printing a message containing the resulting file's name for every processed frame. .SH EXAMPLES .TP .B shp2pcx orc.shp orc std.pal Takes the frames contained in the Shape file .BR orc.shp , and saves them with the palette from .B std.pal into PCX files .BR orc00.pcx ", " orc01.pcx ", " orc02.pcx ", etc." .SH AUTHOR This manpage was written by Robert Bihlmeyer. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. .SH SEE ALSO .BR exult "(6), " pcxtoppm "(1), " splitshp (1) exult-1.2/docs/ipack.10000644000175000001440000000646007707254717010321 .\" -*- nroff -*- .TH ipack 1 2002-03-24 Exult .SH NAME ipack \- Manipulate Flex files containing Shapes .SH SYNOPSIS .B ipack -c .I SCRIPT .B ipack -x .I SCRIPT .B ipack -u .I SCRIPT .SH DESCRIPTION Flex files containing Shapes are used for the storage visual elements by the games .I Exult supports. While .BR expack (1) can operate on such files, using .B ipack is more comfortable. It can extract images from the Flex file directly into PNG-format, and create or update Flex files from a list of PNG files. The first parameter determines the mode of operation: .TP .BR -c " Creation" New Flex and palette files are created according to the instructions contained in the .I SCRIPT file. .TP .BR -u " Update" Works like Creation, but updates an existing Flex file. .TP .BR -x " Extraction" The contents of the Flex file described in the .I SCRIPT file are extracted as PNG is dissected into its contents, as described in this script file. .SS Script File Format Empty lines, and lines starting with a pound sign .RB ( # ) are ignored. The names of the associated Flex archive and palette files are given in lines containing optional whitespace, one of the tokens .BR archive " or " palette , whitespace, and the filename. Other lines define one shape each, and must begin with an image slot number, followed by a slash .RB ( / ), the number of frames, a colon .RB ( : ), and finally the PNG file specification. The numbers may be given either in decimal, in octal prefixed with .BR 0 ; or in hexadecimal prefixed with .BR 0x . The file specification consists of the filename .IR PREFIX , optionally followed by a number and direction in brackets, optionally followed by whitespace and the word .BR flat . Per default, each shape corresponds to a number of PNG files (one for each frame) named .IB PREFIXnn .png with .I nn replaced by the frame number. If the optional bracket expression is used in the specification the Shape corresponds to a single PNG file instead. This file contains all frames, each of which is 8 by 8 pixels in size, arranged next to each other in a rectangular grid. The number in the bracket expression gives the size of this grid in the direction indicated. The direction can be either .B down or .BR across . .SH EXAMPLES .TP .B ipack -c island.scr Creates a Flex file and a palette file as specified by .BR island.scr . .TP .B ipack -x island.scr Extracts all components described in .B island.scr from the Flex file given therein. .SS Example script # script file for island.flx .br archive island.flx .br # put the palette into this file .br palette island.pal .br # the zeroth image has 32 frames in the files .br # zero00.png to zero31.png .br 0/32:zero .br # image 5 consists of 22 frames stored in file .br # five.png in a grid 5 frames across (which means .br # 5 rows of which the last holds only 2 frames) .br 5/22:five(5 across) flat .br # image 4 consists of 12 frames stored in file .br # four.png in a 3 by 4 grid .br 4/12:four(4 down) flat .br # images 1 to 3 are unspecified .SH BUGS Tiled Shapes are currently extracted into multiple PNG files, not a single file as expected during Create/Update. .SH AUTHOR This manpage was written by Robert Bihlmeyer. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. .SH SEE ALSO .BR expack "(1), " exult (6) exult-1.2/flic/0000777000175000001440000000000010062225327007172 5exult-1.2/flic/playfli.cc0000644000175000001440000001517710054030557011070 /** ** playfli.cc - Play Autodesk Animator FLIs ** ** Written: 5/5/2000 - TST **/ /* Copyright (C) 2000 Tristan Tarrant This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include #include "databuf.h" #include "playfli.h" #include "utils.h" #include "gamewin.h" #include "palette.h" #include "SDL_timer.h" #ifndef UNDER_CE using std::ifstream; using std::memset; using std::size_t; using std::cout; using std::endl; #endif playfli::playfli(const char *fli_name) { ifstream fli_stream; U7open(fli_stream, fli_name); fli_data = new StreamDataSource(&fli_stream); initfli(); } playfli::playfli(char *buffer, size_t len): fli_data(new BufferDataSource(buffer, len)) { initfli(); } void playfli::initfli() { fli_size = fli_data->read4(); fli_magic = fli_data->read2(); fli_frames = fli_data->read2(); fli_width = fli_data->read2(); fli_height = fli_data->read2(); fli_depth = fli_data->read2(); fli_flags = fli_data->read2(); fli_speed = fli_data->read2(); fli_buf = NULL; fli_data->skip(110); streampos = streamstart = fli_data->getPos(); frame = 0; palette = new Palette; thispal = -1; nextpal = 0; changepal = false; } void playfli::info(fliinfo *fi) { #ifdef DEBUG cout << "Frame count : " << fli_frames << endl; cout << "Width : " << fli_width << endl; cout << "Height : " << fli_height << endl; cout << "Depth : " << fli_depth << endl; cout << "Speed : " << fli_speed << endl; #endif if (fi) { fi->frames = fli_frames; fi->width = fli_width; fi->height = fli_height; fi->depth = fli_depth; fi->speed = fli_speed; } } int playfli::play(Image_window *win, int first_frame, int last_frame, unsigned long ticks, int brightness) { int frame_size; int frame_magic; int frame_chunks; int chunk_size; int chunk_type; unsigned char *pixbuf; int xoffset=(win->get_width()-fli_width)/2; int yoffset=(win->get_height()-fli_height)/2; bool dont_show = false; if (!fli_buf && win) fli_buf = win->create_buffer (fli_width, fli_height); // Set up last frame if (first_frame == last_frame) dont_show = true; if (first_frame < 0) first_frame += fli_frames; if (last_frame < 0) last_frame += 1 + fli_frames; if (first_frame == last_frame) last_frame++; if (last_frame < 0 || last_frame > fli_frames) last_frame = fli_frames; if (!ticks) ticks = SDL_GetTicks(); if (first_frame < frame) { nextpal = 0; frame = 0; streampos = streamstart; } pixbuf = new unsigned char[fli_width]; if (brightness != palette->get_brightness()) { palette->set_brightness(brightness); changepal = true; } // Play frames... for ( ; frame < last_frame; frame++) { fli_data->seek(streampos); frame_size = fli_data->read4(); frame_magic = fli_data->read2(); frame_chunks = fli_data->read2(); fli_data->skip(8); for (int chunk = 0; chunk < frame_chunks; chunk++) { chunk_size = fli_data->read4(); chunk_type = fli_data->read2(); switch (chunk_type) { case 11: { int packets = fli_data->read2(); unsigned char colors[3 * 256]; memset(colors, 0, 3 * 256); int current = 0; for (int p_count = 0; p_count < packets; p_count++) { int skip = fli_data->read1(); current += skip; int change = fli_data->read1(); if (change == 0) change = 256; fli_data->read((char*)&colors[current*3], change*3); } // Set palette palette->set_palette (colors); if (thispal != nextpal) { thispal = nextpal; changepal = true; } nextpal++; } break; case 12: { int skip_lines = fli_data->read2(); int change_lines = fli_data->read2(); for (int line = 0; line < change_lines; line++) { int packets = fli_data->read1(); int pixpos = 0; for (int p_count = 0; p_count < packets; p_count++) { int skip_count = fli_data->read1(); pixpos += skip_count; uint8 size_count = fli_data->read1(); if (size_count > 127) { size_count = 256 - size_count; unsigned char data = fli_data->read1(); memset(pixbuf, data, size_count); if (fli_buf) fli_buf->copy8(pixbuf,size_count,1,pixpos,skip_lines+line); pixpos += size_count; } else { fli_data->read((char*)pixbuf, size_count); if (fli_buf) fli_buf->copy8(pixbuf,size_count,1,pixpos, skip_lines+line); pixpos += size_count; } } } } break; case 13: break; case 15: { for (int line = 0; line < fli_height; line++) { int packets = fli_data->read1(); int pixpos = 0; for (int p_count = 0; p_count < packets; p_count++) { char size_count = fli_data->read1(); if (size_count > 0) { unsigned char data = fli_data->read1(); memset(&pixbuf[pixpos], data, size_count); pixpos += size_count; } else { fli_data->read((char*)&pixbuf[pixpos], -size_count); pixpos -= size_count; } } if (fli_buf) fli_buf->copy8(pixbuf,fli_width,1,0,line); } } break; case 16: fli_data->skip(fli_width * fli_height); break; default: cout << "UNKNOWN FLIC FRAME" << endl; break; } } streampos += frame_size; if (changepal) palette->apply(false); changepal = false; if (frame < first_frame) continue; // Speed related frame skipping detection int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= ticks; if(win && fli_buf) win->put (fli_buf, xoffset, yoffset); while (SDL_GetTicks() < ticks) SDL_Delay(0); ticks += fli_speed*10; if(win && !dont_show && !skip_frame) win->show(); } delete[] pixbuf; return ticks; } void playfli::put_buffer(Image_window *win) { int xoffset=(win->get_width()-fli_width)/2; int yoffset=(win->get_height()-fli_height)/2; if(win && fli_buf) win->put (fli_buf, xoffset, yoffset); } playfli::~playfli() { if (fli_buf) delete fli_buf; delete fli_data; delete palette; } exult-1.2/flic/playfli.h0000644000175000001440000000340007724430451010723 /* * playfli.cc - Play Autodesk Animator FLIs * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLAYFLI_H #define PLAYFLI_H #include "databuf.h" #include "imagewin.h" class Palette; class playfli { public: struct fliinfo { int frames; int width; int height; int depth; int speed; }; private: DataSource *fli_data; int fli_size; int fli_magic; int fli_frames; int fli_width; int fli_height; int fli_depth; int fli_flags; int fli_speed; Image_buffer *fli_buf; int streamstart; int streampos; int frame; Palette *palette; public: playfli(const char *fli_name); playfli(char *buffer, std::size_t len); ~playfli(); void info(fliinfo *fi = NULL); int play(Image_window *win, int first_frame = 0, int last_frame = -1, unsigned long ticks = 0, int brightness = 100); void put_buffer(Image_window *win); inline Palette *get_palette () { return palette; } private: void initfli(); int nextpal; int thispal; int changepal; }; #endif exult-1.2/flic/Makefile.am0000644000175000001440000000047207431011317011143 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../files \ -I$(srcdir)/../objs -I$(srcdir)/../shapes\ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libflic.la libflic_la_SOURCES = \ playfli.cc \ playfli.h CLEANFILES = *~ exult-1.2/flic/Makefile.in0000644000175000001440000002333210061527053011156 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../files \ -I$(srcdir)/../objs -I$(srcdir)/../shapes\ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libflic.la libflic_la_SOURCES = \ playfli.cc \ playfli.h CLEANFILES = *~ subdir = flic mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libflic_la_LDFLAGS = libflic_la_LIBADD = am_libflic_la_OBJECTS = playfli.lo libflic_la_OBJECTS = $(am_libflic_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/playfli.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libflic_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libflic_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu flic/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libflic.la: $(libflic_la_OBJECTS) $(libflic_la_DEPENDENCIES) $(CXXLINK) $(libflic_la_LDFLAGS) $(libflic_la_OBJECTS) $(libflic_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/playfli.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/objs/0000777000175000001440000000000010062225334007210 5exult-1.2/objs/jawbone.h0000644000175000001440000000310307470135447010735 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _JAWBONE_H_ #define _JAWBONE_H_ #include "contain.h" class Jawbone_object : public Container_game_object { friend class Jawbone_gump; public: Jawbone_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, char res = 0) : Container_game_object(shapenum, framenum, tilex, tiley, lft, res) { } Jawbone_object() : Container_game_object() { } //virtual ~Jawbone_object() { }; // Add an object. virtual bool add(Game_object *obj, bool dont_check = false, bool combine = false); // Remove an object. virtual void remove(Game_object *obj); // Under attack. -> do nothing virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0, int ammo_shape = 0) { return this; } private: Game_object* teeth[19]; int toothcount; void find_teeth(); void update_frame(); }; #endif exult-1.2/objs/egg.h0000644000175000001440000001557007724430452010061 /* * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_EGG #define INCL_EGG 1 class Egg_object; class Animated_egg_object; class Animator; class Monster_actor; class Missile_launcher; #include "iregobjs.h" /* * Here's a class for eggs and paths; i.e., objects that generally aren't * visible. */ class Egglike_game_object : public Ireg_game_object { public: Egglike_game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0) : Ireg_game_object(shapenum, framenum, tilex, tiley, lft) { } // Render. virtual void paint(); // Can this be clicked on? virtual int is_findable(); }; /* * An "egg" is a special object that activates under certain * circumstances. */ class Egg_object : public Egglike_game_object { static Egg_object *editing; // Egg being edited by ExultStudio. protected: unsigned char type; // One of the below types. unsigned char probability; // 1-100, chance of egg activating. unsigned char criteria:3; // How it's activated. See below. unsigned distance:6; // Distance for activation (0-31). unsigned flags:4; // Formed from below flags. unsigned short data1, data2; // More data, depending on type. Rectangle area; // Active area. unsigned char solid_area; // 1 if area is solid, 0 if outline. Missile_launcher *launcher; // For missile eggs. void init_field(unsigned char ty); void activate_teleport(Game_object *obj); // Handle teleport egg. public: enum Egg_types { // Types of eggs: monster = 1, jukebox = 2, soundsfx = 3, voice = 4, usecode = 5, missile = 6, teleport = 7, weather = 8, path = 9, button = 10, // Our own: fire_field = 128, sleep_field = 129, poison_field = 130, caltrops_field = 131, mirror_object = 132 }; enum Egg_flag_shifts { nocturnal = 0, once = 1, hatched = 2, auto_reset = 3 }; enum Egg_criteria { cached_in = 0, // Activated when chunk read in? party_near = 1, avatar_near = 2, // Avatar steps into area. avatar_far = 3, // Avatar steps outside area. avatar_footpad = 4, // Avatar must step on it. party_footpad = 5, something_on = 6, // Something placed on/near it. external_criteria = 7 // Appears on Isle of Avatar. Guessing // these set off all nearby. }; // Create normal eggs. Egg_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned short itype, unsigned char prob, short d1, short d2); // Ctor. for fields: Egg_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned char ty); virtual ~Egg_object(); virtual void set_area(); // Set up active area. int get_distance() const { return distance; } int get_criteria() const { return criteria; } int get_type() const { return type; } // Can it be activated? virtual int is_active(Game_object *obj, int tx, int ty, int tz, int from_tx, int from_ty); Rectangle get_area() const // Get active area. { return area; } int is_solid_area() const { return solid_area; } // Render. virtual void paint(); // Run usecode function. virtual void activate(int event = 1); virtual bool edit(); // Edit in ExultStudio. // Saved from ExultStudio. static void update_from_studio(unsigned char *data, int datalen); virtual void activate(Game_object *obj, bool must = false); void print_debug(); static void set_weather(int weather, int len = 15, Game_object *egg = 0); // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); // Remove/delete this object. virtual void remove_this(int nodel = 0); virtual int is_egg() const // An egg? { return 1; } // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); virtual void reset() { flags &= ~(1 << hatched); } virtual Egg_object *as_egg() { return this; } }; /* * An object that cycles through its frames, or wiggles if just one * frame. */ class Animated_egg_object : public Egg_object { protected: Animator *animator; // Controls animation. public: Animated_egg_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned short itype, unsigned char prob, short d1, short d2); Animated_egg_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned char ty); virtual ~Animated_egg_object(); // Render. virtual void paint(); // Can this be clicked on? virtual int is_findable() { return Ireg_game_object::is_findable(); } // Run usecode function. virtual void activate(int event = 1); void stop_animation(); }; /* * Fields are activated like eggs. */ class Field_object : public Animated_egg_object { bool field_effect(Actor *actor);// Apply field. public: Field_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned char ty) : Animated_egg_object(shapenum, framenum, tilex, tiley, lft, ty) { } // Run usecode function. virtual void activate(int event = 1); virtual void activate(Game_object *obj, bool must = false); // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); }; /* * Mirrors are handled like eggs. */ class Mirror_object : public Egg_object { public: Mirror_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft); // Run usecode function. virtual void activate(int event = 1); virtual void activate(Game_object *obj, bool must = false); // Can it be activated? virtual int is_active(Game_object *obj, int tx, int ty, int tz, int from_tx, int from_ty); virtual void set_area(); // Set up active area. // Render. virtual void paint(); // Can this be clicked on? virtual int is_findable() { return Ireg_game_object::is_findable(); } virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); }; #endif exult-1.2/objs/chunks.cc0000644000175000001440000011612510054030565010735 /** ** Chunks.cc - Chunks (16x16 tiles) on the map. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "chunks.h" #include "chunkter.h" #include "gamewin.h" #include "gamemap.h" #include "shapeinf.h" #include "citerate.h" #include "egg.h" #include "objiter.h" #include "objs.h" #include "ordinfo.h" #include "game.h" #include "animate.h" #include "dir.h" #include "actors.h" #if 0 #include using std::cout; using std::endl; #endif #ifndef UNDER_CE using std::memset; using std::rand; #endif /* * Create the cached data storage for a chunk. */ Chunk_cache::Chunk_cache ( ) : egg_objects(4) { memset((char *) &blocked[0], 0, sizeof(blocked)); memset((char *) &eggs[0], 0, sizeof(eggs)); } /* * Delete cache. */ Chunk_cache::~Chunk_cache ( ) { } /* * This mask gives the low bits (b0) for a given # of ztiles. */ unsigned long tmasks[16] = { 0x0L, 0x1L, 0x5L, 0x15L, 0x55L, 0x155L, 0x555L, 0x1555L, 0x5555L, 0x15555L, 0x55555L, 0x155555L, 0x555555L, 0x1555555L, 0x5555555L, 0x15555555L }; /* * Set (actually, increment count) for a given tile. * Want: 00 => 01, 01 => 10, * 10 => 11, 11 => 11. * So: newb0 = !b0 OR b1, * newb1 = b1 OR b0 */ inline void Set_blocked_tile ( unsigned long *blocked, // 16x16 flags, int tx, int ty, // Tile #'s (0-15). int lift, // Starting lift to set. int ztiles // # tiles along z-axis. ) { unsigned long& val = blocked[ty*c_tiles_per_chunk + tx]; // Get mask for the bit0's: unsigned long mask0 = tmasks[ztiles]<<2*lift; unsigned long mask1 = mask0<<1; // Mask for the bit1's. unsigned long val0s = val&mask0; unsigned long Nval0s = (~val)&mask0; unsigned long val1s = val&mask1; unsigned long newval = val1s | (val0s<<1) | Nval0s | (val1s>>1); // Replace old values with new. val = (val&~(mask0|mask1)) | newval; } /* * Clear (actually, decrement count) for a given tile. * Want: 00 => 00, 01 => 00, * 10 => 01, 11 => 10. * So: newb0 = b1 AND !b0 * newb1 = b1 AND b0 */ inline void Clear_blocked_tile ( unsigned long *blocked, // 16x16 flags, int tx, int ty, // Tile #'s (0-15). int lift, // Starting lift to set. int ztiles // # tiles along z-axis. ) { unsigned long& val = blocked[ty*c_tiles_per_chunk + tx]; // Get mask for the bit0's: unsigned long mask0 = tmasks[ztiles]<<2*lift; unsigned long mask1 = mask0<<1; // Mask for the bit1's. unsigned long val0s = val&mask0; unsigned long Nval0s = (~val)&mask0; unsigned long val1s = val&mask1; unsigned long newval = (val1s & (val0s<<1)) | ((val1s>>1) & Nval0s); // Replace old values with new. val = (val&~(mask0|mask1)) | newval; } /* * Set/unset the blocked flags in a region. */ void Chunk_cache::set_blocked ( int startx, int starty, // Starting tile #'s. int endx, int endy, // Ending tile #'s. int lift, int ztiles, // Lift, height info. bool set // 1 to add, 0 to remove. ) { if (set) { for (int y = starty; y <= endy; y++) for (int x = startx; x <= endx; x++) Set_blocked_tile(blocked, x, y, lift, ztiles); } else { for (int y = starty; y <= endy; y++) for (int x = startx; x <= endx; x++) Clear_blocked_tile(blocked,x, y, lift, ztiles); } } /* * Add/remove an object to/from the cache. */ void Chunk_cache::update_object ( Map_chunk *chunk, Game_object *obj, bool add // 1 to add, 0 to remove. ) { Shape_info& info = obj->get_info(); if (info.is_door()) // Special door list. if (add) doors.append(obj); else doors.remove(obj); int ztiles = info.get_3d_height(); if (!ztiles || !info.is_solid()) return; // Skip if not an obstacle. // Get lower-right corner of obj. int endx = obj->get_tx(); int endy = obj->get_ty(); int frame = obj->get_framenum();// Get footprint dimensions. int xtiles = info.get_3d_xtiles(frame); int ytiles = info.get_3d_ytiles(frame); int lift = obj->get_lift(); if (xtiles == 1 && ytiles == 1) // Simplest case? { if (add) Set_blocked_tile(blocked, endx, endy, lift, ztiles); else Clear_blocked_tile(blocked, endx, endy, lift, ztiles); return; } Rectangle footprint = obj->get_footprint(); // Go through interesected chunks. Chunk_intersect_iterator next_chunk(footprint); Rectangle tiles; int cx, cy; while (next_chunk.get_next(tiles, cx, cy)) gmap->get_chunk(cx, cy)->set_blocked(tiles.x, tiles.y, tiles.x + tiles.w - 1, tiles.y + tiles.h - 1, lift, ztiles, add); } /* * Set a rectangle of tiles within this chunk to be under the influence * of a given egg, or clear it. */ void Chunk_cache::set_egged ( Egg_object *egg, Rectangle& tiles, // Range of tiles within chunk. bool add // 1 to add, 0 to remove. ) { // Egg already there? int eggnum = egg_objects.find(egg); if (add) { if (eggnum < 0) // No, so add it. eggnum = egg_objects.put(egg); if (eggnum > 15) // We only have 16 bits. eggnum = 15; short mask = (1<= egg_objects.size()) return; // Not there. egg_objects[eggnum] = NULL; if (eggnum >= 15) // We only have 16 bits. { // Last one at 15 or above? for (Egg_vector::const_iterator it = egg_objects.begin() + 15; it != egg_objects.end(); ++it) if (*it != 0) // No, so leave bits alone. return; eggnum = 15; } short mask = ~(1<get_area(); if (!foot.w) return; // Empty (probability = 0). Rectangle crect; // Gets tiles within each chunk. int cx, cy; if (egg->is_solid_area()) { // Do solid rectangle. Chunk_intersect_iterator all(foot); while (all.get_next(crect, cx, cy)) gmap->get_chunk(cx, cy)->set_egged(egg, crect, add); return; } // Just do the perimeter. Rectangle top(foot.x, foot.y, foot.w, 1); Rectangle bottom(foot.x, foot.y + foot.h - 1, foot.w, 1); Rectangle left(foot.x, foot.y + 1, 1, foot.h - 2); Rectangle right(foot.x + foot.w - 1, foot.y + 1, 1, foot.h - 2); // Go through intersected chunks. Chunk_intersect_iterator tops(top); while (tops.get_next(crect, cx, cy)) gmap->get_chunk(cx, cy)->set_egged(egg, crect, add); Chunk_intersect_iterator bottoms(bottom); while (bottoms.get_next(crect, cx, cy)) gmap->get_chunk(cx, cy)->set_egged(egg, crect, add); Chunk_intersect_iterator lefts(left); while (lefts.get_next(crect, cx, cy)) gmap->get_chunk(cx, cy)->set_egged(egg, crect, add); Chunk_intersect_iterator rights(right); while (rights.get_next(crect, cx, cy)) gmap->get_chunk(cx, cy)->set_egged(egg, crect, add); } /* * Create the cached data for a chunk. */ void Chunk_cache::setup ( Map_chunk *chunk ) { Game_object *obj; // Set 'blocked' tiles. Object_iterator next(chunk->get_objects()); while ((obj = next.get_next()) != 0) if (obj->is_egg()) update_egg(chunk, (Egg_object *) obj, 1); else update_object(chunk, obj, 1); obj_list = chunk; } /* * Get highest blocked lift below a given level for a given tile. * * Output: Highest lift that's blocked by an object, or -1 if none. */ inline int Chunk_cache::get_highest_blocked ( int lift, // Look below this lift. unsigned long tflags // Flags for desired tile. ) { int i; // Look downwards. for (i = lift - 1; i >= 0 && !(tflags & (3<<(2*i))); i--) ; return i; } /* * Get highest blocked lift below a given level for a given tile. * * Output: Highest lift that's blocked by an object, or -1 if none. */ int Chunk_cache::get_highest_blocked ( int lift, // Look below this lift. int tx, int ty // Square to test. ) { return get_highest_blocked(lift, blocked[ty*c_tiles_per_chunk + tx]); } /* * Get highest blocked lift below a given level for a given tile. * * Output: Highest lift that's blocked by an object, or -1 if none. */ inline int Chunk_cache::get_lowest_blocked ( int lift, // Look above this lift. unsigned long tflags // Flags for desired tile. ) { int i; // Look upward. for (i = lift; i < 16 && !(tflags & (3<<(2*i))); i++) ; if (i == 16) return -1; return i; } /* * Get lowest blocked lift above a given level for a given tile. * * Output: Lowest lift that's blocked by an object, or -1 if none. */ int Chunk_cache::get_lowest_blocked ( int lift, // Look below this lift. int tx, int ty // Square to test. ) { return get_lowest_blocked(lift, blocked[ty*c_tiles_per_chunk + tx]); } /* * See if a tile is water or land. */ inline void Check_terrain ( Map_chunk *nlist, // Chunk. int tx, int ty, // Tile within chunk. int& terrain // Sets: bit0 if land, bit1 if water, // bit2 if solid. ) { ShapeID flat = nlist->get_flat(tx, ty); if (!flat.is_invalid()) { if (flat.get_info().is_water()) terrain |= 2; else if (flat.get_info().is_solid()) terrain |= 4; else terrain |= 1; } } /* * Is a given square occupied at a given lift? * * Output: 1 if so, else 0. * If 0 (tile is free), new_lift contains the new height that * an actor will be at if he walks onto the tile. */ int Chunk_cache::is_blocked ( int height, // Height (in tiles) of obj. being // tested. int lift, // Given lift. int tx, int ty, // Square to test. int& new_lift, // New lift returned. const int move_flags, int max_drop, // Max. drop/rise allowed. int max_rise // Max. rise, or -1 to use old beha- // viour (max_drop if FLY, else 1). ) { // Ethereal beings always return not blocked // and can only move horizontally if (move_flags & MOVE_ETHEREAL) { new_lift = lift; return 0; } // Get bits. unsigned long tflags = blocked[ty*c_tiles_per_chunk + tx]; // Figure max lift allowed. if (max_rise == -1) max_rise = (move_flags & MOVE_FLY) ? max_drop : 1; int max_lift = lift + max_rise; if (max_lift > 15) max_lift = 15; // As high as we can go. for (new_lift = lift; new_lift <= max_lift; new_lift++) { if ((tflags & (3 << (2*new_lift))) == 0) { // Not blocked? int new_high = get_lowest_blocked(new_lift, tflags); // Not blocked above? if (new_high == -1 || new_high >= (new_lift + height)) break; // Okay. } } if (new_lift > max_lift) // Spot not found at lift or higher? { // Look downwards. new_lift = get_highest_blocked(lift, tflags) + 1; if (new_lift >= lift) // Couldn't drop? return 1; int new_high = get_lowest_blocked(new_lift, tflags); if (new_high != -1 && new_high < new_lift + height) return 1; // Still blocked above. } if (new_lift <= lift) // Not going up? See if falling. { new_lift = (move_flags & MOVE_NODROP) ? lift : get_highest_blocked(lift, tflags) + 1; // Don't allow fall of > max_drop. if (lift - new_lift > max_drop) { // Map-editing? Suspend in air there. if (move_flags & MOVE_MAPEDIT) new_lift = lift - max_drop; else return 1; } int new_high = get_lowest_blocked (new_lift, tflags); // Make sure that where we want to go is tall enough for us if (new_high != -1 && new_high < (new_lift + height)) return 1; } // Found a new place to go, lets test if we can actually move there // Lift 0 tests if (new_lift == 0) { if (move_flags & MOVE_MAPEDIT) return 0; // Map-editor, so anything is okay. int ter = 0; Check_terrain (obj_list, tx, ty, ter); if (ter & 2) // Water { if (move_flags & (MOVE_FLY+MOVE_SWIM)) return 0; else return 1; } else if (ter & 1) // Land { if (move_flags & (MOVE_FLY|MOVE_WALK)) return 0; else return 1; } else if (ter & 4) // Blocked { if (move_flags & MOVE_FLY) return 0; else return 1; } else // Other return 0; } else if (move_flags & (MOVE_FLY|MOVE_WALK)) return 0; return 1; } /* * Activate nearby eggs. */ void Chunk_cache::activate_eggs ( Game_object *obj, // Object (actor) that's near. Map_chunk *chunk, // Chunk this is attached to. int tx, int ty, int tz, // Tile (absolute). int from_tx, int from_ty, // Tile walked from. unsigned short eggbits, // Eggs[tile]. bool now // Do them immediately. ) { int i; // Go through eggs. for (i = 0; i < 8*(int)sizeof(eggbits) - 1 && eggbits; i++, eggbits = eggbits >> 1) { Egg_object *egg; if ((eggbits&1) && i < egg_objects.size() && (egg = egg_objects[i]) && egg->is_active(obj, tx, ty, tz, from_tx, from_ty)) { egg->activate(obj, now); if (chunk->get_cache() != this) return; // A teleport could have deleted us! } } if (eggbits) // Check 15th bit. { // DON'T use an iterator here, since // the list can change as eggs are // activated, causing a CRASH! int sz = egg_objects.size(); for ( ; i < sz; i++) { Egg_object *egg = egg_objects[i]; if (egg && egg->is_active(obj, tx, ty, tz, from_tx, from_ty)) { egg->activate(obj, now); if (chunk->get_cache() != this) return; // A teleport could have deleted us! } } } } /* * Find door blocking a given tile. */ Game_object *Chunk_cache::find_door ( Tile_coord tile ) { for (Game_object_vector::iterator it = doors.begin(); it != doors.end(); ++it) if ((*it)->blocks(tile)) return *it; // Found it. return 0; } /* * Create list for a given chunk. */ Map_chunk::Map_chunk ( int chunkx, int chunky // Absolute chunk coords. ) : objects(0), terrain(0), first_nonflat(0), ice_dungeon(0x00), dungeon_levels(0), cache(0), roof(0), dungeon_lights(0), non_dungeon_lights(0), cx(chunkx), cy(chunky), from_below(0), from_right(0), from_below_right(0) { } /* * Delete all objects contained within. */ Map_chunk::~Map_chunk ( ) { delete cache; delete [] dungeon_levels; } /* * Set terrain. Even if the terrain is the same, it still reloads the * 'flat' objects. */ void Map_chunk::set_terrain ( Chunk_terrain *ter ) { if (terrain) { terrain->remove_client(); // Remove objs. from terrain. Game_object_vector removes; { // Separate scope for Object_iterator. Object_iterator it(get_objects()); Game_object *each; while ((each = it.get_next()) != 0) // Kind of nasty, I know: if (each->as_terrain()) removes.push_back(each); } for (Game_object_vector::const_iterator it=removes.begin(); it!=removes.end(); ++it) (*it)->remove_this(); } terrain = ter; terrain->add_client(); // Get RLE objects in chunk. for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) { ShapeID id = ter->get_flat(tilex, tiley); Shape_frame *shape = id.get_shape(); if (shape && shape->is_rle()) { int shapenum = id.get_shapenum(), framenum = id.get_framenum(); Shape_info& info = id.get_info(); Game_object *obj = info.is_animated() ? new Animated_object(shapenum, framenum, tilex, tiley) : new Terrain_game_object(shapenum, framenum, tilex, tiley); add(obj); } } } /* * Add rendering dependencies for a new object. */ void Map_chunk::add_dependencies ( Game_object *newobj, // Object to add. Ordering_info& newinfo // Info. for new object's ordering. ) { Game_object *obj; // Figure dependencies. Nonflat_object_iterator next(this); while ((obj = next.get_next()) != 0) { //cout << "Here " << __LINE__ << " " << obj << endl; /* Compare returns -1 if lt, 0 if dont_care, 1 if gt. */ int newcmp = Game_object::compare(newinfo, obj); int cmp = newcmp == -1 ? 1 : newcmp == 1 ? 0 : -1; if (!cmp) // Bigger than this object? { newobj->dependencies.put(obj); obj->dependors.put(newobj); } else if (cmp == 1) // Smaller than? { obj->dependencies.put(newobj); newobj->dependors.put(obj); } } } /* * Add rendering dependencies for a new object to another chunk. * NOTE: This is static. * * Output: ->chunk that was checked. */ inline Map_chunk *Map_chunk::add_outside_dependencies ( int cx, int cy, // Chunk to check. Game_object *newobj, // Object to add. Ordering_info& newinfo // Info. for new object's ordering. ) { Map_chunk *chunk = gmap->get_chunk(cx, cy); chunk->add_dependencies(newobj, newinfo); return chunk; } /* * Add a game object to a chunk's list. * * Newobj's cx and cy fields are set to this chunk. */ void Map_chunk::add ( Game_object *newobj // Object to add. ) { newobj->cx = get_cx(); // Set object's chunk. newobj->cy = get_cy(); Ordering_info ord(gwin, newobj); // Put past flats. if (first_nonflat) objects.insert_before(newobj, first_nonflat); else objects.append(newobj); // Not flat? if (newobj->get_lift() || ord.info.get_3d_height()) { // Deal with dependencies. int ty = newobj->get_ty(); // First this chunk. add_dependencies(newobj, ord); if (from_below) // Overlaps from below? add_outside_dependencies(cx, INCR_CHUNK(cy), newobj, ord); if (from_right) // Overlaps from right? add_outside_dependencies(INCR_CHUNK(cx), cy, newobj, ord); if (from_below_right) add_outside_dependencies(INCR_CHUNK(cx), INCR_CHUNK(cy), newobj, ord); // See if newobj extends outside. /* Let's try boundary. YES. This helps with statues through roofs!*/ bool ext_left = (newobj->get_tx() - ord.xs) < 0 && cx > 0; bool ext_above = (newobj->get_ty() - ord.ys) < 0 && cy > 0; if (ext_left) { add_outside_dependencies(DECR_CHUNK(cx), cy, newobj, ord)->from_right++; if (ext_above) add_outside_dependencies(DECR_CHUNK(cx), DECR_CHUNK(cy), newobj, ord)->from_below_right++; } if (ext_above) add_outside_dependencies(cx, DECR_CHUNK(cy), newobj, ord)->from_below++; first_nonflat = newobj; // Inserted before old first_nonflat. } if (cache) // Add to cache. cache->update_object(this, newobj, 1); if (ord.info.is_light_source()) // Count light sources. if (dungeon_levels && is_dungeon(newobj->get_tx(), newobj->get_ty())) dungeon_lights++; else non_dungeon_lights++; if (newobj->get_lift() >= 5) // Looks like a roof? { if (ord.info.get_shape_class() == Shape_info::building) roof = 1; } } /* * Add an egg. */ void Map_chunk::add_egg ( Egg_object *egg ) { add(egg); // Add it normally. egg->set_area(); // Messed up Moonshade after Banes if (cache) // Add to cache. need_cache()->update_egg(this, egg, 1); } /* * Remove an egg. */ void Map_chunk::remove_egg ( Egg_object *egg ) { remove(egg); // Remove it normally. if (cache) // Remove from cache. cache->update_egg(this, egg, 0); } /* * Remove a game object from this list. The object's cx and cy fields * are set to invalid #'s (255,255). */ void Map_chunk::remove ( Game_object *remove ) { if (cache) // Remove from cache. cache->update_object(this, remove, 0); remove->clear_dependencies(); // Remove all dependencies. Game_map *gmap = gwin->get_map(); Shape_info& info = remove->get_info(); // See if it extends outside. int frame = remove->get_framenum(), tx = remove->get_tx(), ty = remove->get_ty(); /* Let's try boundary. YES. Helps with statues through roofs. */ bool ext_left = (tx - info.get_3d_xtiles(frame)) < 0 && cx > 0; bool ext_above = (ty - info.get_3d_ytiles(frame)) < 0 && cy > 0; if (ext_left) { gmap->get_chunk(cx - 1, cy)->from_below_right--; if (ext_above) gmap->get_chunk(cx - 1, cy - 1)->from_below_right--; } if (ext_above) gmap->get_chunk(cx, cy - 1)->from_below--; if (info.is_light_source()) // Count light sources. if (dungeon_levels && is_dungeon(tx, ty)) dungeon_lights--; else non_dungeon_lights--; if (remove == first_nonflat) // First nonflat? { // Update. first_nonflat = remove->get_next(); if (first_nonflat == objects.get_first()) first_nonflat = 0; } objects.remove(remove); // Remove from list. remove->set_invalid(); // No longer part of world. } /* * Is a given rectangle of tiles blocked at a given lift? * * Output: 1 if so, else 0. * If 0 (tile is free), new_lift contains the new height that * an actor will be at if he walks onto the tile. */ int Map_chunk::is_blocked ( int height, // Height (along lift) to check. int lift, // Starting lift. int startx, int starty, // Starting tile coords. int xtiles, int ytiles, // Width, height in tiles. int& new_lift, // New lift returned. const int move_flags, int max_drop, // Max. drop/rise allowed. int max_rise // Max. rise, or -1 to use old beha- // viour (max_drop if FLY, else 1). ) { Game_map *gmap = gwin->get_map(); int tx, ty; new_lift = 0; startx %= c_num_tiles; // Watch for wrapping. starty %= c_num_tiles; int stopy = (starty + ytiles)%c_num_tiles, stopx = (startx + xtiles)%c_num_tiles; for (ty = starty; ty != stopy; ty = INCR_TILE(ty)) { // Get y chunk, tile-in-chunk. int cy = ty/c_tiles_per_chunk, rty = ty%c_tiles_per_chunk; for (tx = startx; tx != stopx; tx = INCR_TILE(tx)) { int this_lift; Map_chunk *olist = gmap->get_chunk( tx/c_tiles_per_chunk, cy); olist->setup_cache(); if (olist->is_blocked(height, lift, tx%c_tiles_per_chunk, rty, this_lift, move_flags, max_drop,max_rise)) return (1); // Take highest one. new_lift = this_lift > new_lift ? this_lift : new_lift; } } return (0); } /* * Check an absolute tile position. * * Output: 1 if blocked, 0 otherwise. * Tile.tz may be updated for stepping onto square. */ int Map_chunk::is_blocked ( Tile_coord& tile, int height, // Height in tiles to check. const int move_flags, int max_drop, // Max. drop/rise allowed. int max_rise // Max. rise, or -1 to use old beha- // viour (max_drop if FLY, else 1). ) { // Get chunk tile is in. Game_map *gmap = gwin->get_map(); Map_chunk *chunk = gmap->get_chunk_safely( tile.tx/c_tiles_per_chunk, tile.ty/c_tiles_per_chunk); if (!chunk) // Outside the world? return 0; // Then it's not blocked. chunk->setup_cache(); // Be sure cache is present. int new_lift; // Check it within chunk. if (chunk->is_blocked(height, tile.tz, tile.tx%c_tiles_per_chunk, tile.ty%c_tiles_per_chunk, new_lift, move_flags, max_drop, max_rise)) return (1); tile.tz = new_lift; return (0); } /* * This one is used to see if an object of dims. possibly > 1X1 can * step onto an adjacent square. */ int Map_chunk::is_blocked ( // Object dims: int xtiles, int ytiles, int ztiles, Tile_coord from, // Stepping from here. Tile_coord& to, // Stepping to here. Tz updated. const int move_flags, int max_drop, // Max drop/rise allowed. int max_rise // Max. rise, or -1 to use old beha- // viour (max_drop if FLY, else 1). ) { int vertx0, vertx1; // Get x-coords. of vert. block // to right/left. int horizx0, horizx1; // Get x-coords of horiz. block // above/below. int verty0, verty1; // Get y-coords of horiz. block // above/below. int horizy0, horizy1; // Get y-coords of vert. block // to right/left. // !Watch for wrapping. horizx0 = (to.tx + 1 - xtiles + c_num_tiles)%c_num_tiles; horizx1 = INCR_TILE(to.tx); if (Tile_coord::gte(to.tx, from.tx)) // Moving right? { // Start to right of hot spot. vertx0 = INCR_TILE(from.tx); vertx1 = INCR_TILE(to.tx); // Stop past dest. } else // Moving left? { vertx0 = (to.tx + 1 - xtiles + c_num_tiles)%c_num_tiles; vertx1 = (from.tx + 1 - xtiles + c_num_tiles)%c_num_tiles; } verty0 = (to.ty + 1 - ytiles + c_num_tiles)%c_num_tiles; verty1 = INCR_TILE(to.ty); if (Tile_coord::gte(to.ty, from.ty)) // Moving down? { // Start below hot spot. horizy0 = INCR_TILE(from.ty); horizy1 = INCR_TILE(to.ty); // End past dest. if (to.ty != from.ty) // Includes bottom of vert. area. verty1 = DECR_TILE(verty1); } else // Moving up? { horizy0 = (to.ty + 1 - ytiles + c_num_tiles)%c_num_tiles; horizy1 = (from.ty + 1 - ytiles + c_num_tiles)%c_num_tiles; // Includes top of vert. area. verty0 = INCR_TILE(verty0); } int x, y; // Go through horiz. part. int new_lift = from.tz; int new_lift0 = -1; // All lift changes must be same. #ifdef DEBUG assert(Tile_coord::gte(horizy1, horizy0)); assert(Tile_coord::gte(horizx1, horizx0)); assert(Tile_coord::gte(verty1, verty0)); assert(Tile_coord::gte(vertx1, vertx0)); #endif for (y = horizy0; y != horizy1; y = INCR_TILE(y)) { // Get y chunk, tile-in-chunk. int cy = y/c_tiles_per_chunk, rty = y%c_tiles_per_chunk; for (x = horizx0; x != horizx1; x = INCR_TILE(x)) { Map_chunk *olist = gmap->get_chunk( x/c_tiles_per_chunk, cy); olist->setup_cache(); int rtx = x%c_tiles_per_chunk; if (olist->is_blocked(ztiles, from.tz, rtx, rty, new_lift, move_flags, max_drop, max_rise)) return 1; if (new_lift != from.tz) if (new_lift0 == -1) new_lift0 = new_lift; else if (new_lift != new_lift0) return (1); } } // Do vert. block. for (x = vertx0; x != vertx1; x = INCR_TILE(x)) { // Get x chunk, tile-in-chunk. int cx = x/c_tiles_per_chunk, rtx = x%c_tiles_per_chunk; for (y = verty0; y != verty1; y = INCR_TILE(y)) { Map_chunk *olist = gmap->get_chunk( cx, y/c_tiles_per_chunk); olist->setup_cache(); int rty = y%c_tiles_per_chunk; if (olist->is_blocked(ztiles, from.tz, rtx, rty, new_lift, move_flags, max_drop, max_rise)) return 1; if (new_lift != from.tz) if (new_lift0 == -1) new_lift0 = new_lift; else if (new_lift != new_lift0) return (1); } } to.tz = new_lift; return (0); // All clear. } /* * Get the list of tiles in a square perimeter around a given tile. * * Output: List (8*dist) of tiles, starting in Northwest corner and going * clockwise. List is on heap. */ static Tile_coord *Get_square ( Tile_coord& pos, // Center of square. int dist // Distance to perimeter (>0) ) { Tile_coord *square = new Tile_coord[8*dist]; // Upper left corner: square[0] = Tile_coord(DECR_TILE(pos.tx, dist), DECR_TILE(pos.ty, dist), pos.tz); int i; // Start with top row. int len = 2*dist + 1; int out = 1; for (i = 1; i < len; i++, out++) square[out] = Tile_coord(INCR_TILE(square[out - 1].tx), square[out - 1].ty, pos.tz); // Down right side. for (i = 1; i < len; i++, out++) square[out] = Tile_coord(square[out - 1].tx, INCR_TILE(square[out - 1].ty), pos.tz); // Bottom, going back to left. for (i = 1; i < len; i++, out++) square[out] = Tile_coord(DECR_TILE(square[out - 1].tx), square[out - 1].ty, pos.tz); // Left side, going up. for (i = 1; i < len - 1; i++, out++) square[out] = Tile_coord(square[out - 1].tx, DECR_TILE(square[out - 1].ty), pos.tz); return square; } /* * Check a spot against the 'where' paramater to find_spot. * * Output: true if it passes. */ inline bool Check_spot ( Map_chunk::Find_spot_where where, int tx, int ty, int tz ) { Game_map *gmap = Game_window::get_instance()->get_map(); int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; Map_chunk *chunk = gmap->get_chunk_safely(cx, cy); return (where == Map_chunk::inside) == (chunk->is_roof(tx % c_tiles_per_chunk, ty % c_tiles_per_chunk, tz) < 31); } /* * Find a free area for an object of a given shape, looking outwards. * * Output: Tile if successful, else (-1, -1, -1). */ Tile_coord Map_chunk::find_spot ( Tile_coord pos, // Starting point. int dist, // Distance to look outwards. (0 means // only check 'pos'. int shapenum, // Shape, frame to find spot for. int framenum, int max_drop, // Allow to drop by this much. int dir, // Preferred direction (0-7), or -1 for // random. Find_spot_where where // Inside/outside. ) { Shape_info& info = ShapeID::get_info(shapenum); int xs = info.get_3d_xtiles(framenum); int ys = info.get_3d_ytiles(framenum); int zs = info.get_3d_height(); // The 'MOVE_FLY' flag really means // we can look upwards by max_drop. const int mflags = MOVE_WALK|MOVE_FLY; int new_lift; // Start with original position. if (!Map_chunk::is_blocked(zs, pos.tz, pos.tx - xs + 1, pos.ty - ys + 1, xs, ys, new_lift, mflags, max_drop)) return Tile_coord(pos.tx, pos.ty, new_lift); if (dir < 0) dir = rand()%8; // Choose dir. randomly. dir = (dir + 1)%8; // Make NW the 0 point. for (int d = 1; d <= dist; d++) // Look outwards. { int square_cnt = 8*d ;// # tiles in square's perim. // Get square (starting in NW). Tile_coord *square = Get_square(pos, d); int index = dir*d; // Get index of preferred spot. // Get start of preferred range. index = (index - d/2 + square_cnt)%square_cnt; for (int cnt = square_cnt; cnt; cnt--, index++) { Tile_coord& p = square[index%square_cnt]; if (!Map_chunk::is_blocked(zs, p.tz, p.tx - xs + 1, p.ty - ys + 1, xs, ys, new_lift, mflags, max_drop) && (where == anywhere || Check_spot(where, p.tx, p.ty, new_lift))) { // Use tile before deleting. Tile_coord ret(p.tx, p.ty, new_lift); delete [] square; return ret; } } delete [] square; } return Tile_coord(-1, -1, -1); } /* * Find a free area for an object (usually an NPC) that we want to * approach a given position. * * Output: Tile if successful, else (-1, -1, -1). */ Tile_coord Map_chunk::find_spot ( Tile_coord pos, // Starting point. int dist, // Distance to look outwards. (0 means // only check 'pos'. Game_object *obj, // Object that we want to move. int max_drop, // Allow to drop by this much. Find_spot_where where // Inside/outside. ) { Tile_coord t2 = obj->get_tile(); // Get direction from pos. to object. int dir = (int) Get_direction(pos.ty - t2.ty, t2.tx - pos.tx); return find_spot(pos, dist, obj->get_shapenum(), obj->get_framenum(), max_drop, dir, where); } /* * Find all desired objects within a given rectangle. * * Output: # found, appended to vec. */ int Map_chunk::find_in_area ( Game_object_vector& vec, // Returned here. Rectangle area, // Area to search. int shapenum, int framenum ) { int savesize = vec.size(); // Go through interesected chunks. Chunk_intersect_iterator next_chunk(area); Rectangle tiles; // (Tiles within intersected chunk). int eachcx, eachcy; Game_map *gmap = gwin->get_map(); while (next_chunk.get_next(tiles, eachcx, eachcy)) { Map_chunk *chunk = gmap->get_chunk_safely(eachcx, eachcy); if (!chunk) continue; Object_iterator next(chunk->objects); Game_object *each; while ((each = next.get_next()) != 0) if (each->get_shapenum() == shapenum && each->get_framenum() == framenum && tiles.has_point(each->get_tx(), each->get_ty())) vec.append(each); } return vec.size() - savesize; } /* * Test all nearby eggs when you've teleported in. */ void Map_chunk::try_all_eggs ( Game_object *obj, // Object (actor) that's near. int tx, int ty, int tz, // Tile (absolute). int from_tx, int from_ty // Tile walked from. ) { static int norecurse = 0; // NO recursion here. if (norecurse) return; norecurse++; Game_map *gmap = gwin->get_map(); Tile_coord pos = obj->get_tile(); const int dist = 32; // See if this works okay. Rectangle area(pos.tx - dist, pos.ty - dist, 2*dist, 2*dist); // Go through interesected chunks. Chunk_intersect_iterator next_chunk(area); Rectangle tiles; // (Ignored). int eachcx, eachcy; Egg_vector eggs(40); // Get them here first, as activating // an egg could affect chunk's list. while (next_chunk.get_next(tiles, eachcx, eachcy)) { Map_chunk *chunk = gmap->get_chunk_safely(eachcx, eachcy); if (!chunk) continue; chunk->setup_cache(); // I think we should do this. Object_iterator next(chunk->objects); Game_object *each; while ((each = next.get_next()) != 0) if (each->is_egg()) { Egg_object *egg = (Egg_object *) each; // Music eggs are causing problems. if (egg->get_type() != Egg_object::jukebox && // And don't teleport a 2nd time. egg->get_type() != Egg_object::teleport && egg->is_active(obj, tx, ty, tz, from_tx, from_ty)) eggs.push_back(egg); } } for (Egg_vector::const_iterator it = eggs.begin(); it != eggs.end(); ++it) (*it)->activate(obj); norecurse--; } /* * Add a rectangle of dungeon tiles (but only if higher!). */ void Map_chunk::add_dungeon_levels ( Rectangle& tiles, unsigned int lift ) { if (!dungeon_levels) { // First one found. dungeon_levels = new unsigned char[256/2]; memset(dungeon_levels, 0, 256/2); } int endy = tiles.y + tiles.h, endx = tiles.x + tiles.w; for (int ty = tiles.y; ty < endy; ty++) { for (int tx = tiles.x; tx < endx; tx++) { int tnum = (ty*c_tiles_per_chunk + tx)/2; if (GAME_SI) // SI has roofs at random levels!! lift = 5; if (tx % 2) { dungeon_levels[tnum] &= 0x0F; dungeon_levels[tnum] |= lift << 4; } else { dungeon_levels[tnum] &= 0xF0; dungeon_levels[tnum] |= lift; } } } } /* * Set up the dungeon levels (after IFIX objects read). */ void Map_chunk::setup_dungeon_levels ( ) { Game_map *gmap = gwin->get_map(); Object_iterator next(objects); Game_object *each; while ((each = next.get_next()) != 0) { int shnum = each->get_shapenum(); // Test for mountain-tops. if (shnum == 983 || shnum == 969 || shnum == 183 || shnum == 182 || shnum == 180 || shnum == 324 || ((shnum == 941 || shnum == 394) && Game::get_game_type() == SERPENT_ISLE)) { // SI shape 941, frame 0 => do whole chunk (I think). Rectangle area = (shnum == 941 && each->get_framenum() == 0) ? Rectangle(cx*c_tiles_per_chunk, cy*c_tiles_per_chunk, c_tiles_per_chunk, c_tiles_per_chunk) : each->get_footprint(); // Go through interesected chunks. Chunk_intersect_iterator next_chunk(area); Rectangle tiles;// Rel. tiles. int cx, cy; while (next_chunk.get_next(tiles, cx, cy)) gmap->get_chunk(cx, cy)->add_dungeon_levels( tiles, each->get_lift()); } // Ice Dungeon Pieces in SI else if (Game::get_game_type() == SERPENT_ISLE && ( shnum == 436 || shnum == 437 || shnum == 444 || shnum == 448 || shnum == 466 || shnum == 477)) { // HACK ALERT! This gets 320x200 to work, but it is a hack // This is not exactly accurate. ice_dungeon |= 1 << ( (each->get_tx()>>3) + 2*(each->get_ty()>>3) ); Rectangle area = each->get_footprint(); // Go through interesected chunks. Chunk_intersect_iterator next_chunk(area); Rectangle tiles;// Rel. tiles. int cx, cy; while (next_chunk.get_next(tiles, cx, cy)) gmap->get_chunk(cx, cy)->add_dungeon_levels( tiles, each->get_lift()); } } if (dungeon_levels) // Recount lights. { dungeon_lights = non_dungeon_lights = 0; next.reset(); while ((each = next.get_next()) != 0) if (each->get_info().is_light_source()) if (is_dungeon(each->get_tx(), each->get_ty())) dungeon_lights++; else non_dungeon_lights++; } } /* * Recursively apply gravity over a given rectangle that is known to be * unblocked below a given lift. */ void Map_chunk::gravity ( Rectangle area, // Unblocked tiles (in abs. coords). int lift // Lift where tiles are free. ) { Game_object_vector dropped(20); // Gets list of objs. that dropped. // Go through interesected chunks. Chunk_intersect_iterator next_chunk(area); Rectangle tiles; // Rel. tiles. Not used. int cx, cy, new_lift; while (next_chunk.get_next(tiles, cx, cy)) { Map_chunk *chunk = gmap->get_chunk(cx, cy); Object_iterator objs(chunk->objects); Game_object *obj; while ((obj = objs.get_next()) != 0) { // We DO want NPC's to fall. if (!obj->is_dragable() && !obj->get_info().is_npc()) continue; Tile_coord t = obj->get_tile(); // Get footprint. Rectangle foot = obj->get_footprint(); // Above area? if (t.tz >= lift && foot.intersects(area) && // Unblocked below itself? !is_blocked(1, t.tz - 1, foot.x, foot.y, foot.w, foot.h, new_lift, MOVE_ALL_TERRAIN, 0) && new_lift < t.tz) dropped.push_back(obj); } } Game_object_vector::const_iterator it; // Drop each one found. for (it = dropped.begin(); it != dropped.end(); ++it) { Game_object *obj = *it; Tile_coord t = obj->get_tile(); // Get footprint. Rectangle foot = obj->get_footprint(); // Let drop as far as possible. if (!is_blocked(1, t.tz - 1, foot.x, foot.y, foot.w, foot.h, new_lift, MOVE_ALL_TERRAIN, 100) && new_lift < t.tz) { // Drop & recurse. obj->move(t.tx, t.ty, new_lift); gravity(foot, obj->get_lift() + obj->get_info().get_3d_height()); } } #if 0 for (it = dropped.begin(); it != dropped.end(); ++it) { // Recurse on each one. Game_object *obj = *it; // Get footprint. Rectangle foot = obj->get_footprint(); gravity(foot, obj->get_lift() + obj->get_info().get_3d_height()); } #endif } /* * Finds if there is a 'roof' above lift in tile (tx, ty) * of the chunk. Point is taken 4 above lift * * Roof can be any object, not just a literal roof * * Output: height of the roof. * A return of 31 means no roof * */ int Map_chunk::is_roof(int tx, int ty, int lift) { #if 1 /* Might be lying on bed at lift==2. */ int height = get_lowest_blocked (lift+4, tx, ty); #else /* But this is even worse! */ int height = get_lowest_blocked (lift+2, tx, ty); #endif if (height == -1) return 31; return height; } void Map_chunk::kill_cache() { // Get rid of terrain if (terrain) terrain->remove_client(); terrain = 0; // Now remove the cachce delete cache; cache = 0; // Delete dungeon bits delete [] dungeon_levels; dungeon_levels = 0; } int Map_chunk::get_obj_actors(Game_object_vector &removes, Actor_vector &actors) { int buf_size = 0; bool failed = false; // Separate scope for Object_iterator. Object_iterator it(get_objects()); Game_object *each; while ((each = it.get_next()) != 0) { Actor *actor = each->as_actor(); // Normal objects and monsters if (actor == 0 || (each->is_monster() && each->get_flag(Obj_flags::is_temporary))) { removes.push_back(each); int ireg_size = each->get_ireg_size(); if (ireg_size < 0) failed = true; else buf_size += ireg_size; } // Actors/NPCs here else { actors.push_back(actor); } } return failed?-1:buf_size; } exult-1.2/objs/iregobjs.cc0000644000175000001440000000627507622647334011271 /** ** Iregobjs.cc - Ireg (moveable) game objects. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "contain.h" #include "gamewin.h" #include "gamemap.h" #include "chunks.h" #include "cheat.h" #include "databuf.h" #include "ucsched.h" #include "Gump_manager.h" using std::ostream; /* * Paint at given spot in world. */ void Ireg_game_object::paint ( ) { int x, y; gwin->get_shape_location(this, x, y); if (flags & (1L << Obj_flags::invisible)) paint_invisible(x, y); else paint_shape(x, y); } /* * Move to a new absolute location. This should work even if the old * location is invalid (cx=cy=255). */ void Ireg_game_object::move ( int newtx, int newty, int newlift ) { if (owner) // Watch for this. { owner->remove(this); set_invalid(); // So we can safely move it back. } Game_object::move(newtx, newty, newlift); } /* * Remove an object from its container, or from the world. * The object is deleted. */ void Ireg_game_object::remove_this ( int nodel // 1 to not delete. ) { if (owner) // In a bag, box, or person. owner->remove(this); else // In the outside world. { Map_chunk *chunk = gmap->get_chunk_safely(cx, cy); if (chunk) chunk->remove(this); } if (!nodel) { cheat.clear_this_grabbed_actor((Actor*)this); // Could be an actor gwin->delete_object(this); } } /* * Can this be dragged? */ int Ireg_game_object::is_dragable ( ) const { // 0 weight means 'too heavy'. return get_info().get_weight() > 0; } /* * Write out. */ void Ireg_game_object::write_ireg ( DataSource *out ) { unsigned char buf[11]; // 10-byte entry + length-byte. buf[0] = 10; write_common_ireg(&buf[1]); buf[5] = (get_lift()&15)<<4; buf[6] = get_quality(); Shape_info& info = get_info(); if (info.has_quality_flags()) { // Store 'quality_flags'. buf[6] = get_flag((Obj_flags::invisible) != 0) + ((get_flag(Obj_flags::okay_to_take) != 0) << 3); } // Special case for 'quantity' items: else if (get_flag(Obj_flags::okay_to_take) && info.has_quantity()) buf[6] |= 0x80; buf[7] = (get_flag(Obj_flags::is_temporary) != 0); out->write((char*)buf, sizeof(buf)); // Write scheduled usecode. Game_map::write_scheduled(out, this); } // Get size of IREG. Returns -1 if can't write to buffer int Ireg_game_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gumpman->find_gump(this) || Usecode_script::find(this)) return -1; return 11; } exult-1.2/objs/jawbone.cc0000644000175000001440000000361407470135447011102 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "jawbone.h" #include "objiter.h" // Add an object. bool Jawbone_object::add(Game_object *obj, bool dont_check, bool combine) { if (obj->get_shapenum() != 559) return false; // not a serpent tooth find_teeth(); if (teeth[obj->get_framenum()]) return false; // already have this one if (Container_game_object::add(obj, dont_check)) { teeth[obj->get_framenum()] = obj; toothcount++; update_frame(); return true; } return false; } // Remove an object. void Jawbone_object::remove(Game_object *obj) { Container_game_object::remove(obj); find_teeth(); update_frame(); } void Jawbone_object::find_teeth() { for (int i=0; i<19; i++) teeth[i] = 0; toothcount = 0; Object_list& objects = get_objects(); if (objects.is_empty()) return; // Empty. Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { if (obj->get_shapenum() != 559) { // obj = obj->get_next(); continue; // not a serpent tooth... (shouldn't happen) } toothcount++; teeth[obj->get_framenum()] = obj; // obj = obj->get_next(); } } void Jawbone_object::update_frame() { set_frame(toothcount); } exult-1.2/objs/objiter.cc0000644000175000001440000000430310026506347011077 /** ** Objiter.h - Game objects iterator. ** ** Written: 5/27/2002 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "objiter.h" #include "contain.h" #include "gamewin.h" #include "chunks.h" /* * Create to start after/before a given object within a chunk. */ template D_Recursive_object_iterator::D_Recursive_object_iterator ( Game_object *start // Start here. ) : elems(start->get_outermost()->get_chunk()->get_objects()), child(0) { // Get what obj. is in (or itself). Game_object *owner = start->get_outermost(); Game_object *obj; // Find owner within its chunk. while ((obj = get_next()) != 0 && obj != owner) ; if (!obj) return; // Bad. It wasn't found. if (obj != start) // Given object contained? // Look within for it. while ((obj = get_next()) != 0 && obj != start) ; } /* * Get next game object, going down recursively into containers. * * Output: Next in world, or 0 if done. */ template Game_object *D_Recursive_object_iterator::get_next ( ) { Game_object *obj; if (child) // Going through container? { obj = child->get_next(); if (obj) return obj; delete child; child = 0; // Child done. } obj = elems.get_next(); // Get next from our list. if (!obj) return 0; // All done. // Is it a container? Container_game_object *c = obj->as_container(); if (c) // Container? Set to go through it. child = new D_Recursive_object_iterator( c->get_objects()); return obj; } exult-1.2/objs/chunkter.cc0000644000175000001440000001661510040666551011275 /** ** Chunkter.cc - Chunk terrain (16x16 flat tiles) on the map. ** ** Written: 7/6/01 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "chunkter.h" #include "gamewin.h" #ifdef INCL_OPENGL #include "glshape.h" #endif Chunk_terrain *Chunk_terrain::render_queue = 0; int Chunk_terrain::queue_size = 0; /* * Insert at start of render queue. It may already be there, but it's * assumed that it's already tested as not being at the start. */ void Chunk_terrain::insert_in_queue ( ) { if (render_queue_next) // In queue already? { // !!Assuming it's not at head!! render_queue_next->render_queue_prev = render_queue_prev; render_queue_prev->render_queue_next = render_queue_next; } else queue_size++; // Adding, so increment count. if (!render_queue) // First? render_queue_next = render_queue_prev = this; else { render_queue_next = render_queue; render_queue_prev = render_queue->render_queue_prev; render_queue_prev->render_queue_next = this; render_queue->render_queue_prev = this; } render_queue = this; } /* * Remove from render queue. */ void Chunk_terrain::remove_from_queue ( ) { if (!render_queue_next) return; // Not in queue. queue_size--; if (render_queue_next == this) // Only element? render_queue = 0; else { if (render_queue == this) render_queue = render_queue_next; render_queue_next->render_queue_prev = render_queue_prev; render_queue_prev->render_queue_next = render_queue_next; } render_queue_next = render_queue_prev = 0; } /* * Paint a flat tile into our cached buffer. */ inline void Chunk_terrain::paint_tile ( int tilex, int tiley // Tile within chunk. ) { Shape_frame *shape = get_shape(tilex, tiley); if (shape && !shape->is_rle()) // Only do flat tiles. rendered_flats->copy8(shape->get_data(), c_tilesize, c_tilesize, tilex*c_tilesize, tiley*c_tilesize); } /* * Create list for a given chunk. */ Chunk_terrain::Chunk_terrain ( unsigned char *data // Chunk data. ) : undo_shapes(0), rendered_flats(0), glflats(0), num_clients(0), render_queue_next(0), render_queue_prev(0), modified(false) { for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) { ShapeID id(data[0], (unsigned char) (data[1]&0x7f)); shapes[16*tiley + tilex] = id; data += 2; } } /* * Copy another. The 'modified' flag is set to true. */ Chunk_terrain::Chunk_terrain ( const Chunk_terrain& c2 ) : undo_shapes(0), rendered_flats(0), glflats(0), num_clients(0), render_queue_next(0), render_queue_prev(0), modified(true) { for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) shapes[16*tiley + tilex] = c2.shapes[16*tiley + tilex]; } /* * Clean up. */ Chunk_terrain::~Chunk_terrain ( ) { delete [] undo_shapes; delete rendered_flats; #ifdef HAVE_OPENGL delete glflats; #endif remove_from_queue(); } /* * Set tile's shape. * NOTE: Set's 'modified' flag. */ void Chunk_terrain::set_flat ( int tilex, int tiley, ShapeID id ) { if (!undo_shapes) // Create backup. { undo_shapes = new ShapeID[256]; std::memcpy((char *) undo_shapes, (char *) &shapes[0], sizeof(shapes)); } shapes[16*tiley + tilex] = id; modified = true; } /* * Commit changes. * * Output: True if this was edited, else false. */ bool Chunk_terrain::commit_edits ( ) { if (!undo_shapes) return false; delete [] undo_shapes; undo_shapes = 0; render_flats(); // Update with new data. return true; } /* * Undo changes. Note: We don't clear 'modified', since this could * still have been moved to a different position. */ void Chunk_terrain::abort_edits ( ) { if (undo_shapes) { std::memcpy((char *) &shapes[0], (char *) undo_shapes, sizeof(shapes)); delete [] undo_shapes; undo_shapes = 0; } } /* * Figure max. queue size for given game window. */ static int Figure_queue_size ( ) { Game_window *gwin = Game_window::get_instance(); int w = gwin->get_width(), h = gwin->get_height(); // Figure # chunks, rounding up. int cw = (w + c_chunksize - 1)/c_chunksize, ch = (h + c_chunksize - 1)/c_chunksize; // Add extra in each dir. return 6;//(cw + 3)*(ch + 3); } /* * Create rendered_flats buffer. */ Image_buffer8 *Chunk_terrain::render_flats ( ) { if (!rendered_flats) { if (queue_size > Figure_queue_size()) { // Grown too big. Remove last. Chunk_terrain *last = render_queue->render_queue_prev; last->free_rendered_flats(); render_queue->render_queue_prev = last->render_queue_prev; last->render_queue_prev->render_queue_next = render_queue; last->render_queue_next = last->render_queue_prev = 0; queue_size--; } rendered_flats = new Image_buffer8(c_chunksize, c_chunksize); } // Go through array of tiles. for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) paint_tile(tilex, tiley); #ifdef HAVE_OPENGL delete glflats; glflats = 0; GL_manager *glman = GL_manager::get_instance(); if (glman) // Using OpenGL? glflats = glman->create(rendered_flats); #endif return rendered_flats; } /* * Free pre-rendered landscape. */ void Chunk_terrain::free_rendered_flats ( ) { delete rendered_flats; rendered_flats = 0; #ifdef HAVE_OPENGL delete glflats; glflats = 0; #endif } /* * This method is only used in 'terrain-editor' mode, NOT in normal * gameplay. */ void Chunk_terrain::render_all ( int cx, int cy // Chunk rendering too. ) { Image_window8 *iwin = gwin->get_win(); int ctx = cx*c_tiles_per_chunk, cty = cy*c_tiles_per_chunk; int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty(); // Go through array of tiles. for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) { Shape_frame *shape = get_shape(tilex, tiley); if (!shape) continue; if (!shape->is_rle()) iwin->copy8(shape->get_data(), c_tilesize, c_tilesize, (ctx + tilex - scrolltx)*c_tilesize, (cty + tiley - scrollty)*c_tilesize); else // RLE. { int x, y; Tile_coord tile(ctx + tilex, cty + tiley, 0); gwin->get_shape_location(tile, x, y); sman->paint_shape(x, y, shape); } } } /* * Write out to a chunk. */ void Chunk_terrain::write_flats ( unsigned char *chunk_data ) { for (int ty = 0; ty < c_tiles_per_chunk; ty++) for (int tx = 0; tx < c_tiles_per_chunk; tx++) { ShapeID id = get_flat(tx, ty); int shapenum = id.get_shapenum(), framenum = id.get_framenum(); *chunk_data++ = shapenum&0xff; *chunk_data++ = ((shapenum>>8)&3) | (framenum<<2); } } exult-1.2/objs/animate.cc0000644000175000001440000003517510054030565011065 /** ** Animate.cc - Animated game objects. ** ** Written: 7/27/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "animate.h" #include "gamewin.h" #include "game.h" #include "gameclk.h" #include "Audio.h" #include "actors.h" /* Only need this for Object_sfx. */ #include "dir.h" #include "Flex.h" #include #include #ifndef UNDER_CE using std::map; using std::ostream; using std::rand; using std::endl; using std::cout; #endif /* * A class for playing sound effects when certain objects are nearby. */ class Object_sfx : public Game_singletons { int sfxnum; // Sound effect #. int sfx; // ID of sound effect being played. Game_object *obj; // Object that caused the sound. int distance; // Distance in tiles from Avatar. int dir; // Direction (0-15) from Avatar. public: // Create & start playing sound. Object_sfx(int snum, Game_object *o) : sfxnum(snum), distance(0), sfx(-1) { set_obj(o); } // bool is_active() // Is sound still active? // { return sfx.is_active(); } int get_sfxnum() { return sfxnum; } int get_distance() { return distance; } void set_obj(Game_object *o); // Set to new object. void stop(Game_object *o) // Stop if from given object. { if (o == obj) if(sfx >= 0) { Mix_HaltChannel(sfx); sfx = -1; } } // Get sfx to play for given shape. static int get_shape_sfx(int shapenum); static void play(Game_object *o, int snum, bool stop = false); }; /* * Set to new object if it's closer than the old object, or we're * inactive. */ void Object_sfx::set_obj ( Game_object *o ) { Tile_coord apos = gwin->get_main_actor()->get_tile(); Tile_coord opos = o->get_tile(); int active = 0; if(sfx != -1) active = Mix_Playing(sfx); int new_distance = apos.distance(opos); if (active && new_distance >= distance && o != obj) return; // Farther than current source. obj = o; dir = 0; bool repeat = true; distance = new_distance; int volume = MIX_MAX_VOLUME; // Set volume based on distance. if (distance) { // 160/8 = 20 tiles. 20*20=400. volume = (MIX_MAX_VOLUME*64)/(distance*distance); if (!volume) // Dead? repeat = false; // Time to kill it. if (volume < 8) volume = 8; else if (volume > MIX_MAX_VOLUME) volume = MIX_MAX_VOLUME; dir = Get_direction16(apos.ty - opos.ty, opos.tx - apos.tx); } if (sfx == -1) // First time? { // Start playing, and repeat. sfx = Audio::get_ptr()->play_sound_effect(sfxnum, MIX_MAX_VOLUME, dir, -1); if(sfx >= 0) Mix_Volume(sfx, volume); } else // Set new volume, position. { //Just change the "location" of the sound if(!repeat) { Mix_HaltChannel(sfx); sfx = -1; } else { Mix_Volume(sfx, volume); Mix_SetPosition(sfx, (dir * 22), 0); } } } /* * Get the sound-effect # for a given shape, or -1 if not found. */ int Object_sfx::get_shape_sfx ( int shapenum ) { static map table; static int first = 1; if (first) // First time? { first = 0; // Surf: (47 or 49) table[612] = 49; table[613] = 49; table[632] = 49; table[736] = 49; table[737] = 49; table[751] = 49; table[808] = 49; table[834] = 49; table[875] = 49; table[907] = 49; table[911] = 49; table[918] = 49; table[1012] = 49; table[1020] = 49; table[1022] = 49; // Bubbles: (54, 56). table[334] = 56; table[335] = 56; table[780] = 56; // Fountains: table[893] = 36; // Moongates: table[776] = 77; table[777] = 77; if (GAME_BG) { table[305] = 78; // Black gate. table[786] = 79; // Vortex cube. } // Grandfather clock tick tock, only in the SQSFX files, if (Audio::get_ptr()->get_sfx_file() != 0) { std::string s = Audio::get_ptr()->get_sfx_file()->filename; to_uppercase(s); if(s.find("SQSFX") != std::string::npos) { table[252] = 116; // Grandfather clock table[695] = 116; // Grandfather clock } } } std::map::iterator it = table.find(shapenum); if (it == table.end()) return -1; int sfx = (*it).second; return Audio::game_sfx(sfx); return sfx; } /* * Play a sound, or modify its volume/position. */ void Object_sfx::play ( Game_object *o, // Object. int snum, // Object's sound-effect #. bool stop // Time to stop. ) { // Play a given sfx only once. static map play_table; // Already playing? std::map::iterator it = play_table.find(snum); if (it == play_table.end()) // No. { // Start new SFX for it. if (!stop) play_table[snum] = new Object_sfx(snum, o); return; } Object_sfx *sfx = (*it).second; if (stop) { sfx->stop(o); } else sfx->set_obj(o); // Modify/restart. } /* * Create appropriate animator. */ Animator *Animator::create ( Game_object *ob // Animated object. ) { int shnum = ob->get_shapenum(); int frames = ob->get_num_frames(); Shape_info& info = ob->get_info(); if (!info.is_animated()) // Assume it's just SFX. return new Sfx_animator(ob); else if (frames > 1) return new Frame_animator(ob); else return new Wiggle_animator(ob); } /* * When we delete, better remove from queue. */ Animator::~Animator ( ) { while (gwin->get_tqueue()->remove(this)) ; } /* * Start animation. */ void Animator::start_animation ( ) { // Clean out old entry if there. gwin->get_tqueue()->remove(this); gwin->get_tqueue()->add(Game::get_ticks() + 20, this, (long) gwin); animating = 1; } /* * Retrieve current frame */ int Animator::get_framenum() { return obj->get_framenum(); } /* * Create a frame animator. */ Frame_animator::Frame_animator ( Game_object *o ) : Animator(o, Object_sfx::get_shape_sfx(o->get_shapenum())) { Initialize(); } /* * Initialize a frame animator. */ void Frame_animator::Initialize() { first_frame = 0; created = 0; delay = 100; type = FA_LOOPING; last_shape = obj->get_shapenum(); last_frame = obj->get_framenum(); frames = obj->get_num_frames(); // Serpent Isle if (Game::get_game_type() == SERPENT_ISLE) { switch (last_shape) { case 284: // Sundial is a special case. type = FA_SUNDIAL; break; case 768: // Energy field. Stop at top. type = FA_ENERGY_FIELD; created = Game::get_ticks(); first_frame = last_frame; break; case 153: // Fountain case 184: // Lava case 222: // Pennant case 289: // Fire case 305: // Serpent Statue case 326: // Fountain case 456: // Flux Analyzer case 614: // Magic music box case 655: // Planets case 695: // Grandfather clock case 726: // Pulsating Object case 743: // Statue?? case 794: // Severed limb case 992: // Burning urn first_frame = 6*(last_frame/6); frames = 6; created = last_frame%6; break; case 779: // Magic Wave. first_frame = 6*(last_frame/6); frames = 6; if (last_frame < 6) created = 1; else created = 0; break; case 335: // Bubbles created = last_frame; if (last_frame < 6) { first_frame = 0; frames = 6; } else { first_frame = 6; frames = frames-6; } break; case 322: // Basin case 714: // Basin created = last_frame; if (last_frame != frames-1) { first_frame = 0; frames = frames - 1; } else { first_frame = frames -1; frames = 1; } break; default: break; } } // Black Gate else { switch (last_shape) { case 284: // Sundial is a special case. type = FA_SUNDIAL; break; case 768: // Energy field. Stop at top. type = FA_ENERGY_FIELD; created = Game::get_ticks(); first_frame = last_frame; break; // First frame isn't animated case 862: // Shafts case 880: case 933: // Millsaw if (last_frame == 0) { first_frame = 0; frames = 1; } else { frames = frames -1; first_frame = 1; } break; default: break; } } } /* * Retrieve current frame */ int Frame_animator::get_framenum() { unsigned int ticks = Game::get_ticks(); int framenum = 0; if (last_shape != obj->get_shapenum() || last_frame != obj->get_framenum()) Initialize(); bool dirty_first = gwin->add_dirty(obj); if (last_shape != obj->get_shapenum() || last_frame != obj->get_framenum()) Initialize(); switch (type) { case FA_SUNDIAL: framenum = gclock->get_hour() % frames; break; case FA_ENERGY_FIELD: framenum = (ticks - created) / delay + first_frame; if (framenum >= frames) framenum = frames-1; break; case FA_LOOPING: framenum = (ticks / delay) + created; framenum %= frames; framenum += first_frame; break; } return framenum; } /* * Animation. */ void Frame_animator::handle_event ( unsigned long curtime, // Current time of day. long udata // Game window. ) { unsigned int ticks = Game::get_ticks(); Game_window *gwin = (Game_window *) udata; bool dirty_first = gwin->add_dirty(obj); int framenum = get_framenum(); obj->set_frame(last_frame = framenum); if (!dirty_first && !gwin->add_dirty(obj)) { // No longer on screen. animating = 0; // Stop playing sound. Object_sfx::play(obj, sfxnum, true); return; } if (!framenum && sfxnum >= 0) // Sound effect? Object_sfx::play(obj, sfxnum); // Add back to queue for next time. if (animating) { // Ensure all animations are synced gwin->get_tqueue()->add(ticks + delay- (ticks%delay), this, udata); } } /* * Create a pure SFX player. */ Sfx_animator::Sfx_animator ( Game_object *o ) : Animator(o, Object_sfx::get_shape_sfx(o->get_shapenum())) { } /* * Play SFX. */ void Sfx_animator::handle_event ( unsigned long curtime, // Current time of day. long udata // Game window. ) { const int delay = 200; // Guessing this will be enough. unsigned int ticks = Game::get_ticks(); Game_window *gwin = (Game_window *) udata; Rectangle rect = gwin->clip_to_win(gwin->get_shape_rect(obj)); if (rect.w <= 0 || rect.h <= 0) { // No longer on screen. animating = 0; // Stop playing sound. Object_sfx::play(obj, sfxnum, true); return; } if (sfxnum >= 0) // Sound effect? Object_sfx::play(obj, sfxnum); // Add back to queue for next time. if (animating) // Ensure all animations are synced gwin->get_tqueue()->add(ticks + delay- (ticks%delay), this, udata); } /* * Create a field frame animator. */ Field_frame_animator::Field_frame_animator ( Game_object *o, int rcy // Frame to start recycling at. ) : Animator(o), recycle(rcy), activated(true) { int shapenum = obj->get_shapenum(); frames = obj->get_num_frames(); } /* * Animation. */ void Field_frame_animator::handle_event ( unsigned long curtime, // Current time of day. long udata // Game window. ) { int delay = 100; // Delay between frames. Game_window *gwin = (Game_window *) udata; if (!gwin->add_dirty(obj)) { // No longer on screen. animating = 0; return; } int framenum = obj->get_framenum() + 1; if (framenum == frames) framenum = recycle; // Restart cycle here. obj->set_frame(framenum); gwin->add_dirty(obj); // Add back to queue for next time. if (animating) gwin->get_tqueue()->add(curtime + delay, this, udata); if (activated && rand()%10 == 0)// Check for damage? obj->activate(0); } /* * Animation. */ void Wiggle_animator::handle_event ( unsigned long curtime, // Current time of day. long udata // Game window. ) { int delay = 100; // Delay between frames. Game_window *gwin = (Game_window *) udata; if (!gwin->add_dirty(obj)) { // No longer on screen. animating = 0; return; } Tile_coord t = obj->get_tile(); // Get current position. int newdx = rand()%3; int newdy = rand()%3; t.tx += -deltax + newdx; t.ty += -deltay + newdy; deltax = newdx; deltay = newdy; obj->Game_object::move(t.tx, t.ty, t.tz); // Add back to queue for next time. if (animating) gwin->get_tqueue()->add(curtime + delay, this, udata); } /* * Create at given position. */ Animated_object::Animated_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft ) : Terrain_game_object(shapenum, framenum, tilex, tiley, lft) { animator = Animator::create(this); } /* * When we delete, better remove from queue. */ Animated_object::~Animated_object ( ) { delete animator; } /* * Render. */ void Animated_object::paint ( ) { animator->want_animation(); // Be sure animation is on. Game_object::paint(); } /* * Create at given position. */ Animated_ireg_object::Animated_ireg_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft ) : Ireg_game_object(shapenum, framenum, tilex, tiley, lft) { animator = Animator::create(this); } /* * When we delete, better remove from queue. */ Animated_ireg_object::~Animated_ireg_object ( ) { delete animator; } /* * Render. */ void Animated_ireg_object::paint ( ) { animator->want_animation(); // Be sure animation is on. Ireg_game_object::paint(); } /* * Write out. */ void Animated_ireg_object::write_ireg(DataSource *out) { int oldframe = get_framenum(); set_frame(animator->get_framenum()); Ireg_game_object::write_ireg(out); set_frame(oldframe); } /* * Create at given position. */ Animated_ifix_object::Animated_ifix_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft ) : Ifix_game_object(shapenum, framenum, tilex, tiley, lft) { animator = Animator::create(this); } /* * Create from IFIX */ Animated_ifix_object::Animated_ifix_object(unsigned char *ifix) : Ifix_game_object(ifix) { animator = Animator::create(this); } /* * When we delete, better remove from queue. */ Animated_ifix_object::~Animated_ifix_object ( ) { delete animator; } /* * Render. */ void Animated_ifix_object::paint ( ) { animator->want_animation(); // Be sure animation is on. Ifix_game_object::paint(); } /* * Write out an IFIX object. */ void Animated_ifix_object::write_ifix(DataSource *ifix) { int oldframe = get_framenum(); set_frame(animator->get_framenum()); Ifix_game_object::write_ifix(ifix); set_frame(oldframe); } exult-1.2/objs/spellbook.cc0000644000175000001440000001775110054030576011443 /** ** Spellbook.cc - Spellbook object. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 2000 The Exult Team. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "spellbook.h" #include "gamewin.h" #include "gamemap.h" #include "utils.h" #include "game.h" #include "Gump_manager.h" #include "databuf.h" #include "ucsched.h" #include "actors.h" #include "cheat.h" #include "ucmachine.h" #ifndef UNDER_CE using std::memcpy; using std::ostream; #endif const int REAGENTS = 842; // Shape #. /* * Flags for required reagents. Bits match frame #. */ const int bp = 1; // Black pearl. const int bm = 2; // Blood moss. const int ns = 4; // Nightshade. const int mr = 8; // Mandrake root. const int gr = 16; // Garlic. const int gn = 32; // Ginseng. const int ss = 64; // Spider silk. const int sa = 128; // Sulphuras ash. const int bs = 256; // Blood spawn. const int sc = 512; // Serpent scales. const int wh = 1024; // Worm's hart. // Black Gate: unsigned short Spellbook_object::bg_reagents[9*8] = { 0, 0, 0, 0, 0, 0, 0, 0, // Linear spells require no reagents. // Circle 1: gr|gn|mr, gr|gn, ns|ss, gr|ss, sa|ss, sa, ns, gr|gn, // Circle 2: bm|sa, bp|mr, bp|sa, mr|sa, gr|gn|mr, gr|gn|sa, bp|bm|mr, bm|ns|mr|sa|bp|ss, // Circle 3: gr|ns|sa, gr|gn|ss, ns|ss, ns|mr, ns|bm|bp, gr|gn|mr|sa, bp|ns|ss, ns|mr|bm, // Circle 4: ss|mr, bp|sa|mr, mr|bp|bm, gr|mr|ns|sa, mr|bp|bm, bm|sa, bm|mr|ns|ss|sa, bm|sa, // Circle 5: bp|ns|ss, mr|gr|bm, gr|bp|sa|ss, bm|bp|mr|sa, bp|ss|sa, gr|gn|mr|ss, bm|ns, gn|ns|ss, // Circle 6: gr|mr|ns, sa|ss|bm|gn|ns|mr, bp|mr|ss|sa, sa|bp|bm, mr|ns|sa|bm, ns|ss|bp, gn|ss|bp, bm|sa|mr, // Circle 7: mr|ss, bp|ns|sa, bm|bp|mr|ss|sa, bp|mr|ss|sa, bm|mr|ns|sa, bp|ns|ss|mr, bp|gn|mr, gr|gn|mr|sa, // Circle 8: bp|bm|gr|gn|mr|ns|ss|sa, bm|mr|ns|sa, bp|bm|mr|ns, bm|gr|gn|mr|ns, gr|gn|ss|sa, bm|gr|mr, bp|mr|ns, bm|gr|mr }; // Serpent Isle: unsigned short Spellbook_object::si_reagents[9*8] = { // Circle 1: gr|gn|mr, gr|gn, ns|ss, gr|ss, sa|ss, sa, ns, bp|bm|mr, // Circle 2: gr|gn, bm|sa, ns|sa, bp|sa|wh, mr|sa, gr|gn|ss, gr|gn|mr, gr|gn|sa, // Circle 3: gr|gn|wh,gr|ns|sa, bp|mr, bp|gr, gr|gn|mr|sa, ns|ss, bp|ns|ss, bp|mr|sa|sa, // Circle 4: bm|mr, gr|ss, mr|sa, sa|bm|gr|mr|ss|sc, gr|mr|ns|sa, bm|sa, bp|ss, bm|sa, // Circle 5: mr|ss, bp|gr|ss|sa, bm|bp|mr|sa, gr|gn|mr|ss, bm|ns, gn|ns|ss, sa|bm|mr|ns|ss, bp|gr|mr|sa, // Circle 6: bp|ns|ss, gr|mr|ns, gr|mr|ns, bp|wh|ss|sa, bp|wh|mr|ss|sa, bm|bp|wh|sa, bm|gn|sa, mr|sa|ss|sc, // Circle 7: bp|mr|ss|sa, bm|mr|ns|sa, gr|gn, bp|gn|mr, bm|ns|sa, gr|gn|mr|ss, bp|bm|mr|ss, bp|mr|sa, // Circle 8: wh|ss, bs|bp|ns|sa, bm|bp|mr|ss|sa, bm|bp|mr, bm|gr|ss|wh|sc, bm|bp|gr|ss|wh|sc, gr|mr|sa, bp|bs|mr|ns, // Circle 9: bm|mr|ns|sa, bm|bs|gr|gn|mr|ns, bp|bm|mr|ns, bm|bs|bp|ns|sa, bp|gr|mr|ss|sa, bm|gr|mr|ss, bm|gr|mr, ns|sa|wh|sc }; /* * Get usecode function for a given spell: */ int Get_usecode(int spell) { return 0x640 + spell; } /* * Test for Ring of Reagants. */ bool Spellbook_object::has_ring ( Actor *act ) { if (Game::get_game_type() == SERPENT_ISLE) { Game_object *obj = act->get_readied(Actor::lfinger); if (obj && obj->get_shapenum() == 0x128 && obj->get_framenum() == 3) return true; obj = act->get_readied(Actor::rfinger); if (obj && obj->get_shapenum() == 0x128 && obj->get_framenum() == 3) return true; } return false; } /* * Create a spellbook from Ireg data. */ Spellbook_object::Spellbook_object ( int shapenum, int framenum, unsigned int shapex, unsigned int shapey, unsigned int lft, unsigned char *c, // Circle spell flags. unsigned char bmark // Spell bookmark. ) : Ireg_game_object(shapenum, framenum, shapex, shapey, lft), bookmark(bmark == 255 ? -1 : bmark) { memcpy(circles, c, sizeof(circles)); // Point to reagent table. reagents = GAME_SI ? si_reagents : bg_reagents; } /* * Add a spell. * * Output: 0 if already have it, 1 if successful. */ int Spellbook_object::add_spell ( int spell // 0-71 ) { int circle = spell/8; int num = spell%8; // # within circle. if (circles[circle] & (1<get_property(Actor::mana); int level = act->get_level(); if ((mana < circle) || (level < circle)) // Not enough mana or not yet at required level? return false; if (has_ring(act)) // Ring of reagents (SI)? return true; // Figure what we used. unsigned short flags = reagents[spell]; // Go through bits. for (int r = 0; flags; r++, flags = flags >> 1) // Need 1 of each required reagent. if ((flags&1) && act->count_objects(REAGENTS, c_any_qual, r) == 0) return false; // Missing. return true; } /* * Perform a spell. * * Output: False if unsuccessful. */ bool Spellbook_object::do_spell ( Actor *act, int spell, bool can_do, // Already checked. bool in_combat // Being used in combat. ) { if (can_do || can_do_spell(act, spell)) { int circle = spell/8; // Figure/subtract mana. if (cheat.in_wizard_mode()) circle = 0; int mana = act->get_property(Actor::mana); act->set_property(Actor::mana, mana-circle); // Figure what we used. unsigned short flags = reagents[spell]; if (!cheat.in_wizard_mode() && !has_ring(act)) { // Go through bits. for (int r = 0; flags; r++, flags = flags >> 1) // Remove 1 of each required reagent. if (flags&1) act->remove_quantity(1, REAGENTS, c_any_qual, r); } execute_spell(act, spell, in_combat); return true; } return false; } /* * Perform the usecode for a spell. */ void Spellbook_object::execute_spell ( Actor *act, int spell, bool in_combat // Being used in combat. ) { ucmachine->call_usecode(Get_usecode(spell), act, in_combat ? Usecode_machine::weapon : Usecode_machine::double_click); } /* * Show book when double-clicked. */ void Spellbook_object::activate ( int event ) { gumpman->add_gump(this, Game::get_game_type() == BLACK_GATE ? 43 : 38); } /* * Write out. */ void Spellbook_object::write_ireg ( DataSource *out ) { unsigned char buf[19]; // 18-byte entry + length-byte. buf[0] = 18; uint8 *ptr = &buf[1]; // To avoid confusion about offsets. write_common_ireg(ptr); // Fill in bytes 1-4. ptr += 4; memcpy(ptr, &circles[0], 5); // Store the way U7 does it. ptr += 5; *ptr++ = (get_lift()&15)<<4; // Low bits?++++++ memcpy(ptr, &circles[5], 4); // Rest of spell circles. ptr += 4; *ptr++ = 0; // 3 unknowns. *ptr++ = 0; *ptr++ = 0; *ptr++ = bookmark >= 0 ? bookmark : 255; out->write((char*)buf, sizeof(buf)); // Write scheduled usecode. Game_map::write_scheduled(out, this); } // Get size of IREG. Returns -1 if can't write to buffer int Spellbook_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gumpman->find_gump(this) || Usecode_script::find(this)) return -1; return 19; } exult-1.2/objs/contain.cc0000644000175000001440000004623110054030565011075 /* * contain.cc - Container objects. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "contain.h" #include "gamewin.h" #include "gamemap.h" #include "objiter.h" #include "game.h" #include "ucmachine.h" #include "keyring.h" #include "utils.h" #include "Gump_manager.h" #include "databuf.h" #include "ucsched.h" #ifndef UNDER_CE using std::rand; using std::ostream; #endif /* * Delete all contents. */ Container_game_object::~Container_game_object ( ) { } /* * Remove an object. The object's (cx, cy) fields are set to invalid * #'s (255, 255). */ void Container_game_object::remove ( Game_object *obj ) { if (objects.is_empty()) return; volume_used -= obj->get_volume(); obj->set_owner(0); objects.remove(obj); obj->set_invalid(); // No longer part of world. } /* * Add an object. * * Output: 1, meaning object is completely contained in this. Obj may * be deleted in this case if combine==true. * 0 if not enough space, although obj's quantity may be * reduced if combine==true. */ bool Container_game_object::add ( Game_object *obj, bool dont_check, // 1 to skip volume/recursion check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { if (!dont_check) { // Can't put a bag in a bag. int shnum = get_shapenum(); if (shnum == obj->get_shapenum() || shnum == 522 || // Can't put into locked chest. (shnum == 798 && GAME_BG)) // Or sealed box. return false; } // ugly hack for SI urn (shouldn't be a container) if (Game::get_game_type() == SERPENT_ISLE && get_shapenum() == 914) { return false; } // Always check this. ALWAYS! Game_object *parent = this; do // Watch for snake eating itself. if (obj == parent) return false; while ((parent = parent->get_owner()) != 0); if (combine) // Should we try to combine? { Shape_info& info = obj->get_info(); int quant = obj->get_quantity(); // Combine, but don't add. int newquant = add_quantity(quant, obj->get_shapenum(), info.has_quality() ? obj->get_quality() : c_any_qual, obj->get_framenum(), true); if (newquant == 0) // All added? { obj->remove_this(); return true; } else if (newquant < quant) // Partly successful. obj->modify_quantity(newquant - quant); } int objvol = obj->get_volume(); if (!dont_check) { int maxvol = get_max_volume(); // maxvol = 0 means infinite (ship's hold, hollow tree, etc...) if (maxvol > 0 && objvol + volume_used > maxvol) return false; // Doesn't fit. } volume_used += objvol; obj->set_owner(this); // Set us as the owner. objects.append(obj); // Append to chain. // Guessing: if (get_flag(Obj_flags::okay_to_take)) obj->set_flag(Obj_flags::okay_to_take); return true; } /* * Change shape of a member. */ void Container_game_object::change_member_shape ( Game_object *obj, int newshape ) { int oldvol = obj->get_volume(); obj->set_shape(newshape); // Update total volume. volume_used += obj->get_volume() - oldvol; } /* * Add a key (by quality) to the SI keyring. * * Output: 1 if successful, else 0 (and this does need to be an int). */ static int Add2keyring ( int qual, int framenum ) { if (framenum >=21 && framenum <= 23) return 0; // Fire, ice, blackrock in SI. Keyring *ring = Game_window::get_instance()->get_usecode()->getKeyring(); // Valid quality & not already there? if (qual != c_any_qual && !ring->checkkey(qual)) { ring->addkey(qual); return 1; } return 0; } /* * Get information about whether a shape is a 'quantity' shape, and * whether we need to match its framenum to combine it with another. * * Output: True if a 'quantity' shape. */ static bool Get_combine_info ( int shapenum, int framenum, bool& quantity_frame // Rets. true if frame depends on quan. ) { Game_window *gwin = Game_window::get_instance(); Shape_info& info = ShapeID::get_info(shapenum); quantity_frame = false; if (!info.has_quantity()) return false; switch (shapenum) // Which shapes have frames depending { // on their quantity? case 644: // Coins. case 627: // Lockpicks. case 581: // Ammunition. case 554: // Burst arrows. case 556: // Magic arrows. case 558: // Lucky arrows. case 560: // Love arrows. case 568: // Tseramed arrows. case 722: // Arrows. case 723: // Bolts. case 417: // Magic bolts. case 948: // Bolts. (or SI filari). quantity_frame = true; break; case 951: // Monetari/guilders: case 952: if (GAME_SI) quantity_frame = true; break; default: break; } return true; } /* * Recursively add a quantity of an item to those existing in * this container, and create new objects if necessary. * * Output: Delta decremented # added. */ int Container_game_object::add_quantity ( int delta, // Quantity to add. int shapenum, // Shape #. int qual, // Quality, or c_any_qual for any. int framenum, // Frame, or c_any_framenum for any. int dontcreate // If 1, don't create new objs. ) { if (delta <= 0) return delta; int cant_add = 0; // # we can't add due to weight. int maxweight = get_max_weight();// Check weight. if (maxweight) { maxweight *= 10; // Work in .1 stones. int avail = maxweight - get_outermost()->get_weight(); int objweight = Ireg_game_object::get_weight(shapenum, delta); if (objweight && objweight > avail) { // Limit what we can add. // Work in 1/100ths. int weight1 = (10*objweight)/delta; cant_add = delta - (10*avail)/(weight1 ? weight1 : 1); if (cant_add >= delta) return delta; // Can't add any. delta -= cant_add; } } bool has_quantity_frame; // Quantity-type shape? bool has_quantity = Get_combine_info( shapenum, framenum, has_quantity_frame); // Note: quantity is ignored for // figuring volume. Game_object *obj; if (!objects.is_empty()) { // First try existing items. Object_iterator next(objects); while (delta && (obj = next.get_next()) != 0) { if (has_quantity && obj->get_shapenum() == shapenum && (framenum == c_any_framenum || has_quantity_frame || obj->get_framenum() == framenum)) delta = obj->modify_quantity(delta); // Adding key to SI keyring? else if (GAME_SI && shapenum == 641 && obj->get_shapenum() == 485 && delta == 1) delta -= Add2keyring(qual, framenum); } next.reset(); // Now try recursively. while ((obj = next.get_next()) != 0) delta = obj->add_quantity( delta, shapenum, qual, framenum, 1); } if (!delta || dontcreate) // All added? return (delta + cant_add); else return cant_add + create_quantity(delta, shapenum, qual, framenum == c_any_framenum ? 0 : framenum); } /* * Recursively create a quantity of an item. Assumes weight check has * already been done. * * Output: Delta decremented # added. */ int Container_game_object::create_quantity ( int delta, // Quantity to add. int shnum, // Shape #. int qual, // Quality, or c_any_qual for any. int frnum, // Frame. bool temporary // Create temporary quantity ) { // Usecode container? if (get_shapenum() == 486 && Game::get_game_type() == SERPENT_ISLE) return delta; Shape_info& shp_info = ShapeID::get_info(shnum); if (!shp_info.has_quality()) // Not a quality object? qual = c_any_qual; // Then don't set it. while (delta) // Create them here first. { Game_object *newobj = gmap->create_ireg_object( shp_info, shnum, frnum,0,0,0); if (!add(newobj)) { delete newobj; break; } // Set temporary if (temporary) newobj->set_flag (Obj_flags::is_temporary); if (qual != c_any_qual) // Set desired quality. newobj->set_quality(qual); delta--; if (delta > 0) delta = newobj->modify_quantity(delta); } if (!delta) // All done? return (0); // Now try those below. Game_object *obj; if (objects.is_empty()) return (delta); Object_iterator next(objects); while ((obj = next.get_next()) != 0) delta = obj->create_quantity(delta, shnum, qual, frnum); return (delta); } /* * Recursively remove a quantity of an item from those existing in * this container. * * Output: Delta decremented by # removed. */ int Container_game_object::remove_quantity ( int delta, // Quantity to remove. int shapenum, // Shape #. int qual, // Quality, or c_any_qual for any. int framenum // Frame, or c_any_framenum for any. ) { if (objects.is_empty()) return delta; // Empty. Game_object *obj = objects.get_first(); Game_object *last = obj->get_prev(); // Save last. Game_object *next; while (obj && delta) { // Might be deleting obj. next = obj == last ? 0 : obj->get_next(); bool del = false; // Gets 'deleted' flag. if (obj->get_shapenum() == shapenum && (qual == c_any_qual || obj->get_quality() == qual) && (framenum == c_any_framenum || (obj->get_framenum()&31) == framenum)) delta = -obj->modify_quantity(-delta, &del); if (!del) // Still there? // Do it recursively. delta = obj->remove_quantity(delta, shapenum, qual, framenum); obj = next; } return (delta); } /* * Find and return a desired item. * * Output: ->object if found, else 0. */ Game_object *Container_game_object::find_item ( int shapenum, // Shape #. int qual, // Quality, or c_any_qual for any. int framenum // Frame, or c_any_framenum for any. ) { if (objects.is_empty()) return 0; // Empty. Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { if (obj->get_shapenum() == shapenum && (framenum == c_any_framenum || (obj->get_framenum()&31) == framenum) && (qual == c_any_qual || obj->get_quality() == qual)) return (obj); // Do it recursively. Game_object *found = obj->find_item(shapenum, qual, framenum); if (found) return (found); } return (0); } /* * Run usecode when double-clicked. */ void Container_game_object::activate ( int event ) { if (edit()) return; // Map-editing. int shnum = get_shapenum(); Gump_manager *gump_man = gumpman; if (Game::get_game_type() == BLACK_GATE) switch(shnum) // Watch for gumps. { case 405: // Ship's hold gump_man->add_gump(this, game->get_shape("gumps/shipshold")); return; case 406: // Nightstand. case 407: // Desk. case 283: case 203: case 416: // Chest of drawers. case 679: gump_man->add_gump(this, game->get_shape("gumps/drawer")); return; case 400: // Bodies. case 414: case 762: case 778: case 892: case 507: // Bones gump_man->add_gump(this, game->get_shape("gumps/body")); return; case 800: // Chest. gump_man->add_gump(this, game->get_shape("gumps/chest")); return; case 801: // Backpack. gump_man->add_gump(this, game->get_shape("gumps/backpack")); return; case 799: // Unsealed box gump_man->add_gump(this, game->get_shape("gumps/box")); return; case 802: // Bag. gump_man->add_gump(this, game->get_shape("gumps/bag")); return; case 803: // Basket. gump_man->add_gump(this, game->get_shape("gumps/basket")); return; case 804: // Crate. gump_man->add_gump(this, game->get_shape("gumps/crate")); return; case 819: // Barrel. gump_man->add_gump(this, game->get_shape("gumps/barrel")); return; } else if (Game::get_game_type() == SERPENT_ISLE) switch(shnum) // Watch for gumps. { case 405: // Ship's hold gump_man->add_gump(this, game->get_shape("gumps/shipshold")); return; case 406: // Nightstand. case 407: // Desk. case 283: case 416: // Chest of drawers. case 679: gump_man->add_gump(this, game->get_shape("gumps/drawer")); return; case 400: // Bodies. case 402: case 414: case 762: case 778: case 892: case 507: // Bones gump_man->add_gump(this, game->get_shape("gumps/body")); return; case 800: // Chest. if (get_quality() >= 251) // Trapped? { // Run normal usecode fun. ucmachine->call_usecode(shnum, this, (Usecode_machine::Usecode_events) event); return; } // FALL THROUGH to 486. case 486: // Usecode container. gump_man->add_gump(this, game->get_shape("gumps/chest")); return; case 801: // Backpack. gump_man->add_gump(this, game->get_shape("gumps/backpack")); return; case 799: // Unsealed box gump_man->add_gump(this, game->get_shape("gumps/box")); return; case 802: // Bag. gump_man->add_gump(this, game->get_shape("gumps/bag")); return; case 803: // Basket. gump_man->add_gump(this, game->get_shape("gumps/basket")); return; case 804: // Crate. gump_man->add_gump(this, game->get_shape("gumps/crate")); return; case 819: // Barrel. gump_man->add_gump(this, game->get_shape("gumps/barrel")); return; case 297: // Hollow Tree gump_man->add_gump(this, game->get_shape("gumps/tree")); return; case 555: // Serpent Jawbone gump_man->add_gump(this, game->get_shape("gumps/jawbone")); return; } // Try to run normal usecode fun. ucmachine->call_usecode(shnum, this, (Usecode_machine::Usecode_events) event); } /* * Get (total) weight. */ int Container_game_object::get_weight ( ) { int wt = Ireg_game_object::get_weight(); Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) wt += obj->get_weight(); return wt; } /* * Drop another onto this. * * Output: 0 to reject, 1 to accept. */ int Container_game_object::drop ( Game_object *obj // May be deleted if combined. ) { if (!get_owner()) // Only accept if inside another. return (0); return (add(obj, false, true)); // We'll take it, and try to combine. } /* * Recursively count all objects of a given shape. */ int Container_game_object::count_objects ( int shapenum, // Shape#, or c_any_shapenum for any. int qual, // Quality, or c_any_qual for any. int framenum // Frame#, or c_any_framenum for any. ) { int total = 0; Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { if ((shapenum == c_any_shapenum || obj->get_shapenum() == shapenum) && // Watch for reflection. (framenum == c_any_framenum || (obj->get_framenum()&31) == framenum) && (qual == c_any_qual || obj->get_quality() == qual)) { // Check quantity. int quant = obj->get_quantity(); total += quant; } // Count recursively. total += obj->count_objects(shapenum, qual, framenum); } return (total); } /* * Recursively get all objects of a given shape. */ int Container_game_object::get_objects ( Game_object_vector& vec, // Objects returned here. int shapenum, // Shape#, or c_any_shapenum for any. int qual, // Quality, or c_any_qual for any. int framenum // Frame#, or c_any_framenum for any. ) { int vecsize = vec.size(); Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { if ((shapenum == c_any_shapenum || obj->get_shapenum() == shapenum) && (qual == c_any_qual || obj->get_quality() == qual) && // Watch for reflection. (framenum == c_any_framenum || (obj->get_framenum()&31) == framenum)) vec.push_back(obj); // Search recursively. obj->get_objects(vec, shapenum, qual, framenum); } return (vec.size() - vecsize); } /* * Set a flag on this and all contents. */ void Container_game_object::set_flag_recursively ( int flag ) { set_flag(flag); Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) obj->set_flag_recursively(flag); } /* * Write out container and its members. */ void Container_game_object::write_ireg ( DataSource *out ) { unsigned char buf[13]; // 13-byte entry + length-byte. buf[0] = 12; uint8 *ptr = &buf[1]; // To avoid confusion about offsets. write_common_ireg(ptr); // Fill in bytes 1-4. ptr += 4; Game_object *first = objects.get_first(); // Guessing: +++++ unsigned short tword = first ? first->get_prev()->get_shapenum() : 0; Write2(ptr, tword); *ptr++ = 0; // Unknown. *ptr++ = get_quality(); int npc = get_live_npc_num(); // If body, get source. int quant; if (Game::get_game_type() == SERPENT_ISLE) quant = npc + 0x80; else quant = (npc >= 0 && npc <= 127) ? (npc + 0x80) : 0; *ptr++ = quant&0xff; // "Quantity". *ptr++ = (get_lift()&15)<<4; // Lift *ptr++ = (unsigned char)resistance; // Resistance. // Flags: B0=invis. B3=okay_to_take. *ptr++ = get_flag((Obj_flags::invisible) != 0) + ((get_flag(Obj_flags::okay_to_take) != 0) << 3); out->write((char*)buf, sizeof(buf)); write_contents(out); // Write what's contained within. // Write scheduled usecode. Game_map::write_scheduled(out, this); } // Get size of IREG. Returns -1 if can't write to buffer int Container_game_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gumpman->find_gump(this) || Usecode_script::find(this)) return -1; int total_size = 13; // Now what's inside. if (!objects.is_empty()) { Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { int size = obj->get_ireg_size(); if (size < 0) return -1; total_size += size; } total_size += 1; } return total_size; } /* * Write contents (if there is any). */ void Container_game_object::write_contents ( DataSource *out ) { if (!objects.is_empty()) // Now write out what's inside. { Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) obj->write_ireg(out); out->write1(0x01); // A 01 terminates the list. } } bool Container_game_object::extract_contents() { if (objects.is_empty()) return true; bool status = true; Container_game_object *owner = get_owner(); Game_object *obj; while ((obj = objects.get_first())) { remove(obj); if (owner) { owner->add(obj,1); // add without checking volume } else { obj->set_invalid(); // set to invalid chunk so move() doesn't fail if ((get_cx() == 255) && (get_cy() == 255)) { obj->remove_this(0); status = false; } else { obj->move(get_tile()); } } } return status; } void Container_game_object::delete_contents() { if (objects.is_empty()) return; Game_object *obj; while ((obj = objects.get_first())) { remove(obj); obj->delete_contents(); // recurse into contained containers obj->remove_this(0); } } void Container_game_object::remove_this(int nodel) { // Special case to avoid recursion. if (Container_game_object::get_owner()) { // First remove from owner. Ireg_game_object::remove_this(1); if (nodel) // Not deleting? Then done. return; } if (!nodel) extract_contents(); Ireg_game_object::remove_this(nodel); } exult-1.2/objs/virstone.h0000644000175000001440000000313007505074442011155 /** ** Virstone.h - Virtue stones. ** ** Written: 10/27/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_VIRSTONE #define INCL_VIRSTONE 1 #include "iregobjs.h" /* * A virtue stone can be set to a position on the map. */ class Virtue_stone_object : public Ireg_game_object { Tile_coord pos; // Position it teleports to. public: Virtue_stone_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft) : Ireg_game_object(shapenum, framenum, tilex, tiley, lft), pos(0, 0, 0) { } void set_pos(Tile_coord t) // Set/get position. { pos = t; } void set_pos(unsigned char tilex, unsigned char tiley, unsigned char schunk, unsigned char lft); Tile_coord get_pos() { return pos; } // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); }; #endif exult-1.2/objs/contain.h0000644000175000001440000000753107724430452010750 /* * contain.h - Container objects. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_CONTAIN #define INCL_CONTAIN 1 #include "iregobjs.h" /* * A container object: */ class Container_game_object : public Ireg_game_object { int volume_used; // Amount of volume occupied. char resistance; // Resistance to attack. protected: Object_list objects; // ->first object. int get_max_volume() const // Max. we'll hold. (Guessing). { int v = get_volume(); return v; } public: Container_game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, char res = 0) : Ireg_game_object(shapenum, framenum, tilex, tiley, lft), volume_used(0), resistance(res), objects(0) { } Container_game_object() : volume_used(0), resistance(0), objects(0) { } virtual ~Container_game_object(); Object_list& get_objects() { return objects; } // For when an obj's quantity changes: void modify_volume_used(int delta) { volume_used += delta; } // Room for this object? int has_room(Game_object *obj) const { return get_max_volume() <= 0 || obj->get_volume() + volume_used <= get_max_volume(); } // Remove an object. virtual void remove(Game_object *obj); // Add an object. virtual bool add(Game_object *obj, bool dont_check = false, bool combine = false); // Change member shape. virtual void change_member_shape(Game_object *obj, int newshape); // Find object's spot. virtual int find_readied(Game_object *obj) { return -1; } virtual Game_object *get_readied(int index) const { return 0; } virtual void call_readied_usecode(int index, Game_object *obj, int eventid) { } // Add/remove quantities of objs. virtual int add_quantity(int delta, int shapenum, int qual = c_any_qual, int framenum = c_any_framenum, int dontcreate = 0); virtual int create_quantity(int delta, int shapenum, int qual, int framenum, bool temporary = false); virtual int remove_quantity(int delta, int shapenum, int qual, int framenum); virtual Game_object *find_item(int shapenum, int qual, int framenum); // Run usecode function. virtual void activate(int event = 1); virtual int get_weight(); // Drop another onto this. virtual int drop(Game_object *obj); // Count contained objs. virtual int count_objects(int shapenum, int qual = c_any_qual, int framenum = c_any_framenum); // Get contained objs. virtual int get_objects(Game_object_vector& vec, int shapenum, int qual, int framenum); virtual void set_flag_recursively(int flag); // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); // Write contents in IREG format. virtual void write_contents(DataSource* out); virtual int get_obj_hp() const { return resistance; } virtual void set_obj_hp(int hp) { resistance = (char)hp; } bool extract_contents(); virtual void delete_contents(); virtual void remove_this(int nodel = 0); virtual Container_game_object *as_container() { return this; } }; #endif exult-1.2/objs/flags.h0000755000175000001440000000363007520163074010405 /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef FLAGS_H #define FLAGS_H namespace Obj_flags { enum { // Bit #'s of flags: invisible = 0, asleep = 1, charmed = 2, cursed = 3, dead = 4, in_party = 6, // Guess, appears to be correct paralyzed = 7, poisoned = 8, protection = 9, on_moving_barge = 10, // ??Guessing. okay_to_take = 11, // Okay to take?? might = 12, // Double strength, dext, intel. no_spell_casting = 13, cant_die = 14, // Test flag in Monster_info. dancing = 15, // ??Not sure. dont_move = 16, // User can't move. In BG, // completely invisible. si_on_moving_barge = 17,// SI's version of 10? is_temporary = 18, // Is temporary okay_to_land = 21, // Used for flying-carpet. in_dungeon = 23, // Pretty sure. If set, you won't // be accused of stealing food. confused = 25, // ??Guessing. in_motion = 26, // ??Guessing (cart, boat)?? met = 28, // Has the npc been met si_tournament = 29, // SI-Call usecode (eventid=7) si_zombie = 30, // Used for sick Neyobi. // Flags > 31 polymorph = 32, // SI. Pretty sure about this. tattooed = 33, // Guess (SI). read = 34, // Guess (SI). petra = 35, // Guess freeze = 37 // SI. Pretty sure. }; } #endif exult-1.2/objs/egg.cc0000644000175000001440000006721110054030566010206 /* * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Audio.h" #include "monsters.h" #include "cheat.h" #include "chunks.h" #include "animate.h" #include "effects.h" #include "egg.h" #include "exult.h" #include "game.h" #include "gameclk.h" #include "gamewin.h" #include "gamemap.h" #include "npctime.h" #include "paths.h" #include "ucmachine.h" #include "ucscriptop.h" #include "ucsched.h" #include "Gump_manager.h" #ifdef USE_EXULTSTUDIO #include "server.h" #include "objserial.h" #include "mouse.h" #include "servemsg.h" #endif #ifndef UNDER_CE using std::cout; using std::endl; using std::rand; using std::ostream; #endif Egg_object *Egg_object::editing = 0; /* * Timer for a missile egg (type-6 egg). */ class Missile_launcher : public Time_sensitive, public Game_singletons { Egg_object *egg; // Egg this came from. int weapon; // Shape for weapon. int shapenum; // Shape for missile. int dir; // Direction (0-7). (8==??). int delay; // Delay (msecs) between launches. public: Missile_launcher(Egg_object *e, int weap, int shnum, int di, int del) : egg(e), weapon(weap), shapenum(shnum), dir(di), delay(del) { } virtual void handle_event(unsigned long curtime, long udata); }; /* * Launch a missile. */ void Missile_launcher::handle_event ( unsigned long curtime, long udata ) { Tile_coord src = egg->get_tile(); // Is egg off the screen? if (!gwin->get_win_tile_rect().has_point(src.tx, src.ty)) return; // Return w'out adding back to queue. Projectile_effect *proj = 0; if (dir < 8) // Direction given? { // Get adjacent tile in direction. Tile_coord adj = src.get_neighbor(dir%8); // Make it go 20 tiles. int dx = adj.tx - src.tx, dy = adj.ty - src.ty; Tile_coord dest = src; dest.tx += 20*dx; dest.ty += 20*dy; proj = new Projectile_effect(src, dest, shapenum, weapon); } else // Target a party member. { Actor *party[9]; int psize = gwin->get_party(party, 1); int cnt = psize; int n = rand()%psize; // Pick one at random. // Find one we can hit. for (int i = n; !proj && cnt; cnt--, i = (i + 1)%psize) if (Fast_pathfinder_client::is_straight_path(src, party[i]->get_tile())) proj = new Projectile_effect( src, party[i], shapenum, weapon); } if (proj) eman->add_effect(proj); // Add back to queue for next time. gwin->get_tqueue()->add(curtime + (delay > 0 ? delay : 1), this, udata); } /* * Paint at given spot in world. */ void Egglike_game_object::paint ( ) { if(gwin->paint_eggs) Game_object::paint(); } /* * Can this be clicked on? */ int Egglike_game_object::is_findable ( ) { return gwin->paint_eggs && Ireg_game_object::is_findable(); } /* * Create an egg from IREG data. */ Egg_object::Egg_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned short itype, unsigned char prob, short d1, short d2 ) : Egglike_game_object(shapenum, framenum, tilex, tiley, lft), probability(prob), data1(d1), data2(d2), area(Rectangle(0, 0, 0, 0)), launcher(0) { type = itype&0xf; // Teleport destination? if (type == teleport && framenum == 6 && shapenum == 275) type = path; // (Mountains N. of Vesper). criteria = (itype & (7<<4)) >> 4; distance = (itype >> 10) & 0x1f; unsigned char noct = (itype >> 7) & 1; unsigned char do_once = (itype >> 8) & 1; // Missile eggs can be rehatched unsigned char htch = (type == missile) ? 0 : ((itype >> 9) & 1); solid_area = (criteria == something_on || criteria == cached_in || // Teleports need solid area. type == teleport) ? 1 : 0; unsigned char ar = (itype >> 15) & 1; flags = (noct << nocturnal) + (do_once << once) + (htch << hatched) + (ar << auto_reset); if (type == usecode || type == teleport || type == path) set_quality(data1&0xff); // Party_near & auto_reset don't mix // well. if (criteria == party_near && (flags&(1<get_tqueue()->remove(launcher); delete launcher; } } /* * Set active area after being added to its chunk. */ void Egg_object::set_area ( ) { if (!probability || type == path)// No chance of normal activation? { area = Rectangle(0, 0, 0, 0); return; } Tile_coord t = get_tile(); // Get absolute tile coords. switch (criteria) // Set up active area. { case cached_in: // Make it really large. area = Rectangle(t.tx - 32, t.ty - 32, 64, 64); break; case avatar_footpad: case party_footpad: { Shape_info& info = get_info(); int xtiles = info.get_3d_xtiles(), ytiles = info.get_3d_ytiles(); area = Rectangle(t.tx - xtiles + 1, t.ty - ytiles + 1, xtiles, ytiles); break; } case avatar_far: // Make it 1 tile bigger each dir. area = Rectangle(t.tx - distance - 1, t.ty - distance - 1, 2*distance + 3, 2*distance + 3); break; default: { int width = 2*distance; width++; // Added 8/1/01. if (distance <= 1) // Small? { // More guesswork: if (criteria == external_criteria) width += 2; } area = Rectangle(t.tx - distance, t.ty - distance, width, width); break; } } // Don't go outside the world. Rectangle world(0, 0, c_num_chunks*c_tiles_per_chunk, c_num_chunks*c_tiles_per_chunk); area = area.intersect(world); } /* * Is the egg active when stepping onto a given spot, or placing an obj. * on the spot? */ int Egg_object::is_active ( Game_object *obj, // Object placed (or Actor). int tx, int ty, int tz, // Tile stepped onto. int from_tx, int from_ty // Tile stepped from. ) { if ((flags & (1 << (int) hatched)) && !(flags & (1 << (int) auto_reset))) return (0); // For now... Already hatched. if (flags & (1 << (int) nocturnal)) { // Nocturnal. int hour = gclock->get_hour(); if (!(hour >= 9 || hour <= 5)) return (0); // It's not night. } if (cheat.in_map_editor()) return 0; // Disable in map-editor. Egg_criteria cri = (Egg_criteria) get_criteria(); int deltaz = tz - get_lift(); int absdeltaz = deltaz < 0 ? -deltaz : deltaz; switch (cri) { case cached_in: // Anywhere in square. { if (obj != gwin->get_main_actor() || !area.has_point(tx, ty)) return 0; // Not in square. if (!(flags & (1 << (int) hatched))) return 1; // First time. // Must have autoreset. // Just activate when reentering. return !area.has_point(from_tx, from_ty); } case avatar_near: if (obj != gwin->get_main_actor()) return 0; #ifdef DEBUG print_debug(); #endif // fall through case party_near: // Avatar or party member. if (!obj->get_flag(Obj_flags::in_party)) return 0; if (type == teleport) // Teleports: Any tile, exact lift. return absdeltaz == 0 && area.has_point(tx, ty); if (!((absdeltaz <= 1 || // Using trial&error here: (Game::get_game_type() == SERPENT_ISLE && type != missile) || (type == missile && tz/5 == get_lift()/5)) && // New tile is in, old is out. area.has_point(tx, ty) && !area.has_point(from_tx, from_ty))) return 0; return 1; case avatar_far: // New tile is outside, old is inside. { if (obj != gwin->get_main_actor() || !area.has_point(tx, ty)) return (0); Rectangle inside(area.x + 1, area.y + 1, area.w - 2, area.h - 2); return inside.has_point(from_tx, from_ty) && !inside.has_point(tx, ty); } case avatar_footpad: return obj == gwin->get_main_actor() && deltaz == 0 && area.has_point(tx, ty); case party_footpad: return area.has_point(tx, ty) && deltaz == 0 && obj->get_flag(Obj_flags::in_party); case something_on: return // Guessing. At SI end, deltaz == -1. deltaz >= -1 && deltaz <= 3 && area.has_point(tx, ty) && !obj->as_actor(); case external_criteria: default: return 0; } } /* * Paint at given spot in world. */ void Egg_object::paint ( ) { Egglike_game_object::paint(); // Make sure launcher is active. if (launcher && !launcher->in_queue()) gwin->get_tqueue()->add(0L, launcher, 0); } /* * Run usecode when double-clicked. */ void Egg_object::activate ( int /* event */ ) { if (!edit()) activate(0, 0); } /* * Edit in ExultStudio. * * Output: True if map-editing & ES is present. */ bool Egg_object::edit ( ) { #ifdef USE_EXULTSTUDIO if (client_socket >= 0 && // Talking to ExultStudio? cheat.in_map_editor()) { editing = 0; Tile_coord t = get_tile(); unsigned long addr = (unsigned long) this; if (Egg_object_out(client_socket, addr, t.tx, t.ty, t.tz, get_shapenum(), get_framenum(), type, criteria, probability, distance, (flags>>nocturnal)&1, (flags>>once)&1, (flags>>hatched)&1, (flags>>auto_reset)&1, data1, data2) != -1) { cout << "Sent egg data to ExultStudio" << endl; editing = this; } else cout << "Error sending egg data to ExultStudio" <= 0) Exult_server::Send_data(client_socket, Exult_server::cancel); return; } if (shape == -1) shape = 275; // FOR NOW. // Create. Gets initialized below. egg = new Egg_object(shape, 0, 0, 0, 0, 0, 0, 0, 0); int lift; // Try to drop at increasing hts. for (lift = 0; lift < 12; lift++) if (gwin->drop_at_lift(egg, x, y, lift)) break; if (lift == 12) { if (client_socket >= 0) Exult_server::Send_data(client_socket, Exult_server::cancel); delete egg; return; } if (client_socket >= 0) Exult_server::Send_data(client_socket, Exult_server::user_responded); } egg->type = type; if (shape != -1) egg->set_shape(shape); if (frame == -1) switch (type) { // (These aren't perfect.) case monster: frame = 0; break; case jukebox: frame = 2; break; case soundsfx:frame = 1; break; case voice: frame = 3; break; case weather: frame = 4; break; case teleport:frame = 5; break; case path: frame = 6; break; case missile: egg->set_shape(200); if ((data2 & 0xFF) < 8) frame = 2 + ((data2 & 0xFF) / 2); else frame = 1; break; default: frame = 7; break; } if (frame != -1) egg->set_frame(frame); gwin->add_dirty(egg); egg->criteria = criteria&7; egg->distance = distance&31; egg->probability = probability; egg->flags = ((nocturnal?1:0)<data1 = data1; egg->data2 = data2; if (type == usecode || type == teleport || type == path) egg->set_quality(data1&0xff); Map_chunk *chunk = gmap->get_chunk_safely(egg->get_cx(), egg->get_cy()); chunk->remove_egg(egg); // Got to add it back. chunk->add_egg(egg); cout << "Egg updated" << endl; #endif } /* * Create a monster nearby. */ static void Create_monster ( Game_window *gwin, Egg_object *egg, int shnum, // Monster shape. Monster_info *inf, // Info. int sched, int align ) { Tile_coord dest = Map_chunk::find_spot( egg->get_tile(), 5, shnum, 0, 1); if (dest.tx != -1) { Monster_actor *monster = Monster_actor::create(shnum, dest, sched, align); gwin->add_dirty(monster); gwin->add_nearby_npc(monster); } } /* * Handle a teleport egg. */ void Egg_object::activate_teleport ( Game_object *obj // Object (actor) that came near it. ) { Tile_coord pos(-1, -1, -1); // Get position to jump to. int qual = get_quality(); if (qual == 255) { // Jump to coords. int schunk = data1 >> 8; pos = Tile_coord( (schunk%12)*c_tiles_per_schunk + (data2&0xff), (schunk/12)*c_tiles_per_schunk + (data2>>8), 0); } else { Egg_vector vec; // Look for dest. egg (frame == 6). if (find_nearby_eggs(vec, 275, 256, qual, 6)) { Egg_object *path = vec[0]; pos = path->get_tile(); } } cout << "Should teleport to (" << pos.tx << ", " << pos.ty << ')' << endl; if (pos.tx != -1 && obj && obj->get_flag(Obj_flags::in_party)) // Teleport everyone!!! gwin->teleport_party(pos); } /* * Hatch egg. */ void Egg_object::activate ( Game_object *obj, // Object (actor) that came near it. bool must // If 1, skip dice roll & execute // usecode eggs immediately. ) { #ifdef DEBUG print_debug(); #endif // Flag it as done. flags |= (1 << (int) hatched); /* +++++ I just move the 'hatched' line here from below the 'return' in an effort to fix the 'monsters spawning too often' bug. NEED to see if this breaks anything! */ /* MAJOR HACK! This is an attempt at a work-around of a potential bug in the original Serpent Isle. See SourceForge bug #879253 Prevent the Serpent Staff egg from hatching only once */ Tile_coord eggpos = get_tile(); if (GAME_SI && eggpos.tx == 1287 && eggpos.ty == 2568 && eggpos.tz == 0) { flags &= ~(1 << (int) hatched); } /* end hack */ int roll = must ? 0 : 1 + rand()%100; if (roll > probability) return; // Out of luck. switch(type) { case jukebox: #ifdef DEBUG cout << "Audio parameters might be: " << (data1&0xff) << " and " << ((data1>>8)&0x01) << endl; #endif Audio::get_ptr()->start_music((data1)&0xff,(data1>>8)&0x01); break; case soundsfx: { int dir = 0; if (obj) // Get direction from obj. to egg. { Tile_coord epos = get_tile(), opos = obj->get_tile(); dir = Get_direction16(opos.ty - epos.ty, epos.tx - opos.tx); } Audio::get_ptr()->play_sound_effect( Audio::game_sfx(data1&0xff), SDL_MIX_MAXVOLUME, dir, (data1>>8)&1); break; } case voice: ucmachine->do_speech(data1&0xff); break; case monster: // Also creates other objects. { int shnum = data2&1023; int frnum = data2>>10; Monster_info *inf = ShapeID::get_info(shnum).get_monster_info(); if (inf) { // Armageddon spell cast? if (gwin->armageddon) break; int sched = data1>>8; int align = data1&3; int cnt = (data1&0xff)>>2; if (cnt > 1) // Randomize. cnt = 1 + (rand()%cnt); while (cnt--) Create_monster(gwin, this, shnum, inf, sched, align); } else // Create item. { Shape_info& info = ShapeID::get_info(shnum); Game_object *nobj =gmap->create_ireg_object(info, shnum, frnum, get_tx(), get_ty(), get_lift()); Map_chunk *chunk = gmap->get_chunk(get_cx(), get_cy()); if (nobj->is_egg()) chunk->add_egg((Egg_object *) nobj); else chunk->add(nobj); gwin->add_dirty(nobj); nobj->set_flag(Obj_flags::okay_to_take); // Objects are created temporary nobj->set_flag(Obj_flags::is_temporary); } break; } case usecode: { // Data2 is the usecode function. if (must) // From script? Do immediately. ucmachine->call_usecode(data2, this, Usecode_machine::egg_proximity); else // Do on next animation frame. { Usecode_script *scr = new Usecode_script(this); scr->add(Ucscript::usecode, data2); if (flags & (1<<(int)once)) { // Don't remove until done. scr->add(Ucscript::remove); flags &= ~(1<<(int)once); } scr->start(gwin->get_std_delay()); } break; } case missile: { // Get data. Not sure about delay. int weapon = data1, dir = data2&0xff, delay = data2>>8; Shape_info& info = ShapeID::get_info(weapon); Weapon_info *winf = info.get_weapon_info(); int proj; if (winf && winf->get_projectile()) proj = winf->get_projectile(); else proj = 856; // Fireball. Shouldn't get here. if (!launcher) launcher = new Missile_launcher(this, weapon, proj, dir, gwin->get_std_delay()*delay); if (!launcher->in_queue()) gwin->get_tqueue()->add(0L, launcher, 0); break; } case teleport: activate_teleport(obj); break; case weather: { set_weather(data1&0xff, data1>>8, this); break; } case button: // Set off all in given area. { int dist = data1&0xff; Egg_vector eggs; find_nearby_eggs(eggs, 275, dist); for (Egg_vector::const_iterator it = eggs.begin(); it != eggs.end(); ++it) { Egg_object *egg = *it; if (egg != this && egg->criteria == external_criteria && !(egg->flags & (1 << (int) hatched))) // Experimental attempting to fix problem in Silver Seed egg->activate(obj, 0); } break; } default: cout << "Egg not actioned" << endl; } if (flags & (1 << (int) once)) remove_this(0); } /* * Print debug information. */ void Egg_object::print_debug ( ) { cout << "Egg type is " << (int) type << ", prob = " << (int) probability << ", distance = " << (int) distance << ", crit = " << (int) criteria << ", once = " << ((flags & (1<<(int)once)) != 0) << ", hatched = " << ((flags & (1<<(int)hatched)) != 0) << ", areset = " << ((flags & (1<<(int)auto_reset)) != 0) << ", data1 = " << data1 << ", data2 = " << data2 << endl; } /* * Set the weather (static). */ void Egg_object::set_weather ( int weather, // 0-6. int len, // In game minutes (I think). Game_object *egg // Egg this came from, or null. ) { if (!len) // Means continuous. len = 120; // How about a couple game hours? int cur = eman->get_weather(); cout << "Current weather is " << cur << "; setting " << weather << endl; switch (weather) { case 0: // Back to normal. eman->remove_weather_effects(); break; case 1: // ++++++++LATER: Should be snow, I think (jsf). case 2: // Storm. if (cur != weather) eman->add_effect(new Storm_effect(len, 0, egg)); break; case 3: // (On Ambrosia). eman->remove_weather_effects(); eman->add_effect(new Sparkle_effect(len, 0, egg)); break; case 6: // Clouds. eman->add_effect(new Clouds_effect(len, 0, egg)); break; default: break; } } /* * Move to a new absolute location. This should work even if the old * location is invalid (cx=cy=255). */ void Egg_object::move ( int newtx, int newty, int newlift ) { // Figure new chunk. int newcx = newtx/c_tiles_per_chunk, newcy = newty/c_tiles_per_chunk; Map_chunk *newchunk = gmap->get_chunk_safely(newcx, newcy); if (!newchunk) return; // Bad loc. remove_this(1); // Remove from old. set_lift(newlift); // Set new values. shape_pos = ((newtx%c_tiles_per_chunk) << 4) + newty%c_tiles_per_chunk; newchunk->add_egg(this); // Updates cx, cy. gwin->add_dirty(this); // And repaint new area. } /* * This is needed since it calls remove_egg(). */ void Egg_object::remove_this ( int nodel // 1 to not delete. ) { if (get_owner()) // Watch for this. get_owner()->remove(this); else { Map_chunk *chunk = gmap->get_chunk_safely(cx, cy); if (chunk) { gwin->add_dirty(this); // (Make's ::move() simpler.). chunk->remove_egg(this); } } if (launcher) // Stop missiles. { gwin->get_tqueue()->remove(launcher); delete launcher; launcher = 0; } if (!nodel) gwin->delete_object(this); } /* * Write out. */ void Egg_object::write_ireg ( DataSource *out ) { unsigned char buf[13]; // 13-byte entry + length-byte. buf[0] = 12; uint8 *ptr = &buf[1]; // To avoid confusion about offsets. write_common_ireg(ptr); // Fill in bytes 1-4. ptr += 4; unsigned short tword = type&0xf;// Set up 'type' word. tword |= ((criteria&7)<<4); tword |= (((flags>>nocturnal)&1)<<7); tword |= (((flags>>once)&1)<<8); tword |= (((flags>>hatched)&1)<<9); tword |= ((distance&0x1f)<<10); tword |= (((flags>>auto_reset)&1)<<15); Write2(ptr, tword); *ptr++ = probability; Write2(ptr, data1); *ptr++ = (get_lift()&15)<<4; Write2(ptr, data2); out->write((char*)buf, sizeof(buf)); // Write scheduled usecode. Game_map::write_scheduled(out, this); } // Get size of IREG. Returns -1 if can't write to buffer int Egg_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gumpman->find_gump(this) || Usecode_script::find(this)) return -1; return 13; } /* * Create from IREG data. */ Animated_egg_object::Animated_egg_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned short itype, unsigned char prob, short d1, short d2 ) : Egg_object(shapenum, framenum, tilex, tiley, lft, itype, prob, d1, d2) { animator = new Frame_animator(this); } /* * Create for fields. */ Animated_egg_object::Animated_egg_object ( int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, unsigned char ty ) : Egg_object(shapenum, framenum, tilex, tiley, lft, ty) { int recycle = 0; // Frame to begin new cycles after 1st. switch (type) { case poison_field: recycle = 6; break; case sleep_field: recycle = 1; break; case fire_field: recycle = 8; break; case caltrops_field: animator = 0; return; // This doesn't get animated. } animator = new Field_frame_animator(this, recycle); } /* * Delete. */ Animated_egg_object::~Animated_egg_object() { delete animator; } /* * Render. */ void Animated_egg_object::paint ( ) { if (animator) animator->want_animation(); // Be sure animation is on. Ireg_game_object::paint(); // Always paint these. } /* * Run usecode when double-clicked or when activated by proximity. */ void Animated_egg_object::activate ( int event ) { Egg_object::activate(event); flags &= ~(1 << (int) hatched); // Moongate: reset always. } /* * Stop animation. */ void Animated_egg_object::stop_animation ( ) { delete animator; animator = 0; } /* * Apply field. * * Output: True to delete field. */ bool Field_object::field_effect ( Actor *actor ) { bool del = false; // Only delete poison, sleep fields. switch (type) { case poison_field: if (rand()%2) { actor->set_flag(Obj_flags::poisoned); del = true; } break; case sleep_field: if (rand()%2) { actor->set_flag(Obj_flags::asleep); del = true; } break; case fire_field: // Blue fire (serpent isle)? if (get_shapenum() == 561) { actor->reduce_health(5 + rand()%4); } else if (rand()%2) { actor->reduce_health(1); } // But no sleeping here. actor->clear_flag(Obj_flags::asleep); break; case caltrops_field: if (actor->get_property(Actor::intelligence)* (actor->get_flag(Obj_flags::might) ? 2 : 1) < rand()%40) { actor->reduce_health(2 + rand()%3); } return false; } if (!del) // Tell animator to keep checking. ((Field_frame_animator *) animator)->activated = true; return del; } /* * Run usecode when double-clicked or when activated by proximity. * (Generally, nothing will happen.) */ void Field_object::activate ( int event ) { // Field_frame_animator calls us with // event==0 to check for damage. if (event != Usecode_machine::npc_proximity) { Ireg_game_object::activate(event); return; } Actor_queue npcs; // Find all nearby NPC's. gwin->get_nearby_npcs(npcs); npcs.push(gwin->get_main_actor()); // Include Avatar. Rectangle eggfoot = get_footprint(); // Clear flag to check. ((Field_frame_animator *) animator)->activated = false; for (Actor_queue::const_iterator it = npcs.begin(); it != npcs.end(); ++it) { Actor *actor = *it; if (actor->is_dead() || Game_object::distance(actor) > 4) continue; if (actor->get_footprint().intersects(eggfoot)) Field_object::activate(actor); } } /* * Someone stepped on it. */ void Field_object::activate ( Game_object *obj, // Object (actor) that came near it. bool /* must */ // If 1, skip dice roll. ) { if (field_effect((Actor *) obj))// Apply field. remove_this(0); // Delete sleep/poison if applied. } /* * Write out. These are stored as normal game objects. */ void Field_object::write_ireg ( DataSource *out ) { Ireg_game_object::write_ireg(out); } // Get size of IREG. Returns -1 if can't write to buffer int Field_object::get_ireg_size() { return Ireg_game_object::get_ireg_size(); } /* * It's a Mirror */ Mirror_object::Mirror_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft) : Egg_object(shapenum, framenum, tilex, tiley, lft, Egg_object::mirror_object) { solid_area = 1; } void Mirror_object::activate(int event) { Ireg_game_object::activate(event); } void Mirror_object::activate(Game_object *obj, bool must) { // These are broken, so dont touch if ((get_framenum()%3) == 2) return; int wanted_frame = get_framenum()/3; wanted_frame *= 3; // Find upperleft or our area Tile_coord t = get_tile(); // To left or above? if (get_shapenum()==268) // Left { t.tx++; t.ty--; } else // Above { t.tx--; t.ty++; } // We just want to know if the area is blocked int nl = 0; if (Map_chunk::is_blocked(1, t.tz, t.tx, t.ty, 2, 2, nl, MOVE_WALK, 0)) { wanted_frame++; } // Only if it changed update the shape if (get_framenum()!=wanted_frame) change_frame(wanted_frame); } // Can it be activated? int Mirror_object::is_active(Game_object *obj, int tx, int ty, int tz, int from_tx, int from_ty) { // These are broken, so dont touch int frnum = get_framenum(); if (frnum%3 == 2) return 0; if (frnum >= 3 && GAME_BG) // Demon mirror in FOV. return 0; return 1; } // Set up active area. void Mirror_object::set_area() { // These are broken, so dont touch if ((get_framenum()%3) == 2) area = Rectangle(0, 0, 0, 0); Tile_coord t = get_tile(); // Get absolute tile coords. // To left or above? if (get_shapenum()==268) area = Rectangle(t.tx-1, t.ty-3, 6, 6); else area = Rectangle(t.tx-3 , t.ty-1, 6, 6); } void Mirror_object::paint() { Ireg_game_object::paint(); // Always paint these. } /* * Write out. These are stored as normal game objects. */ void Mirror_object::write_ireg(DataSource *out) { Ireg_game_object::write_ireg(out); } // Get size of IREG. Returns -1 if can't write to buffer int Mirror_object::get_ireg_size() { // TODO!!!!!!! return Ireg_game_object::get_ireg_size(); } exult-1.2/objs/spellbook.h0000644000175000001440000000457307575215735011323 /** ** Spellbook.h - Spellbook object. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 2000 The Exult Team. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_SPELLBOOK #define INCL_SPELLBOOK 1 #include "iregobjs.h" const int NREAGENTS = 11; // Total # reagents. /* * A spellbook: */ class Spellbook_object : public Ireg_game_object { // Reagents needed for each spell: static unsigned short bg_reagents[9*8], si_reagents[9*8]; unsigned short *reagents; // ->appropriate table. unsigned char circles[9]; // Spell-present flags for each circle. int bookmark; // Spell # that bookmark is on, or -1. public: friend class Bookmark_button; friend class Spellbook_gump; // Create from ireg. data. Spellbook_object(int shapenum, int framenum, unsigned int shapex, unsigned int shapey, unsigned int lft, unsigned char *c, unsigned char bmark); int add_spell(int spell); // Add a spell. bool has_ring(Actor *act); // Has ring-o-reagents? // Can we do this spell? bool can_do_spell(Actor *act, int spell); bool can_do_spell(Actor *act) // Can we do bookmarked spell? { return bookmark >= 0 ? can_do_spell(act, bookmark) : false; } // Do the spell. bool do_spell(Actor *act, int spell, bool can_do = false, bool in_combat = false); // Do bookmarked spell. bool do_spell(Actor *act, bool in_combat = false) { return bookmark >= 0 ? do_spell(act, bookmark, false, in_combat) : false; } static void execute_spell(Actor *act, int spell, bool in_combat = false); // Run usecode function. virtual void activate(int event = 1); // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. // Returns -1 if can't write to buffer virtual int get_ireg_size(); }; #endif exult-1.2/objs/Makefile.am0000644000175000001440000000145707510371633011177 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../pathfinder -I$(srcdir)/../files \ -I$(srcdir)/../server -I$(srcdir)/../gumps \ -I$(srcdir)/../audio -I$(srcdir)/../usecode $(SDL_CFLAGS) \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libobjs.la libobjs_la_SOURCES = \ animate.cc \ animate.h \ barge.cc \ barge.h \ chunks.cc \ chunks.h \ chunkter.cc \ chunkter.h \ citerate.h \ contain.cc \ contain.h \ egg.cc \ egg.h \ find_nearby.h \ flags.h \ iregobjs.cc \ iregobjs.h \ mappatch.cc \ mappatch.h \ objiter.h \ objiter.cc \ objlist.h \ objs.cc \ objs.h \ ordinfo.h \ spellbook.cc \ spellbook.h \ virstone.cc \ virstone.h \ jawbone.cc \ jawbone.h \ objnames.cc CLEANFILES = *~ exult-1.2/objs/Makefile.in0000644000175000001440000002714110061527065011203 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../pathfinder -I$(srcdir)/../files \ -I$(srcdir)/../server -I$(srcdir)/../gumps \ -I$(srcdir)/../audio -I$(srcdir)/../usecode $(SDL_CFLAGS) \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libobjs.la libobjs_la_SOURCES = \ animate.cc \ animate.h \ barge.cc \ barge.h \ chunks.cc \ chunks.h \ chunkter.cc \ chunkter.h \ citerate.h \ contain.cc \ contain.h \ egg.cc \ egg.h \ find_nearby.h \ flags.h \ iregobjs.cc \ iregobjs.h \ mappatch.cc \ mappatch.h \ objiter.h \ objiter.cc \ objlist.h \ objs.cc \ objs.h \ ordinfo.h \ spellbook.cc \ spellbook.h \ virstone.cc \ virstone.h \ jawbone.cc \ jawbone.h \ objnames.cc CLEANFILES = *~ subdir = objs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libobjs_la_LDFLAGS = libobjs_la_LIBADD = am_libobjs_la_OBJECTS = animate.lo barge.lo chunks.lo chunkter.lo \ contain.lo egg.lo iregobjs.lo mappatch.lo objiter.lo objs.lo \ spellbook.lo virstone.lo jawbone.lo objnames.lo libobjs_la_OBJECTS = $(am_libobjs_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/animate.Plo $(DEPDIR)/barge.Plo \ @AMDEP_TRUE@ $(DEPDIR)/chunks.Plo $(DEPDIR)/chunkter.Plo \ @AMDEP_TRUE@ $(DEPDIR)/contain.Plo $(DEPDIR)/egg.Plo \ @AMDEP_TRUE@ $(DEPDIR)/iregobjs.Plo $(DEPDIR)/jawbone.Plo \ @AMDEP_TRUE@ $(DEPDIR)/mappatch.Plo $(DEPDIR)/objiter.Plo \ @AMDEP_TRUE@ $(DEPDIR)/objnames.Plo $(DEPDIR)/objs.Plo \ @AMDEP_TRUE@ $(DEPDIR)/spellbook.Plo $(DEPDIR)/virstone.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libobjs_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libobjs_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu objs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libobjs.la: $(libobjs_la_OBJECTS) $(libobjs_la_DEPENDENCIES) $(CXXLINK) $(libobjs_la_LDFLAGS) $(libobjs_la_OBJECTS) $(libobjs_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/animate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/barge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/chunks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/chunkter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/contain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/egg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/iregobjs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/jawbone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mappatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objiter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objnames.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/spellbook.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/virstone.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/objs/ordinfo.h0000644000175000001440000000374607504206421010752 /** ** Ordinfo.h - Ordering information. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_ORDINFO #define INCL_ORDINFO 1 /* * Information about an object used during render-order comparison (lt()): */ class Ordering_info { public: Rectangle area; // Area (pixels) rel. to screen. Shape_info& info; // Info. about shape. int tx, ty, tz; // Absolute tile coords. int xs, ys, zs; // Tile dimensions. #if 1 /* For experimental compare(). */ int xleft, xright, ynear, yfar, zbot, ztop; #endif private: void init(const Game_object *obj) { Tile_coord t = obj->get_tile(); tx = t.tx; ty = t.ty; tz = t.tz; int frnum = obj->get_framenum(); xs = info.get_3d_xtiles(frnum); ys = info.get_3d_ytiles(frnum); zs = info.get_3d_height(); #if 1 /* For experimental compare(). */ xleft = tx - xs + 1; xright = tx; yfar = ty - ys + 1; ynear = ty; ztop = tz + zs - 1; zbot = tz; if (!zs) // Flat? zbot--; #endif } public: friend class Game_object; friend class Map_chunk; // Create from scratch. Ordering_info(Game_window *gwin, Game_object *obj) : area(gwin->get_shape_rect(obj)), info(obj->get_info()) { init(obj); } Ordering_info(Game_window *gwin, Game_object *obj, Rectangle& a) : area(a), info(obj->get_info()) { init(obj); } }; #endif exult-1.2/objs/chunks.h0000644000175000001440000002353207727014600010603 /** ** Chunks.h - Chunks (16x16 tiles) on the map. ** ** Written: 10/1/98 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CHUNKS_H #define CHUNKS_H #include "objlist.h" #include "exult_constants.h" #include "rect.h" #include "shapeid.h" #include "tiles.h" #include "vec.h" #include "chunkter.h" class Map_chunk; class Egg_object; class Game_object; class Npc_actor; class Image_buffer8; class Chunk_terrain; /* * Data cached for a chunk to speed up processing, but which doesn't need * to be saved to disk: */ class Chunk_cache : public Game_singletons { Map_chunk *obj_list; unsigned long blocked[256]; // For each tile, 2 bits for each lift // level for #objs blocking there. Egg_vector egg_objects; // ->eggs which influence this chunk. unsigned short eggs[256]; // Bit #i (0-14) set means that the // tile is within egg_object[i]'s // influence. Bit 15 means it's 1 or // more of // egg_objects[15-(num_eggs-1)]. Game_object_vector doors; // Keep special list of doors. friend class Map_chunk; Chunk_cache(); ~Chunk_cache(); int get_num_eggs() { return egg_objects.size(); } // Set/unset blocked region. void set_blocked(int startx, int starty, int endx, int endy, int lift, int ztiles, bool set); // Add/remove object. void update_object(Map_chunk *chunk, Game_object *obj, bool add); // Set area within egg's influence. void set_egged(Egg_object *egg, Rectangle& tiles, bool add); // Add egg. void update_egg(Map_chunk *chunk, Egg_object *egg, bool add); // Set up with chunk's data. void setup(Map_chunk *chunk); #if 0 /* OLD WAY. Goes away. */ // Set blocked tile's bits. void set_blocked_tile(int tx, int ty, int lift, int ztiles) { unsigned short val = (((1 << ztiles) - 1) << lift); unsigned short inter = blocked[ty*c_tiles_per_chunk + tx]&val; if (inter) intersects(tx, ty, inter); blocked[ty*c_tiles_per_chunk + tx] |= val; } // Clear blocked tile's bits. void clear_blocked_tile(int tx, int ty, int lift, int ztiles) { blocked[ty*c_tiles_per_chunk + tx] &= ~(((1 << ztiles) - 1) << lift); } #endif // Get highest lift blocked below a // given level for a desired tile. int get_highest_blocked(int lift, unsigned long tflags); int get_highest_blocked(int lift, int tx, int ty); int get_lowest_blocked(int lift, unsigned long tflags); int get_lowest_blocked(int lift, int tx, int ty); // Is a spot occupied? int is_blocked(int height, int lift, int tx, int ty, int& new_lift, const int move_flags, int max_drop = 1, int max_rise = -1); // Activate eggs nearby. void activate_eggs(Game_object *obj, Map_chunk *chunk, int tx, int ty, int tz, int from_tx, int from_ty, unsigned short eggbits, bool now); void activate_eggs(Game_object *obj, Map_chunk *chunk, int tx, int ty, int tz, int from_tx, int from_ty, bool now) { unsigned short eggbits = eggs[ (ty%c_tiles_per_chunk)*c_tiles_per_chunk + (tx%c_tiles_per_chunk)]; if (eggbits) activate_eggs(obj, chunk, tx, ty, tz, from_tx, from_ty, eggbits, now); } // Find door blocking given tile. Game_object *find_door(Tile_coord t); public: // Quick is blocked inline int is_blocked_fast(int tx, int ty, int lift) { return blocked[ty*c_tiles_per_chunk + tx] & (3 << (2*lift)); } }; /* * Game objects are stored in a list for each chunk, sorted from top-to- * bottom, left-to-right. */ class Map_chunk : public Game_singletons { Chunk_terrain *terrain; // Flat landscape tiles. Object_list objects; // ->first in list of all objs. 'Flat' // obs. (lift=0,ht=0) stored 1st. Game_object *first_nonflat; // ->first nonflat in 'objects'. // Counts of overlapping objects from // chunks below, to right. unsigned char from_below, from_right, from_below_right; unsigned char ice_dungeon; // For SI, chunk split into 4 quadrants unsigned char *dungeon_levels; // A 'dungeon' level value for each tile (4 bit). Chunk_cache *cache; // Data for chunks near player. unsigned char roof; // 1 if a roof present. // # light sources in chunk. unsigned char dungeon_lights, non_dungeon_lights; unsigned char cx, cy; // Absolute chunk coords. of this. void add_dungeon_levels(Rectangle& tiles, unsigned int lift); void add_dependencies(Game_object *newobj, class Ordering_info& newinfo); static Map_chunk *add_outside_dependencies(int cx, int cy, Game_object *newobj, class Ordering_info& newinfo); public: friend class Npc_actor; Map_chunk(int chunkx, int chunky); ~Map_chunk(); // Delete everything in chunk. Chunk_terrain *get_terrain() const { return terrain; } void set_terrain(Chunk_terrain *ter); void add(Game_object *obj); // Add an object. void add_egg(Egg_object *egg); // Add/remove an egg. void remove_egg(Egg_object *egg); void remove(Game_object *obj); // Remove an object. // Apply gravity over given area. static void gravity(Rectangle area, int lift); // Is there a roof? Returns height int is_roof(int tx, int ty, int lift); Object_list& get_objects() { return objects; } Game_object* get_first_nonflat() const { return first_nonflat; } int get_cx() const { return cx; } int get_cy() const { return cy; } int get_dungeon_lights() const // Get #lights. { return dungeon_lights; } int get_non_dungeon_lights() const { return non_dungeon_lights; } ShapeID get_flat(int tilex, int tiley) const { return terrain ? terrain->get_flat(tilex, tiley) : ShapeID(); } Image_buffer8 *get_rendered_flats() { return terrain ? terrain->get_rendered_flats() : 0; } // Get/create/setup cache. Chunk_cache *get_cache() const { return cache; } Chunk_cache *need_cache() { if (!cache) { cache = new Chunk_cache(); cache->setup(this); } return cache; } void setup_cache() { (void) need_cache(); } // Set/unset blocked region. void set_blocked(int startx, int starty, int endx, int endy, int lift, int ztiles, bool set) { need_cache()->set_blocked(startx, starty, endx, endy, lift, ztiles, set); } // Get highest lift blocked. int get_highest_blocked(int lift, int tx, int ty) { return need_cache()->get_highest_blocked(lift, tx, ty); } int get_lowest_blocked(int lift, int tx, int ty) { return need_cache()->get_lowest_blocked(lift, tx, ty); } // Is a spot occupied? int is_blocked(int height, int lift, int tx, int ty, int& new_lift, const int move_flags, int max_drop = 1, int max_rise = -1) { return cache->is_blocked(height, lift, tx, ty, new_lift, move_flags, max_drop, max_rise); } // Check range. static int is_blocked(int height, int lift, int startx, int starty, int xtiles, int ytiles, int& new_lift, const int move_flags, int max_drop, int max_rise = -1); // Check absolute tile. static int is_blocked(Tile_coord& tile, int height = 1, const int move_flags = MOVE_ALL_TERRAIN, int max_drop = 1, int max_rise = -1); // Check for > 1x1 object. static int is_blocked(int xtiles, int ytiles, int ztiles, Tile_coord from, Tile_coord& to, const int move_flags, int max_drop = 1, int max_rise = -1); enum Find_spot_where // For find_spot() below. { anywhere = 0, inside, // Must be inside. outside // Must be outside, }; // Find spot for an object. static Tile_coord find_spot(Tile_coord pos, int dist, int shapenum, int framenum, int max_drop = 0,int dir = -1, Find_spot_where where = anywhere); // For approaching 'pos' by an object: static Tile_coord find_spot(Tile_coord pos, int dist, Game_object *obj, int max_drop = 0, Find_spot_where where = anywhere); // Set area within egg's influence. void set_egged(Egg_object *egg, Rectangle& tiles, bool add) { need_cache()->set_egged(egg, tiles, add); } void activate_eggs(Game_object *obj, int tx, int ty, int tz, int from_tx, int from_ty, bool now = false) { need_cache()->activate_eggs(obj, this, tx, ty, tz, from_tx, from_ty, now);} // Find door blocking given tile. Game_object *find_door(Tile_coord t) { return need_cache()->find_door(t); } static int find_in_area(Game_object_vector& vec, Rectangle area, int shapenum, int framenum); // Use this when teleported in. static void try_all_eggs(Game_object *obj, int tx, int ty, int tz, int from_tx, int from_ty); void setup_dungeon_levels(); // Set up after IFIX objs. read. inline int has_dungeon() // Any tiles within dungeon? { return dungeon_levels != 0; } // NOTE: The following should only be // called if has_dungeon()==1. inline int is_dungeon(int tx, int ty) // Is object within dungeon? (returns height) { int tnum = ty*c_tiles_per_chunk + tx; return tnum%2? dungeon_levels[tnum/2] >> 4: dungeon_levels[tnum/2] & 0xF; } // Is the dungeon an ICE dungeon.NOTE: This is a // Hack and splits the chunk into 4 parts. Only if inline bool is_ice_dungeon(int tx, int ty) // all 4 are ice, will we have an ice dungeon { return ice_dungeon == 0x0F;//0 != ((ice_dungeon >> ( (tx>>3) + 2*(ty>>3) ) )&1); } // Kill the items and the cache void kill_cache(); // Get all objects and actors for use when writing memory cache. // returns size require to save int get_obj_actors(Game_object_vector &removes, Actor_vector &actors); }; #endif exult-1.2/objs/iregobjs.h0000644000175000001440000000671507724430452011124 /* * iregobjs.h - Ireg (moveable) game objects. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef IREGOBJS_H #define IREGOBJS_H 1 #include "exult_types.h" #include "objs.h" /* * A moveable game object (from 'ireg' files): */ class Ireg_game_object : public Game_object { Container_game_object *owner; // Container this is in, or 0. protected: unsigned flags:32; // 32 flags used in 'usecode'. unsigned flags2:32; // Another 32 flags used in 'usecode'. public: Ireg_game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0) : Game_object(shapenum, framenum, tilex, tiley, lft), owner(0), flags(0), flags2(0), lowlift(-1), highshape (-1) { } // Copy constructor. Ireg_game_object(const Ireg_game_object& obj2) : Game_object(obj2), owner(0), flags(0), flags2(0), lowlift(-1), highshape (-1) { } // Create fake entry. Ireg_game_object() : owner(0), flags(0), flags2(0), lowlift(-1), highshape (-1) { } virtual ~Ireg_game_object() { } void set_flags(uint32 f) // For initialization. { flags = f; } // Render. virtual void paint(); virtual void paint_terrain() { } // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); void move(Tile_coord t) { move(t.tx, t.ty, t.tz); } // Remove/delete this object. virtual void remove_this(int nodel = 0); virtual Container_game_object *get_owner() { return owner; } virtual void set_owner(Container_game_object *o) { owner = o; } virtual int is_dragable() const;// Can this be dragged? virtual void set_flag(int flag) { if (flag >= 0 && flag < 32) flags |= ((uint32) 1 << flag); else if (flag >= 32 && flag < 64) flags2 |= ((uint32) 1 << (flag-32)); } virtual void clear_flag(int flag) { if (flag >= 0 && flag < 32) flags &= ~((uint32) 1 << flag); else if (flag >= 32 && flag < 64) flags2 &= ~((uint32) 1 << (flag-32)); } virtual int get_flag(int flag) const { if (flag >= 0 && flag < 32) return flags & ((uint32) 1 << flag); else if (flag >= 32 && flag < 64) return flags2 & ((uint32) 1 << (flag-32)); return 0; } virtual void set_flag_recursively(int flag) { set_flag(flag); } uint32 get_flags() const { return flags; } uint32 get_flags2() const { return flags2; } // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); int lowlift; int highshape; virtual int get_high_shape() const { return highshape; }; virtual void set_high_shape(int s) { highshape = s;}; virtual int get_low_lift() const { return lowlift; }; virtual void set_low_lift(int l) { lowlift = l;}; }; #endif exult-1.2/objs/objs.h0000644000175000001440000003001007724430453010237 /* * objs.h - Game objects. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OBJS_H #define OBJS_H #include // STL string #include "exult_constants.h" #include "exult_types.h" #include "flags.h" #include "rect.h" #include "shapeid.h" #include "tqueue.h" #include "tiles.h" #include "vec.h" #include "objlist.h" class Actor; class Map_chunk; class Container_game_object; class Terrain_game_object; class Egg_object; class Barge_object; class Game_window; class Npc_actor; class PathFinder; class Rectangle; class Schedule; class Usecode_machine; class Vga_file; class DataSource; template class T_Object_list; /* * A game object is a shape from shapes.vga along with info. about its * position within its chunk. */ class Game_object : public ShapeID { protected: static Game_object *editing; // Obj. being edited by ExultStudio. unsigned char shape_pos; // (X,Y) of shape within chunk. unsigned char lift; // Raise by 4* this number. short quality; // Some sort of game attribute. private: Game_object *next, *prev; // ->next in chunk list or container. Game_object_vector dependencies;// Objects which must be painted before // this can be rendered. Game_object_vector dependors; // Objects which must be painted after. static unsigned char rotate[8]; // For getting rotated frame #. public: uint32 render_seq; // Render sequence #. protected: unsigned char cx, cy; // (Absolute) chunk coords., or if this // is in a container, coords. within // gump's rectangle. // Handle attack on an object. int attack_object(Actor *attacker, int weapon_shape, int ammo_shape); // Create from ifix record. Game_object(unsigned char *ifix) : ShapeID(ifix[2], ifix[3]), shape_pos(ifix[0]), lift(ifix[1] & 0xf), quality(0), cx(255), cy(255) { } public: friend class T_Object_list; friend class T_Object_iterator; friend class T_Flat_object_iterator; friend class T_Object_iterator_backwards; friend class Map_chunk; Game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0) : ShapeID(shapenum, framenum), shape_pos((tilex << 4) + tiley), lift(lft), quality(0), cx(255), cy(255) { } // Copy constructor. Game_object(const Game_object& obj2) : ShapeID(obj2), shape_pos(obj2.shape_pos), lift(obj2.lift), quality(obj2.quality), cx(obj2.cx), cy(obj2.cy) { } Game_object() : ShapeID() // Create fake entry. { } virtual ~Game_object() { } int get_tx() const // Get tile (0-15) within chunk. { return (shape_pos >> 4) & 0xf; } int get_ty() const { return shape_pos & 0xf; } int get_lift() const { return lift; } Tile_coord get_tile() const // Get location in abs. tiles. { return Tile_coord(cx*c_tiles_per_chunk + get_tx(), cy*c_tiles_per_chunk + get_ty(), lift); } // Get distance to another object. int distance(Game_object *o2) const { return get_tile().distance( o2->get_tile()); } // Get direction to another object. int get_direction(Game_object *o2) const; int get_direction(Tile_coord t2) const; Map_chunk *get_chunk(); // Get chunk this is in. int get_quality() const { return quality; } void set_quality(int q) { quality = q; } int get_quantity() const; // Like # of coins. virtual int get_obj_hp() const; // hitpoints for non-NPCs virtual void set_obj_hp(int hp); int get_volume() const; // Get space taken. // Add/remove to/from quantity. int modify_quantity(int delta, bool *del = 0); // Set shape coord. within chunk. void set_shape_pos(unsigned int shapex, unsigned int shapey) { shape_pos = (shapex << 4) + shapey; } void set_lift(int l) { lift = l; } Game_object *get_next() { return next; } Game_object *get_prev() { return prev; } // Compare for render order. static int compare(class Ordering_info& inf1, Game_object *obj2); int lt(Game_object& obj2); // Is this less than another in pos.? // Return chunk coords. int get_cx() const { return cx; } int get_cy() const { return cy; } void set_invalid() // Set to invalid position. { cx = cy = 255; } bool is_pos_invalid() const { return cx >= c_num_chunks || cy >= c_num_chunks; } void set_chunk(int newcx, int newcy) { cx = newcx; cy = newcy; } // Get frame for desired direction. int get_dir_framenum(int dir, int frnum) const { return (frnum&0xf) + rotate[dir]; } // Get it using current dir. int get_dir_framenum(int frnum) const { return (frnum&0xf) + (get_framenum()&(16 | 32)); } // Get direction (NPC) is facing. int get_dir_facing() const; // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); void move(Tile_coord t) { move(t.tx, t.ty, t.tz); } void change_frame(int frnum); // Change frame & set to repaint. // Swap positions. int swap_positions(Game_object *obj2); int get_dependency_count() // Get objs. to paint first. { return dependencies.size(); } Game_object *get_dependency(int i) { return dependencies[i]; } void clear_dependencies(); // Remove all dependencies. // Find nearby objects. #define HDR_DECLARE_FIND_NEARBY(decl_type) \ static int find_nearby(decl_type vec, Tile_coord pos, \ int shapenum, int delta, int mask, \ int qual = c_any_qual, int framenum = c_any_framenum) HDR_DECLARE_FIND_NEARBY(Egg_vector&); HDR_DECLARE_FIND_NEARBY(Actor_vector&); HDR_DECLARE_FIND_NEARBY(Game_object_vector&); #undef HDR_DECLARE_FIND_NEARBY int find_nearby_actors(Actor_vector& vec, int shapenum, int delta) const; int find_nearby_eggs(Egg_vector& vec, int shapenum, int delta, int qual = c_any_qual, int frnum = c_any_framenum) const; int find_nearby(Game_object_vector& vec, int shapenum, int delta, int mask, int qual = c_any_qual, int framenum = c_any_framenum) const; Game_object *find_closest(Game_object_vector& vec, int *shapenums, int num_shapes, int dist = 24); Game_object *find_closest(int *shapenums, int num_shapes, int dist = 24); Game_object *find_closest(int shapenum, int dist = 24) { return find_closest(&shapenum, 1, dist); } Rectangle get_footprint(); // Get tile footprint. bool blocks(Tile_coord tile); // Do we block a given tile? // Find object blocking given tile. static Game_object *find_blocking(Tile_coord tile); static Game_object *find_door(Tile_coord tile); int is_closed_door() const; // Checking for a closed door. Game_object *get_outermost(); // Get top 'owner' of this object. void say(const char *text); // Put text up by item. void say(int from, int to); // Show random msg. from 'text.flx'. // Render. virtual void paint(); void paint_outline(Pixel_colors pix); // Make this class abstract. virtual void paint_terrain() = 0; // Can this be clicked on? virtual int is_findable() { return 1; } // Run usecode function. virtual void activate(int event = 1); virtual bool edit(); // Edit in ExultStudio. // Saved from ExultStudio. static void update_from_studio(unsigned char *data, int datalen); virtual std::string get_name() const; // Remove/delete this object. virtual void remove_this(int nodel = 0); virtual Container_game_object *get_owner() { return 0; } virtual void set_owner(Container_game_object *o) { } static int get_weight(int shnum, int quant = 1); virtual int get_weight(); virtual int get_max_weight(); // Get max. weight allowed. virtual int is_dragable() const;// Can this be dragged? // Drop another onto this. virtual int drop(Game_object *obj); // Set/clear/get actor flag. virtual void set_flag(int flag) { } virtual void set_siflag(int flag) { } virtual void clear_siflag(int flag) { } virtual void clear_flag(int flag) { } virtual int get_flag(int flag) const { return 0; } virtual void set_flag_recursively(int flag) { } virtual int get_siflag(int flag) const { return 0; } virtual int get_type_flag(int flag) const { return 0; } virtual Actor *as_actor() { return 0; } virtual Npc_actor *as_npc() { return 0; } virtual Barge_object *as_barge() { return 0; } virtual Terrain_game_object *as_terrain() { return 0; } virtual Container_game_object *as_container() { return 0; } virtual Egg_object *as_egg() { return 0; } virtual int is_egg() const // An egg? { return 0; } // Count contained objs. virtual int count_objects(int shapenum, int qual = c_any_qual, int framenum = c_any_framenum) { return 0; } // Get contained objs. virtual int get_objects(Game_object_vector& vec, int shapenum, int qual, int framenum) { return 0; } // Add an object. virtual bool add(Game_object *obj, bool dont_check = false, bool combine = false); // Add to NPC 'ready' spot. virtual int add_readied(Game_object *obj, int index, int dont_check = 0, int force_pos = 0) { return add(obj, dont_check!=0); } virtual int add_quantity(int delta, int shapenum, int qual = c_any_qual, int framenum = c_any_framenum, int dontcreate = 0) { return delta; } virtual int create_quantity(int delta, int shapenum, int qual, int framenum, bool temporary = false) { return delta; } virtual int remove_quantity(int delta, int shapenum, int qual, int framenum) { return delta; } virtual Game_object *find_item(int shapenum, int qual, int framenum) { return 0; } // Get coord. where this was placed. virtual Tile_coord get_original_tile_coord() const { return get_tile(); } // Move out of the way. virtual int move_aside(Actor *for_actor, int dir) { return 0; } // For now. // Get frame if rotated clockwise. virtual int get_rotated_frame(int quads); // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame) { return 0; } virtual int is_monster() { return 0; } // Under attack. virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0, int ammo_shape = 0); // Write out to IREG file. virtual void write_ireg(DataSource* out) { } // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size() { return 0; } // Write out IFIX, CHUNKS. virtual void write_ifix(DataSource* ifix) { } virtual void elements_read() // Called when all member items read. { } // Write common IREG data. void write_common_ireg(unsigned char *buf); virtual int get_live_npc_num() { return -1; } virtual void delete_contents() { } }; /* * Object from U7chunks. */ class Terrain_game_object : public Game_object { public: Terrain_game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0) : Game_object(shapenum, framenum, tilex, tiley, lft) { } virtual Terrain_game_object *as_terrain() { return this; } virtual void paint_terrain(); }; /* * Object from an IFIXxx file. */ class Ifix_game_object : public Game_object { public: // Create from ifix record. Ifix_game_object(unsigned char *ifix) : Game_object(ifix) { } Ifix_game_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0) : Game_object(shapenum, framenum, tilex, tiley, lft) { } // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); // Remove/delete this object. virtual void remove_this(int nodel = 0); virtual void paint_terrain() { } virtual void write_ifix(DataSource* ifix); }; #endif exult-1.2/objs/objs.cc0000644000175000001440000007311110054030576010376 /* * objs.cc - Game objects. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "objs.h" #include "chunks.h" #include "objiter.h" #include "egg.h" #include "gamewin.h" #include "gamemap.h" #include "actors.h" #include "ucmachine.h" #include "items.h" #include "dir.h" #include "ordinfo.h" #include "game.h" #include "Gump_manager.h" #include "effects.h" #include "databuf.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #include // STL function things #ifdef USE_EXULTSTUDIO #include "cheat.h" #include "server.h" #include "objserial.h" #include "servemsg.h" #endif #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::memcpy; using std::memset; using std::rand; using std::ostream; using std::strchr; using std::string; #endif // Offset to each neighbor, dir=0-7. short Tile_coord::neighbors[16] = {0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0, -1,-1 }; Game_object *Game_object::editing = 0; // Bit 5=S, Bit6=reflect. on diag. unsigned char Game_object::rotate[8] = { 0, 0, 48, 48, 16, 16, 32, 32}; extern bool combat_trace; /* * Get direction to another object. */ int Game_object::get_direction ( Game_object *o2 ) const { Tile_coord t1 = get_tile(); Tile_coord t2 = o2->get_tile(); // Treat as cartesian coords. return (int) Get_direction(t1.ty - t2.ty, t2.tx - t1.tx); } /* * Get direction to a given tile. */ int Game_object::get_direction ( Tile_coord t2 ) const { Tile_coord t1 = get_tile(); // Treat as cartesian coords. return (int) Get_direction(t1.ty - t2.ty, t2.tx - t1.tx); } /* * Get chunk this is in. */ Map_chunk *Game_object::get_chunk ( ) { return gmap->get_chunk(cx, cy); } /* * Does a given shape come in quantity. */ static int Has_quantity ( int shnum // Shape number. ) { Shape_info& info = ShapeID::get_info(shnum); return info.has_quantity(); } static int Has_hitpoints(int shnum) { Shape_info& info = ShapeID::get_info(shnum); return ((info.get_shape_class() == Shape_info::has_hp) || (info.get_shape_class() == Shape_info::container)); // containers have hitpoints too ('resistance') } const int MAX_QUANTITY = 100; // Highest quantity possible. /* * Get the quantity. */ int Game_object::get_quantity ( ) const { int shnum = get_shapenum(); if (Has_quantity(shnum)) { int qual = quality & 0x7f; return qual ? qual : 1; } else return 1; } int Game_object::get_obj_hp() const { int shnum = get_shapenum(); if (Has_hitpoints(shnum)) return quality; else return 0; } void Game_object::set_obj_hp(int hp) { int shnum = get_shapenum(); if (Has_hitpoints(shnum)) set_quality(hp); } /* * Get the volume. */ int Game_object::get_volume ( ) const { int vol = get_info().get_volume(); return vol; // I think U7 ignores quantity! } /* * Add or remove from object's 'quantity', and delete if it goes to 0. * Also, this sets the correct frame, even if delta == 0. * * Output: Delta decremented/incremented by # added/removed. * Container's volume_used field is updated. */ int Game_object::modify_quantity ( int delta, // >=0 to add, <0 to remove. bool *del // If !null, true ret'd if deleted. ) { if (del) *del = false; if (!Has_quantity(get_shapenum())) { // Can't do quantity here. if (delta > 0) return (delta); remove_this(); // Remove from container (or world). if (del) *del = true; return (delta + 1); } int quant = quality&0x7f; // Get current quality. if (!quant) quant = 1; // Might not be set. int newquant = quant + delta; if (delta >= 0) // Adding? { // Too much? if (newquant > MAX_QUANTITY) newquant = MAX_QUANTITY; } else if (newquant <= 0) // Subtracting. { remove_this(); // We're done for. if (del) *del = true; return (delta + quant); } int oldvol = get_volume(); // Get old volume used. quality = (char) newquant; // Store new value. int shapenum = get_shapenum(); // Set appropriate shape. int num_frames = get_num_frames(); int new_frame = newquant - 1; if (new_frame > 7) // Range is 0-7. new_frame = 7; if (shapenum == 565 || // Starbursts are special. shapenum == 636) // So are serpentine daggers. set_frame(0); // (Fixes messed-up games.) else if (shapenum != 842) // Leave reagants alone. // Guessing: Works for ammo, arrows. set_frame(num_frames == 32 ? 24 + new_frame : new_frame); Container_game_object *owner = get_owner(); if (owner) // Update owner's volume. owner->modify_volume_used(get_volume() - oldvol); return (delta - (newquant - quant)); } /* * Based on frame #, get direction (N, S, E, W, 0-7), this (generally an * NPC) is facing. */ int Game_object::get_dir_facing ( ) const { int reflect = get_framenum()&(16 | 32); switch (reflect) { case 0: return (int) north; case 48: return (int) east; case 16: return (int) south; case 32: default: return (int) west; } } /* * Move to a new absolute location. This should work even if the old * location is invalid (cx=cy=255). */ void Game_object::move ( int newtx, int newty, int newlift ) { // Figure new chunk. int newcx = newtx/c_tiles_per_chunk, newcy = newty/c_tiles_per_chunk; Map_chunk *newchunk = gmap->get_chunk_safely(newcx, newcy); if (!newchunk) return; // Bad loc. // Remove from old. Map_chunk *oldchunk = gmap->get_chunk_safely(cx, cy); if (oldchunk) { gwin->add_dirty(this); // Want to repaint old area. oldchunk->remove(this); } set_lift(newlift); // Set new values. shape_pos = ((newtx%c_tiles_per_chunk) << 4) + newty%c_tiles_per_chunk; newchunk->add(this); // Updates cx, cy. gwin->add_dirty(this); // And repaint new area. } /* * Change the frame and set to repaint areas. */ void Game_object::change_frame ( int frnum ) { gwin->add_dirty(this); // Set to repaint old area. set_frame(frnum); gwin->add_dirty(this); // Set to repaint new. } /* * Swap positions with another object (of the same footprint). * * Output: 1 if successful, else 0. */ int Game_object::swap_positions ( Game_object *obj2 ) { Shape_info& inf1 = get_info(); Shape_info& inf2 = obj2->get_info(); if (inf1.get_3d_xtiles() != inf2.get_3d_xtiles() || inf1.get_3d_ytiles() != inf2.get_3d_ytiles()) return 0; // Not the same size. Tile_coord p1 = get_tile(); Tile_coord p2 = obj2->get_tile(); remove_this(1); // Remove (but don't delete) each. set_invalid(); obj2->remove_this(1); obj2->set_invalid(); move(p2.tx, p2.ty, p2.tz); // Move to new locations. obj2->move(p1.tx, p1.ty, p1.tz); return (1); } /* * Remove all dependencies. */ void Game_object::clear_dependencies ( ) { Game_object_vector::const_iterator X; // First do those we depend on. for(X = dependencies.begin(); X != dependencies.end(); ++X ) (**X).dependors.remove(this); dependencies.clear(); // Now those who depend on us. for(X = dependors.begin(); X != dependors.end(); ++X ) (**X).dependencies.remove(this); dependors.clear(); } /* * Check an object in find_nearby() against the mask. * * Output: 1 if it passes. */ static int Check_mask ( Game_window *gwin, Game_object *obj, int mask ) { Shape_info& info = obj->get_info(); if ((mask&(4|8)) && // Both seem to be all NPC's. !info.is_npc()) return 0; Shape_info::Shape_class sclass = info.get_shape_class(); // Egg/barge? if ((sclass == Shape_info::hatchable || sclass == Shape_info::barge) && !(mask&0x10)) // Only accept if bit 16 set. return 0; if (info.is_transparent() && // Transparent? !(mask&0x80)) return 0; // Invisible object? if (obj->get_flag(Obj_flags::invisible)) if (!(mask&20)) // Guess: 0x20 == invisible. { if (!(mask&0x40)) // Guess: Inv. party member. return 0; if (!obj->get_flag(Obj_flags::in_party)) return 0; } return 1; // Passed all tests. } /* * Find objects near a given position. * * Output: # found, appended to vec. */ #define FN_VECTOR Egg_vector #define FN_OBJECT Egg_object #define FN_CAST ->as_egg() #include "find_nearby.h" int Game_object::find_nearby_eggs ( Egg_vector& vec, int shapenum, int delta, int qual, int frnum ) const { return Game_object::find_nearby (vec, get_tile(), shapenum, delta, 16, qual, frnum); } #define FN_VECTOR Actor_vector #define FN_OBJECT Actor #define FN_CAST ->as_actor() #include "find_nearby.h" int Game_object::find_nearby_actors ( Actor_vector& vec, int shapenum, int delta ) const { return Game_object::find_nearby(vec, get_tile(), shapenum, delta, 8, c_any_qual, c_any_framenum); } #define FN_VECTOR Game_object_vector #define FN_OBJECT Game_object #define FN_CAST #include "find_nearby.h" int Game_object::find_nearby ( Game_object_vector& vec, int shapenum, int delta, int mask, int qual, int framenum ) const { return Game_object::find_nearby(vec, get_tile(), shapenum, delta, mask, qual, framenum); } /* * For sorting closest to a given spot. */ class Object_closest_sorter { Tile_coord pos; // Pos. to get closest to. public: Object_closest_sorter(Tile_coord p) : pos(p) { } bool operator()(const Game_object *o1, const Game_object *o2) { Tile_coord t1 = o1->get_tile(), t2 = o2->get_tile(); return t1.distance(pos) < t2.distance(pos); } }; /* * Find the closest nearby objects with a shape in a given list. * * Output: ->closest object, or 0 if none found. */ Game_object *Game_object::find_closest ( Game_object_vector& vec, // List returned here, closest 1st. int *shapenums, // Shapes to look for. // c_any_shapenum=any NPC. int num_shapes, // Size of shapenums. int dist // Distance to look (tiles). ) { int i; for (i = 0; i < num_shapes; i++) // 0xb0 mask finds anything. find_nearby(vec, shapenums[i], dist, 0xb0); int cnt = vec.size(); if (!cnt) return (0); if (cnt > 1) std::sort(vec.begin(), vec.end(), Object_closest_sorter(get_tile())); return *(vec.begin()); } /* * Find the closest nearby object with a shape in a given list. * * Output: ->object, or 0 if none found. */ Game_object *Game_object::find_closest ( int *shapenums, // Shapes to look for. // c_any_shapenum=any NPC. int num_shapes, // Size of shapenums. int dist // Distance to look (tiles). ) { Game_object_vector vec; // Gets objects found. int i; for (i = 0; i < num_shapes; i++) // 0xb0 mask finds anything. find_nearby(vec, shapenums[i], dist, 0xb0); int cnt = vec.size(); if (!cnt) return (0); Game_object *closest = 0; // Get closest. int best_dist = 10000; // In tiles. // Get our location. Tile_coord loc = get_tile(); for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Game_object *obj = *it; int dist = obj->get_tile().distance(loc); if (dist < best_dist) { closest = obj; best_dist = dist; } } return (closest); } /* * Get footprint in absolute tiles. */ Rectangle Game_object::get_footprint ( ) { Shape_info& info = get_info(); // Get footprint. int frame = get_framenum(); int xtiles = info.get_3d_xtiles(frame); int ytiles = info.get_3d_ytiles(frame); Tile_coord t = get_tile(); Rectangle foot((t.tx - xtiles + 1 + c_num_tiles)%c_num_tiles, (t.ty - ytiles + 1 + c_num_tiles)%c_num_tiles, xtiles, ytiles); return foot; } /* * Does this object block a given tile? */ bool Game_object::blocks ( Tile_coord tile ) { Tile_coord t = get_tile(); if (t.tx < tile.tx || t.ty < tile.ty || t.tz > tile.tz) return false; // Out of range. Shape_info& info = get_info(); int ztiles = info.get_3d_height(); if (!ztiles || !info.is_solid()) return false; // Skip if not an obstacle. // Occupies desired tile? int frame = get_framenum(); if (tile.tx > t.tx - info.get_3d_xtiles(frame) && tile.ty > t.ty - info.get_3d_ytiles(frame) && tile.tz < t.tz + ztiles) return true; return false; } /* * Find the game object that's blocking a given tile. * * Output: ->object, or 0 if not found. */ Game_object *Game_object::find_blocking ( Tile_coord tile // Tile to check. ) { Map_chunk *chunk = gmap->get_chunk(tile.tx/c_tiles_per_chunk, tile.ty/c_tiles_per_chunk); Game_object *obj; Object_iterator next(chunk->get_objects()); while ((obj = next.get_next()) != 0) if (obj->blocks(tile)) return obj; return (0); } /* * Find door blocking a given tile. * * Output: ->door, or 0 if not found. */ Game_object *Game_object::find_door ( Tile_coord tile ) { Map_chunk *chunk = gmap->get_chunk(tile.tx/c_tiles_per_chunk, tile.ty/c_tiles_per_chunk); return chunk->find_door(tile); } /* * Is this a closed door? */ int Game_object::is_closed_door ( ) const { Shape_info& info = get_info(); if (!info.is_door()) return 0; // Get door's footprint. int xtiles = info.get_3d_xtiles(), ytiles = info.get_3d_ytiles(); // Get its location. Tile_coord doortile = get_tile(); Tile_coord before, after; // Want tiles to both sides. if (xtiles > ytiles) // Horizontal footprint? { before = doortile + Tile_coord(-xtiles, 0, 0); after = doortile + Tile_coord(1, 0, 0); } else // Vertical footprint. { before = doortile + Tile_coord(0, -ytiles, 0); after = doortile + Tile_coord(0, 1, 0); } // Should be blocked before/after. return (Map_chunk::is_blocked(before) && Map_chunk::is_blocked(after)); } /* * Get the topmost owner of this object. * * Output: ->topmost owner, or the object itself. */ Game_object *Game_object::get_outermost ( ) { Game_object *top = this; Game_object *above; while ((above = top->get_owner()) != 0) top = above; return top; } /* * Show text by the object on the screen. */ void Game_object::say ( const char *text ) { eman->add_text(text, this); } /* * Show a random string from 'text.flx' by the object. */ void Game_object::say ( int from, int to // Range (inclusive). ) { if (from > to) return; int offset = rand()%(to - from + 1); if (from + offset < num_item_names) say(item_names[from + offset]); } /* * Paint at given spot in world. */ void Game_object::paint ( ) { int x, y; gwin->get_shape_location(this, x, y); paint_shape(x, y); } /* * Paint outline. */ void Game_object::paint_outline ( Pixel_colors pix // Color to use. ) { int x, y; gwin->get_shape_location(this, x, y); ShapeID::paint_outline(x, y, pix); } /* * Run usecode when double-clicked. */ void Game_object::activate ( int event ) { if (edit()) return; // Map-editing. int usefun = get_shapenum(); // Serpent Isle spell scrolls: if (usefun == 0x2cb && Game::get_game_type() == SERPENT_ISLE) { gumpman->add_gump(this, 65); return; } // !!!Special case: books if (usefun == 0x282 && get_quality() >= 100 && get_quality() < 180) usefun = 0x638; else if (usefun == 0x282 && get_quality() >= 180 && Game::get_game_type() == SERPENT_ISLE ) usefun = 0x63b; else if (usefun == 0x2c1 && get_quality() >= 213 && Game::get_game_type() == SERPENT_ISLE ) usefun = 0x62a; ucmachine->call_usecode(usefun, this, (Usecode_machine::Usecode_events) event); } /* * Edit in ExultStudio. */ bool Game_object::edit ( ) { #ifdef USE_EXULTSTUDIO if (client_socket >= 0 && // Talking to ExultStudio? cheat.in_map_editor()) { editing = 0; Tile_coord t = get_tile(); unsigned long addr = (unsigned long) this; std::string name = get_name(); if (Object_out(client_socket, Exult_server::obj, addr, t.tx, t.ty, t.tz, get_shapenum(), get_framenum(), get_quality(), name) != -1) { cout << "Sent object data to ExultStudio" << endl; editing = this; } else cout << "Error sending object to ExultStudio" <add_dirty(obj); obj->set_shape(shape, frame); gwin->add_dirty(obj); obj->set_quality(quality); // See if it moved. Tile_coord oldt = obj->get_tile(); if (oldt.tx != tx || oldt.ty != ty || oldt.tz != tz) obj->move(tx, ty, tz); cout << "Object updated" << endl; #endif } /* * Remove an object from the world. * The object is deleted. */ void Game_object::remove_this ( int nodel // 1 to not delete. ) { Map_chunk *chunk = gmap->get_chunk_safely(cx, cy); if (chunk) chunk->remove(this); if (!nodel) gwin->delete_object(this); } /* * Can this be dragged? */ int Game_object::is_dragable ( ) const { return (0); // Default is 'no'. } /* * Static method to get shape's weight in 1/10 stones. 0 means infinite. */ int Game_object::get_weight ( int shnum, // Shape #, int quant // Quantity. ) { int wt = quant * ShapeID::get_info(shnum).get_weight(); // Special case: reagents, coins. if (shnum == 842 || shnum == 644 || (Game::get_game_type() == SERPENT_ISLE && // Monetari/guilders/filari: (shnum == 951 || shnum == 952 || shnum == 948))) { wt /= 10; if (wt <= 0) wt = 1; } if (Has_quantity(shnum)) if (wt <= 0) wt = 1; return wt; } /* * Get weight of object in 1/10 stones. */ int Game_object::get_weight ( ) { return get_weight(get_shapenum(), get_quantity()); } /* * Get maximum weight in stones that can be held. * * Output: Max. allowed, or 0 if no limit (i.e., not carried by an NPC). */ int Game_object::get_max_weight ( ) { // Looking outwards for NPC. Container_game_object *own = get_owner(); return own ? own->get_max_weight() : 0; } /* * Add an object to this one by combining. * * Output: 1, meaning object is completely combined to this. Obj. is * deleted in this case. * 0 otherwise, although obj's quantity may be * reduced if combine==true. */ bool Game_object::add ( Game_object *obj, bool dont_check, // 1 to skip volume/recursion check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { return combine ? drop(obj)!=0 : false; } /* * Drop another onto this. * * Output: 0 to reject, 1 to accept. */ int Game_object::drop ( Game_object *obj // This may be deleted. ) { int shapenum = get_shapenum(); // It's possible if shapes match. if (obj->get_shapenum() != shapenum || !Has_quantity(shapenum) || // ++++Really should use // Get_combine_info in contain.cc // Reagents are a special case. (shapenum == 842 && get_framenum() != obj->get_framenum())) return (0); int objq = obj->get_quantity(); int total_quant = get_quantity() + objq; if (total_quant > MAX_QUANTITY) // Too much? return (0); modify_quantity(objq); // Add to our quantity. obj->remove_this(); // It's been used up. return (1); } //#define DEBUGLT #ifdef DEBUGLT static int rx1 = -1, ry1 = -1, rx2 = -1, ry2 = -1; static void Debug_lt ( int tx1, int ty1, // 1st coord. int tx2, int ty2 // 2nd coord. ) { if (tx1 == rx1 && ty1 == ry1) { if (tx2 == rx2 && ty2 == ry2) cout << "Debug_lt" << endl; } } #endif /* * Compare ranges along a given dimension. */ inline void Compare_ranges ( int from1, int to1, // First object's range. int from2, int to2, // Second object's range. // Returns: int& cmp, // -1 if 1st < 2nd, 1 if 1st > 2nd, // 0 if equal. bool& overlap // true returned if they overlap. ) { if (to1 < from2) { overlap = false; cmp = -1; } else if (to2 < from1) { overlap = false; cmp = 1; } else // X's overlap. { overlap = true; if (from1 < from2) cmp = -1; else if (from1 > from2) cmp = 1; else if (to1 - from1 < to2 - from2) cmp = 1; else if (to1 - from1 > to2 - from2) cmp = -1; else cmp = 0; } } /* * Compare two objects. * * Output: -1 if 1st < 2nd, 0 if dont_care, 1 if 1st > 2nd. */ int Game_object::compare ( Ordering_info& inf1, // Info. for object 1. Game_object *obj2 ) { // See if there's no overlap. Rectangle r2 = gwin->get_shape_rect(obj2); if (!inf1.area.intersects(r2)) return (0); // No overlap on screen. Ordering_info inf2(gwin, obj2, r2); #ifdef DEBUGLT Debug_lt(inf1.tx, inf1.ty, inf2.tx, inf2.ty); #endif int xcmp, ycmp, zcmp; // Comparisons for a given dimension: // -1 if o1o2. bool xover, yover, zover; // True if dim's overlap. Compare_ranges(inf1.xleft, inf1.xright, inf2.xleft, inf2.xright, xcmp, xover); Compare_ranges(inf1.yfar, inf1.ynear, inf2.yfar, inf2.ynear, ycmp, yover); Compare_ranges(inf1.zbot, inf1.ztop, inf2.zbot, inf2.ztop, zcmp, zover); if (!xcmp && !ycmp && !zcmp) // Same space? // Paint biggest area sec. (Fixes // plaque at Penumbra's.) return (inf1.area.w < inf2.area.w && inf1.area.h < inf2.area.h) ? -1 : (inf1.area.w > inf2.area.w && inf1.area.h > inf2.area.h) ? 1 : 0; // return 0; // Equal. if (xover & yover & zover) // Complete overlap? if (!inf1.zs) // Flat one is always drawn first. return !inf2.zs ? 0 : -1; else if (!inf2.zs) return 1; if (xcmp >= 0 && ycmp >= 0 && zcmp >= 0) return 1; // GTE in all dimensions. if (xcmp <= 0 && ycmp <= 0 && zcmp <= 0) return -1; // LTE in all dimensions. if (yover) // Y's overlap. { if (xover) // X's too? return zcmp; else if (zover) // Y's and Z's? return xcmp; // Just Y's overlap. else if (!zcmp) // Z's equal? return xcmp; else // See if X and Z dirs. agree. if (xcmp == zcmp) return xcmp; #if 1 /* Woohoo! Seems to work without messing up N. Trinsic gate. */ // Experiment: Fixes Trinsic mayor // statue-through-roof. else if (inf1.ztop/5 < inf2.zbot/5 && inf2.info.occludes()) return -1; // A floor above/below. else if (inf2.ztop/5 < inf1.zbot/5 && inf1.info.occludes()) return 1; #endif else return 0; } else if (xover) // X's overlap. { if (zover) // X's and Z's? return ycmp; else if (!zcmp) // Z's equal? return ycmp; else return ycmp == zcmp ? ycmp : 0; } // Neither X nor Y overlap. else if (xcmp == -1) // o1 X before o2 X? { if (ycmp == -1) // o1 Y before o2 Y? // If Z agrees or overlaps, it's LT. return (zover || zcmp <= 0) ? -1 : 0; } else if (ycmp == 1) // o1 Y after o2 Y? if (zover || zcmp >= 0) return 1; #if 1 /* So far, this seems to work without causing problems: */ // Experiment: Fixes Brit. museum // statue-through-roof. else if (inf1.ztop/5 < inf2.zbot/5) return -1; // A floor above. else #endif return 0; return 0; } /* * Should this object be rendered before obj2? * NOTE: This older interface isn't as efficient. * * Output: 1 if so, 0 if not, -1 if cannot compare. */ int Game_object::lt ( Game_object& obj2 ) { Ordering_info ord(gwin, this); int cmp = compare(ord, &obj2); return cmp == -1 ? 1 : cmp == 1 ? 0 : -1; } /* * Get frame if rotated 1, 2, or 3 quadrants clockwise. This is to * support barges (ship, cart, flying carpet). */ int Game_object::get_rotated_frame ( int quads // 1=90, 2=180, 3=270. ) { int curframe = get_framenum(); int shapenum = get_shapenum(); Shape_info& info = get_info(); if (shapenum == 292) // Seat is a special case. { int dir = curframe%4; // Current dir (0-3). return (curframe - dir) + (dir + quads)%4; } else if (info.is_barge_part()) // Piece of a barge? switch (quads) { case 1: return (curframe^32)^((curframe&32) ? 3 : 1); case 2: return curframe^2; case 3: return (curframe^32)^((curframe&32) ? 1 : 3); default: return curframe; } else // Reflect. Bit 32==horizontal. return curframe ^ ((quads%2)<<5); } /* * Figure attack points against an object, and also run weapon's usecode. */ int Game_object::attack_object ( Actor *attacker, int weapon_shape, // Weapon shape, or 0 to use readied. int ammo_shape ) { int wpoints = 0; Weapon_info *winf; if (weapon_shape > 0) winf = ShapeID::get_info(weapon_shape).get_weapon_info(); else if (ammo_shape > 0) // Not sure about all this... winf = ShapeID::get_info(ammo_shape).get_weapon_info(); else winf = attacker->get_weapon(wpoints); int usefun; // Run usecode if present. if (winf && (usefun = winf->get_usecode()) != 0) ucmachine->call_usecode(usefun, this, Usecode_machine::weapon); if (!wpoints && winf) wpoints = winf->get_damage(); if (!wpoints) // Telekenesis should NOT destroy! return 0; if (attacker) wpoints += attacker->get_level() + attacker->get_effective_prop((int) Actor::strength); return wpoints; } /* * Being attacked. * * Output: 0 if destroyed, else object itself. */ Game_object *Game_object::attacked ( Actor *attacker, int weapon_shape, // Weapon shape, or 0 to use readied, // or -weapon shape if explosion. int ammo_shape ) { if (weapon_shape < 0) // We ignore this flag. weapon_shape = -weapon_shape; int wpoints = attack_object(attacker, weapon_shape, ammo_shape); int shnum = get_shapenum(); int frnum = get_framenum(); int hp = get_obj_hp(); // Returns 0 if doesn't have HP's or is // indestructible, if (!hp) { // with exceptions: // some special cases // guessing these don't have hitpoints by default because // doors need their 'quality' field for something else if (shnum == 432 || shnum == 433) // doors { if (get_quality()==0 || weapon_shape==704) // only 'normal' doors (or powderkeg) if (frnum != 3 && frnum < 7) // no magic-locked or steel doors hp = 6; } else if (shnum == 270 || shnum == 376) // more doors { if (get_quality()==0 || weapon_shape==704) // only 'normal' doors (or powderkeg) if (frnum < 3 || (frnum >= 8 && frnum <= 10) || (frnum >= 16 && frnum <= 18)) // no magic or steel doors hp = 6; } // Serpent statue at end of SI: else if (shnum == 743 && Game::get_game_type() == SERPENT_ISLE) hp = 1; else if (shnum == 704 && weapon_shape == 704) { // Powder keg... // cause chain reaction // marked already detonating powderkegs with quality if (get_quality()==0) { Tile_coord pos = get_tile(); eman->add_effect( new Explosion_effect(pos, this)); } } // Arrow hitting practice targt? else if (shnum == 735 && ammo_shape == 722) { int newframe = !frnum ? (3*(rand()%8) + 1) : ((frnum%3) != 0 ? frnum + 1 : frnum); change_frame(newframe); } #if 0 else if (shnum == 522 && frnum < 2) { // locked normal chest if (get_quality() == 0 || get_quality() == 255) hp = 6; } #endif } string name = ""; if (attacker) name = attacker->get_name(); if (hp == 0) { // indestructible if (combat_trace) { cout << name << " attacks " << get_name() << ". No effect." << endl; } return this; } if (combat_trace) { cout << name << " hits " << get_name() << " for " << wpoints << " hit points, leaving " << hp - wpoints << " remaining" << endl; } if (wpoints >= hp) { // object destroyed eman->remove_text_effect(this); ucmachine->call_usecode(0x626, this, Usecode_machine::weapon); return 0; } else { set_obj_hp(hp - wpoints); return this; } } /* * Write the common IREG data for an entry. */ void Game_object::write_common_ireg ( unsigned char *buf // 4-byte buffer to be filled. ) { // Coords: buf[0] = ((get_cx()%16) << 4) | get_tx(); buf[1] = ((get_cy()%16) << 4) | get_ty(); int shapenum = get_shapenum(), framenum = get_framenum(); buf[2] = shapenum&0xff; buf[3] = ((shapenum>>8)&3) | (framenum<<2); } /* * Paint terrain objects only. */ void Terrain_game_object::paint_terrain ( ) { paint(); } /* * Move to a new absolute location. This should work even if the old * location is invalid (cx=cy=255). */ void Ifix_game_object::move ( int newtx, int newty, int newlift ) { Game_object::move(newtx, newty, newlift); // Mark superchunk as 'modified'. int cx = get_cx(), cy = get_cy(); if (cx >= 0 && cx < c_num_chunks && cy >= 0 && cy < c_num_chunks) gmap->set_ifix_modified(cx, cy); } /* * Remove an object from the world. * The object is deleted. */ void Ifix_game_object::remove_this ( int nodel // 1 to not delete. ) { // Mark superchunk as 'modified'. int cx = get_cx(), cy = get_cy(); if (cx >= 0 && cx < c_num_chunks && cy >= 0 && cy < c_num_chunks) gmap->set_ifix_modified(cx, cy); Game_object::remove_this(nodel); } /* * Write out an IFIX object. */ void Ifix_game_object::write_ifix ( DataSource *ifix // Where to write. ) { unsigned char buf[4]; buf[0] = shape_pos; buf[1] = lift; int shapenum = get_shapenum(), framenum = get_framenum(); buf[2] = shapenum&0xff; buf[3] = ((shapenum>>8)&3) | (framenum<<2); ifix->write((char*)buf, sizeof(buf)); } exult-1.2/objs/mappatch.h0000644000175000001440000000502607365611341011106 /** ** Mappatch.h - Patches to the game map. ** ** Written: 10-18-2001 **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_MAPPATCH #define INCL_MAPPATCH 1 #include #include #include "tiles.h" class Game_object; /* * Specify an object by location, shape, etc. */ class Object_spec { public: Tile_coord loc; // Where it is. int shapenum; // Shape #, or -359 for 'dont care'. int framenum; // Frame #, or -359. int quality; // Quality, or -359. Object_spec(Tile_coord t, int shnum = c_any_shapenum, int frnum = c_any_framenum, int qual = c_any_qual) : loc(t), shapenum(shnum), framenum(frnum), quality(qual) { } }; /* * Base class for map patches: */ class Map_patch { Object_spec spec; // Specifies object to modify. public: friend class Map_patch_collection; Map_patch(Object_spec s) : spec(s) { } Game_object *find(); // Find matching object. virtual bool apply() = 0; // Perform action. }; // Sigh, this is needed to prevent compiler error with MSVC typedef std::list Map_patch_list; typedef std::map Map_patch_map; /* * Remove an object. */ class Map_patch_remove : public Map_patch { bool all; // Delete all matching. public: Map_patch_remove(Object_spec s, bool a = false) : Map_patch(s) { } virtual bool apply(); // Perform action. }; /* * Move/modify an object. */ class Map_patch_modify : public Map_patch { Object_spec mod; // Modification. public: Map_patch_modify(Object_spec s, Object_spec m) : Map_patch(s), mod(m) { } virtual bool apply(); // Perform action. }; /* * Here's a collection of patches, organized by superchunk. */ class Map_patch_collection { Map_patch_map patches; public: Map_patch_collection() { } ~Map_patch_collection(); void add(Map_patch *p); // Add a patch. void apply(int schunk); // Apply for given superchunk. }; #endif exult-1.2/objs/citerate.h0000644000175000001440000000434207750361551011114 /** ** Citerate.h - Chunk iterator. ** ** Written: 7/13/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_CITERATE #define INCL_CITERATE 1 /* * Here's an iterator that takes a rectangle of tiles, and sequentially * returns the interesection of that rectangle with each chunk that it * touches. */ class Chunk_intersect_iterator { Rectangle tiles; // Original rect, shifted -cx, -cy. int start_tx; // Saves start of tx in tiles. // Chunk #'s covered: int startcx, stopcx, stopcy; int curcx, curcy; // Next chunk to return. public: Chunk_intersect_iterator(Rectangle t) : tiles(t), startcx(t.x/c_tiles_per_chunk), stopcx(INCR_CHUNK((t.x + t.w - 1)/c_tiles_per_chunk)), stopcy(INCR_CHUNK((t.y + t.h - 1)/c_tiles_per_chunk)), curcy(t.y/c_tiles_per_chunk) { curcx = startcx; tiles.shift(-curcx*c_tiles_per_chunk,-curcy*c_tiles_per_chunk); start_tx = tiles.x; if (t.x < 0 || t.y < 0) { // Empty to begin with. curcx = stopcx; curcy = stopcy; } } // Intersect is ranged within chunk. int get_next(Rectangle& intersect, int& cx, int& cy) { if (curcx == stopcx) // End of row? if (curcy == stopcy) return (0); else { tiles.y -= c_tiles_per_chunk; tiles.x = start_tx; curcy = INCR_CHUNK(curcy); curcx = startcx; } Rectangle cr(0, 0, c_tiles_per_chunk, c_tiles_per_chunk); // Intersect given rect. with chunk. intersect = cr.intersect(tiles); cx = curcx; cy = curcy; curcx = INCR_CHUNK(curcx); tiles.x -= c_tiles_per_chunk; return (1); } }; #endif exult-1.2/objs/objnames.cc0000644000175000001440000004137010054030576011241 /* * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "objs.h" #include "game.h" #include "items.h" #include "gamewin.h" #include "actors.h" using std::string; #ifndef HAVE_SNPRINTF extern int snprintf(char *, size_t, const char *, /*args*/ ...); namespace std { using ::snprintf; } #else #endif #ifndef UNDER_CE using std::strchr; #endif /* * For objects that can have a quantity, the name is in the format: * %1/%2/%3/%4 * Where * %1 : singular prefix (e.g. "a") * %2 : main part of name * %3 : singular suffix * %4 : plural suffix (e.g. "s") */ /* * Extracts the first, second and third parts of the name string */ static void get_singular_name ( const char *name, // Raw name string from TEXT.FLX string& output_name // Output string ) { if(*name != '/') // Output the first part { do output_name += *name++; while(*name != '/' && *name != '\0'); if(*name == '\0') // should not happen { output_name = "?"; return; } // If there is a first part it is followed by a space output_name += ' '; } name++; // Output the second part while(*name != '/' && *name != '\0') output_name += *name++; if(*name == '\0') // should not happen { output_name = "?"; return; } name++; // Output the third part while(*name != '/' && *name != '\0') output_name += *name++; if(*name == '\0') // should not happen { output_name = "?"; return; } name++; } /* * Extracts the second and fourth parts of the name string */ static void get_plural_name ( const char *name, int quantity, string& output_name ) { char buf[20]; snprintf(buf, 20, "%d ", quantity); // Output the quantity output_name = buf; // Skip the first part while(*name != '/' && *name != '\0') name++; if(*name == '\0') // should not happen { output_name = "?"; return; } name++; // Output the second part while(*name != '/' && *name != '\0') output_name += *name++; if(*name == '\0') // should not happen { output_name = "?"; return; } name++; // Skip the third part while(*name != '/' && *name != '\0') name++; if(*name == '\0') // should not happen { output_name = "?"; return; } name++; while(*name != '\0') // Output the last part output_name += *name++; } /* * Returns the string to be displayed when the item is clicked on */ string Game_object::get_name ( ) const { int quantity; string display_name; int shnum = get_shapenum(); int frnum = get_framenum(); int qual = get_quality(); int index = -1; if (GAME_BG) { //TODO: yourself switch (shnum) // Some special cases! { case 0x34a: // Reagents index = 0x500 + frnum; break; case 0x3bb: // Amulets if (frnum < 3) index = 0x508 + frnum; else index = shnum; break; case 0x179: // Food items index = 0x50b + frnum; break; case 0x28a: // Sextants index = 0x52c - frnum; break; case 0x2a3: // Desk items index = 0x52d + frnum; break; case 0x390: // "Blood" if (frnum < 4) index = 0x390; else index = -1; break; default: index = shnum; break; } } else if (GAME_SI) { //TODO: yourself, misc. checks/fixes switch (shnum) // More special cases! { case 0x097: // wall if (frnum == 17) index = 0x681; // door else index = shnum; break; case 0x98: // wall if (frnum == 22) index = 0x681; // door else index = shnum; break; case 0x0b2: // Cloth maps if (frnum < 5 || GAME_SS) index = 0x596 + frnum; else index = shnum; // only SS has a description for frame 5 break; case 0x0d1: // Artifacts index = 0x5c0 + frnum; break; case 0xd2: // chicken coop if (frnum == 4) index = 0x680; // platform else index = shnum; break; case 0x0e3: // cloak if (frnum <= 4) index = 0x5ff + frnum; else index = shnum; break; case 0x0f3: // coffin if (frnum >= 7) index = 0x605; // stone bier else index = shnum; break; case 0x0f4: // Large skulls if (frnum < 2) index = 0x5d8 + frnum; else index = shnum; break; case 0x106: // Blackrock Serpents if (frnum < 4) index = 0x592 + frnum; else index = shnum; break; case 0x11a: // painting if (frnum >= 6 && frnum <= 10) index = 0x60c; // ruined painting else index = shnum; break; case 0x11d: // brush if (frnum == 6) index = 0x5fa; else index = shnum; break; case 0x11e: // drum if (frnum == 1 || frnum == 2) index = 0x669; // drumsticks else index = shnum; break; case 0x124: // seat if (frnum == 17 || frnum == 18 || frnum == 19 || frnum == 22) index = 0x5fc; else index = shnum; break; case 0x128: // Rings index = 0x5b8 + frnum; break; case 0x12c: // cooking utensil if (frnum <= 7) index = 0x636 + (frnum/2); else if (frnum >= 8 && frnum <= 23) index = 0x63a + (frnum%4); else if (frnum >= 24) index = 0x63e + (frnum%2); break; case 0x12f: if (frnum >= 10 && frnum <= 14) index = 0x60b; else index = shnum; break; case 0x135: // fallen tree if (frnum == 2) index = 0x635; // large skull else index = shnum; break; case 0x141: // reeds if (frnum == 11) index = 0x61c; // crucifix else index = shnum; break; case 0x14a: // serpent rune if (frnum < 8) index = 0x607; // stones else index = shnum; break; case 0x150: // light source index = 0x646 + frnum; break; case 0x152: // lit light source { if (num_item_names <= 0x657) break; string tmp = item_names[0x657]; // lit tmp += item_names[0x646 + frnum]; return tmp; } break; case 0x172: // floor if (frnum == 19) index = 0x60e; // wall else index = shnum; break; case 0x179: // Food items index = 0x510 + frnum; break; case 0x17a: // fence if (frnum == 3 || (frnum > 7 && frnum < 12)) index = 0x60e; // wall else index = shnum; break; case 0x17f: // magic helm if (frnum == 1) index = 0x614; // helm of courage else index = shnum; break; case 0x194: // food index = 0x640 + frnum; break; case 0x19f: // garbage if (frnum > 20 && frnum < 24) index = 0x60f; // skull else index = shnum; break; case 0x1ba: // fireplace if (frnum == 2) index = 0x620; // wooden post else index = shnum; break; case 0x1bd: // Soul prisms index = 0x56b + frnum; break; case 0x1c2: // Orbs index = 0x585 + frnum; break; case 0x1d3: // Magic plants index = 0x581 + frnum/2; break; case 0x1db: // wall of lights if (frnum == 10) index = 0x683; // wall else index = shnum; break; case 0x1df: // claw + gwani amulet index = 0x5f8 + frnum/2; break; case 0x1e3: // rug if (frnum >= 2) index = 0x608; // meditation mat else index = shnum; break; case 0x1f9: // magic lens if (frnum == 2) index = 0x615; // lens of translating else index = shnum; break; case 0x201: // floor if (frnum == 5) index = 0x60d; // bookshelf else index = shnum; break; case 0x206: // glass counter top if (frnum == 26) index = 0x682; // table else index = shnum; break; case 0x207: // Moon's Eye if (frnum == 1) index = 0x616; // crystal ball else index = shnum; break; case 0x21a: // fence if (frnum == 3 || (frnum > 7 && frnum < 12)) index = 0x60e; // wall else index = shnum; break; case 0x21e: // Crested Helmets index = 0x5a3 + frnum; break; case 0x220: // broken column if (frnum == 14) index = 0x611; // pillar of purity else index = shnum; break; case 0x241: // Nests if (frnum < 6) index = 0x5ab + frnum/3; else index = shnum; break; case 0x24b: // Boots index = 0x59c + frnum; break; case 0x268: // Bottles switch (frnum) { case 1: index = 0x5f2; // wine decanter break; case 9: index = 0x5f3; // fawnish ale break; case 16: index = 0x5f4; // ice wine break; case 17: index = 0x5f5; // vintage wine break; case 18: index = 0x5f6; // wineskin break; case 20: index = 0x5f7; // everlasting goblet break; default: index = shnum; } break; case 0x281: // key switch (frnum) { case 21: index = 0x630; // key of fire break; case 22: index = 0x631; // key of ice break; case 23: index = 0x62f; // blackrock key break; default: index = shnum; } break; case 0x288: // sleeping powder if (frnum >= 2) index = 0x65c - 2 + frnum; else index = shnum; break; case 0x289: // Artifacts index = 0x573 + frnum; break; case 0x28a: // Sextants index = 0x531 - frnum; break; case 0x290: // wine press if (frnum == 1) index = 0x634; // wine vat else index = shnum; break; case 0x2a1: // strange plant if (frnum > 8) index = 0x62c; // snowy plant else index = shnum; break; case 0x2a3: // Desk items index = 0x532 + frnum; break; case 0x2a5: // stockings if (frnum < 2) index = 0x62a + frnum; else index = shnum; break; case 0x2af: // pillar if (frnum == 11) index = 0x611; // pillar of purity else index = shnum; break; case 0x2b0: // serpent carving if (frnum > 1) index = 0x621 - 1 + (frnum/2); else index = shnum; break; case 0x2b4: // Lute if (frnum == 2) index = 0x5be; else index = shnum; break; case 0x2b5: // whistle if (frnum == 1) index = 0x617; // whistle else if (frnum == 4 || frnum == 5) index = 0x618; // bone flute else index = shnum; break; case 0x2b8: // bed if (frnum == 1) index = 0x5da; // stone bier else if (frnum == 2) index = 0x5db; // cot else if (frnum == 4) index = 0x5dc; // pallet else if (frnum == 5) index = 0x5dd; // fur pallet else index = shnum; break; case 0x2cd: // plate if (frnum == 9) index = 0x61a; // platter of replenishment else index = shnum; break; case 0x2ce: // pedestal if (frnum == 8) index = 0x619; // blackrock obelisk else index = shnum; break; case 0x2d7: // Dream Crystal if (frnum <= 1) index = 0x659; // dream crystal else if (frnum == 2) index = 0x65a; // mirror rock else if (frnum >= 3) index = 0x65b; // icy column break; case 0x2d8: // Force_Wall // TODO: CHECK if (frnum > 0) index = 0x683; // wall else index = shnum; break; case 0x2f4: // caltrops if (frnum == 2 || frnum == 3) index = 0x5fb; // broken glass else index = shnum; break; case 0x313: // lever if (frnum == 8 || frnum == 9) index = 0x613; // button else index = shnum; break; case 0x314: // switch if (frnum >= 6 && frnum <= 9) index = 0x613; // button else index = shnum; break; case 0x31f: // Body parts index = 0x5df + frnum; break; case 0x320: // chest if (frnum == 4 || frnum == 5) index = 0x5fd; else if (frnum == 6 || frnum == 7) index = 0x5fe; else index = shnum; break; case 0x32a: // Bucket if (frnum == 1 && qual >= 10 && qual <= 15) index = 0x55b + qual; else if (frnum == 2 && qual == 9) index = 0x55b + qual; else index = 0x55b + frnum; break; case 0x347: // Hourglass if (frnum == 1) index = 0x5bf; else index = shnum; break; case 0x34a: // Reagents index = 0x500 + frnum; break; case 0x35f: // kitchen items index = 0x66b + frnum; break; case 0x365: // wall if (frnum == 11) index = 0x610; // spirit wall else index = shnum; break; case 0x36c: // sliding door if (frnum >= 10 && frnum <= 14) index = 0x60b; // iris door else index = shnum; break; case 0x377: // More rings index = 0x5bc + frnum; break; case 0x37a: // table if (frnum == 6) index = 0x62e; // torture table else index = shnum; break; case 0x390: // blood if (frnum == 24) index = 0x5de; // acid else if (frnum < 4) index = 0x390; // blood else index = -1; break; case 0x392: // urn if (frnum <= 1) { // when frame = 0,1, the quality is an NPC num // the item name is then the name of that NPC + "'s ashes" // (quality == 0,255: 'urn of ashes') Actor* npc = gwin->get_npc(get_quality()); if (get_quality() > 0 && npc && !npc->is_unused()) { string tmp = npc->get_npc_name(); if (tmp != "" && num_item_names>0x65e) { tmp += item_names[0x65e]; // 's ashes return tmp; } } index = 0x632; // urn with ashes } else if (frnum == 2) index = 0x633; // pot of unguent else index = shnum; break; case 0x397: // bookshelf if (frnum == 6) index = 0x60a; // slate mantle else index = shnum; break; case 0x39f: // serpent slot if (frnum >= 4 && frnum <= 7) index = 0x61e; // slotted serpent else index = shnum; break; case 0x3a7: // sliding door if (frnum == 2) index = 0x60b; // iris door else index = shnum; break; case 0x3a8: // sliding door if (frnum == 2) index = 0x60b; // iris door else index = shnum; break; case 0x3b0: // pot if (frnum == 5) index = 0x61b; // cuspidor else index = shnum; break; case 0x3bb: // Amulets index = 0x5ae + frnum; break; case 0x3d1: // fur pelt if (frnum == 0 || frnum == 8) index = 0x61f; // leopard rug else index = shnum; break; case 0x3e5: // spent light source { if (num_item_names <= 0x658) break; string tmp = item_names[0x658]; // spent tmp += item_names[0x646 + frnum]; return tmp; } break; case 0x3e6: // statue if (frnum <= 3) index = 0x628 + (frnum/2); else index = shnum; break; case 0x3e7: // plant index = 0x65f + frnum; break; case 0x3ea: // table if (frnum == 1) index = 0x62d; // embalming table else index = shnum; break; case 0x3ec: // Helmets index = 0x5a6 + frnum; break; case 0x3f3: // Beds if (frnum == 1) index = 0x5da; // stone bier else if (frnum == 2) index = 0x5db; // cot else if (frnum == 4) index = 0x5dc; // pallet else if (frnum == 5) index = 0x5dd; // fur pallet else index = shnum; break; case 0x3f8: // floor if (frnum == 20 || frnum == 21) index = 0x623; // symbol of balance else if (frnum == 22) index = 0x624; // symbol of order else if (frnum == 23) index = 0x625; // symbol of chaos else index = shnum; break; default: index = shnum; break; } // no Silver Seed? if (!GAME_SS) { if (index >= 0x605) { index -= 11; } else if (index >= 0x5bc) { index -= 10; } else if (index >= 0x5b8) { index -= 9; } else if (index >= 0x59c) { index -= 8; } else if (index >= 0x592) { index -= 7; } else if (index >= 0x581) { index -= 2; } } } else { index = shnum; } const char *name = (index >= 0 && index < num_item_names) ? item_names[index] : 0; if(name == 0) { return ""; // return "?"; } if (ShapeID::get_info(shnum).has_quantity()) quantity = quality & 0x7f; else quantity = 1; // If there are no slashes then it is simpler if(strchr(name, '/') == 0) { if(quantity <= 1) display_name = name; else { char buf[50]; snprintf(buf, 50, "%d %s", quantity, name); display_name = buf; } } else if(quantity <= 1) // quantity might be zero? get_singular_name(name, display_name); else get_plural_name(name, quantity, display_name); return display_name; } exult-1.2/objs/barge.h0000644000175000001440000000775407767762766010433 /** ** Barge.h - Ships, carts, flying-carpets. ** ** Written: 7/13/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_BARGE #define INCL_BARGE 1 #include "contain.h" /* * A 'barge', such as a ship or horse-and-cart. The elements of a barge * are stored in the outside world, so rendering and obstacle detection * don't have to be reimplemented. */ class Barge_object : public Container_game_object, public Time_sensitive { Game_object_vector objects; // All objects in/on barge. int perm_count; // Counts permanent parts of barge, // which proceed those placed on it. unsigned char xtiles, ytiles; // Tiles covered (when vertical). unsigned char dir; // Direction: 0=N, 1=E, 2=S, 3=W. bool complete; // Flag: all members have been read. bool gathered; // Items on barge have been gathered. bool ice_raft; // For Serpent Isle. bool first_step; // So first motion can just be 1 tile. signed char boat; // 1 if a boat, 0 if not; -1=untested. int frame_time; // Time between frames in msecs. 0 if // not moving. PathFinder *path; // For traveling. Tile_coord center; // Center of barge. Game_object *get_object(int i) { return objects[i]; } void swap_dims(); void set_center(); int okay_to_rotate(Tile_coord pos); void add_dirty(); // Finish up move/rotate operation. void finish_move(Tile_coord *positions); public: Barge_object(int shapenum, int framenum, unsigned int shapex, unsigned int shapey, unsigned int lft, int xt, int yt, int d) : Container_game_object(shapenum, framenum, shapex, shapey, lft), perm_count(0), xtiles(xt), ytiles(yt), dir(d), complete(false), gathered(false), ice_raft(false), first_step(true), boat(-1), frame_time(0), path(0) { } Rectangle get_tile_footprint(); bool is_moving() { return frame_time > 0; } int get_xtiles() // Dims. in tiles. { return xtiles; } int get_ytiles() { return ytiles; } Tile_coord get_center() { return center; } virtual ~Barge_object(); void set_to_gather() // Require 'gather' on next move. { gathered = false; } void gather(); // Gather up objects on barge. void face_direction(int ndir); // Face dir. (0-7). // Start rolling/sailing. void travel_to_tile(Tile_coord dest, int speed); void turn_right(); // Turn 90 degrees right. void turn_left(); void turn_around(); void stop() // Stop moving. { frame_time = 0; first_step = true; } void done(); // No longer being operated. int okay_to_land(); // See if clear to land. virtual Barge_object *as_barge() { return this; } // For Time_sensitive: virtual void handle_event(unsigned long curtime, long udata); // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); // Remove an object. virtual void remove(Game_object *obj); // Add an object. virtual bool add(Game_object *obj, bool dont_check = false, bool combine = false); // Drop another onto this. virtual int drop(Game_object *obj); // Render. virtual void paint(); // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame = -1); // Write out to IREG file. virtual void write_ireg(DataSource* out); // Get size of IREG. Returns -1 if can't write to buffer virtual int get_ireg_size(); virtual void elements_read(); // Called when all member items read. }; #endif exult-1.2/objs/objiter.h0000644000175000001440000001072510054030566010742 /** ** Objiter.h - Game objects iterator. ** ** Written: 7/29/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_OBJITER #define INCL_OBJITER 1 #include "objlist.h" class Map_chunk; class Game_object; /* * Want to make all object iterators modification-safe. For now, just * trying to detect modification during iteration. */ template class T_Safe_object_iterator { T_Object_list& list; public: T_Safe_object_iterator(T_Object_list& l) : list(l) { list.add_iterator(); } ~T_Safe_object_iterator() { list.remove_iterator(); } }; /* * Iterate through list of objects. */ template class T_Object_iterator : public T_Safe_object_iterator { protected: T first; T stop; T cur; // Next to return. public: void reset() { cur = first; stop = 0; } T_Object_iterator(T_Object_list& objects) : T_Safe_object_iterator(objects), first(objects.get_first()) { reset(); } T get_next() { if (cur == stop) return 0; T ret = cur; cur = cur->next; stop = first; return ret; } }; typedef T_Object_iterator Object_iterator; /* * Iterate through a chunk's nonflat objects. */ template class T_Nonflat_object_iterator : public T_Object_iterator { T nonflats; public: void reset() { this->cur = nonflats; this->stop = 0; } T_Nonflat_object_iterator(L chunk) : T_Object_iterator(chunk->get_objects()), nonflats(chunk->get_first_nonflat()) { reset(); } }; typedef T_Nonflat_object_iterator Nonflat_object_iterator; /* * Iterate through a chunk's flat objects. */ template class T_Flat_object_iterator : public T_Safe_object_iterator { T first; T stop; T cur; // Next to return. T stop_at; public: void reset() { cur = first; stop = 0; } T_Flat_object_iterator(L chunk) : T_Safe_object_iterator(chunk->get_objects()) { first = chunk->get_objects().get_first() == chunk->get_first_nonflat() ? 0 : chunk->get_objects().get_first(); stop_at = chunk->get_first_nonflat() ? chunk->get_first_nonflat() : chunk->get_objects().get_first(); reset(); } T get_next() { if (cur == stop) return 0; T ret = cur; cur = cur->get_next(); stop = stop_at; return ret; } }; typedef T_Flat_object_iterator Flat_object_iterator; /* * Iterate backwards through list of objects. */ template class T_Object_iterator_backwards : public T_Safe_object_iterator { T first; T stop; T cur; // Return prev. to this. public: void reset() { cur = first; stop = 0; } T_Object_iterator_backwards(L chunk) : T_Safe_object_iterator(chunk->get_objects()), first(chunk->get_objects().get_first()) { reset(); } T_Object_iterator_backwards(T_Object_list& objects) : T_Safe_object_iterator(objects), first(objects.get_first()) { reset(); } T get_next() { if (cur == stop) return 0; cur = cur->prev; stop = first; return cur; } }; typedef T_Object_iterator_backwards Object_iterator_backwards; /* * Iterate through a list of objects (recursively). */ template class D_Recursive_object_iterator { // Child we're going through, or 0. D_Recursive_object_iterator *child; D elems; // Goes through our elements. public: D_Recursive_object_iterator(Object_list& objs) : elems(objs), child(0) { } // Start at given object. D_Recursive_object_iterator(Game_object *obj); Game_object *get_next(); // Get next, going into containers. }; /* * Iterate forwards/backwards through a list of objects (recursively). */ typedef D_Recursive_object_iterator Recursive_object_iterator_backwards; typedef D_Recursive_object_iterator Recursive_object_iterator; #endif exult-1.2/objs/objlist.h0000755000175000001440000000544507270737467011004 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OBJLIST_H #define OBJLIST_H #include "shapeid.h" template class T_Object_iterator; template class T_Flat_object_iterator; template class T_Object_iterator_backwards; /* * A list of objects chained together with the 'next' and 'prev' * fields: */ template class T_Object_list { friend class T_Object_iterator; friend class T_Flat_object_iterator; friend class T_Object_iterator_backwards; T first; // ->first in (circular) chain. unsigned short iter_count; // # of iterators. public: T_Object_list(T f = 0) : first(f), iter_count(0) { } // Delete the chain. ~T_Object_list() { if (!first) return; T objects = first; T obj; do { obj = objects; objects = obj->next; delete obj; } while (obj != first); } // Report iterator problem. void report_problem() const { std::cerr << "Danger! Danger! Object list modified while being iterated." << std::endl; std::cerr.flush(); } int is_empty() const { return first == 0; } void add_iterator() { iter_count++; } void remove_iterator() { iter_count--; } T get_first() const { return first; } // Insert at head of chain. void insert(T nobj) { if (iter_count) report_problem(); if (!first) // First one. nobj->next = nobj->prev = nobj; else { nobj->next = first; nobj->prev = first->prev; first->prev->next = nobj; first->prev = nobj; } first = nobj; } // Insert before given obj. void insert_before(T nobj, T before) { if (iter_count) report_problem(); nobj->next = before; nobj->prev = before->prev; before->prev->next = nobj; before->prev = nobj; first = before == first ? nobj : first; } // Append. void append(T nobj) { insert(nobj); first = nobj->next; } void remove(T dobj) { if (iter_count) report_problem(); if (dobj == first) first = dobj->next != first ? dobj->next : 0; dobj->next->prev = dobj->prev; dobj->prev->next = dobj->next; } }; class Game_object; typedef T_Object_list Object_list; #endif exult-1.2/objs/animate.h0000644000175000001440000001215307725005354010727 /** ** Animate.h - Animated game objects. ** ** Written: 7/27/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_ANIMATE #define INCL_ANIMATE 1 #include "iregobjs.h" /* * An animator: */ class Animator : public Time_sensitive, public Game_singletons { protected: Game_object *obj; // Object we're controlling. unsigned char deltax, deltay; // If wiggling, deltas from // original position. bool animating; // 1 if animation turned on. int sfxnum; // Sound effects #, or -1 if none. void start_animation(); public: Animator(Game_object *o, int snum = -1) : obj(o), deltax(0), deltay(0), animating(false), sfxnum(snum) { } static Animator *create(Game_object *ob); ~Animator(); void want_animation() // Want animation on. { if (!animating) start_animation(); } int get_deltax() { return deltax; } int get_deltay() { return deltay; } virtual int get_framenum(); }; /* * Animate by going through frames. */ class Frame_animator : public Animator { unsigned char first_frame; // First frame of animation. unsigned char frames; // # of frames. unsigned int created; // Time created unsigned int delay; // Rate of animation unsigned short last_shape; // To check if we need to re init unsigned short last_frame; // To check if we need to re init enum // Type of animation { FA_LOOPING = 0, FA_SUNDIAL = 1, FA_ENERGY_FIELD = 2 } type; void Initialize(); public: Frame_animator(Game_object *o); virtual int get_framenum(); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); }; /* * Just play SFX. */ class Sfx_animator : public Animator { public: Sfx_animator(Game_object *o); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); }; /* * Animate by going through frames, but only do the lower frames once. */ class Field_frame_animator : public Animator { unsigned char frames; // # of frames. unsigned char recycle; // # of frame to recycle at. bool activated; // Time to check for damage. public: friend class Field_object; Field_frame_animator(Game_object *o, int rcy); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); }; /* * Animate by wiggling. */ class Wiggle_animator : public Animator { public: Wiggle_animator(Game_object *o) : Animator(o) { } // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); }; /* * An object that cycles through its frames, or wiggles if just one * frame. The base class is for those in U7chunks. */ class Animated_object : public Terrain_game_object { Animator *animator; // Controls animation. public: Animated_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0); virtual ~Animated_object(); // Render. virtual void paint(); // +++++Needed on this one: // Get coord. where this was placed. virtual Tile_coord get_original_tile_coord() const { return get_tile() + Tile_coord(-animator->get_deltax(), -animator->get_deltay(), 0); } }; /* * An object that cycles through its frames, or wiggles if just one * frame. This is the IREG version. */ class Animated_ireg_object : public Ireg_game_object { Animator *animator; // Controls animation. public: Animated_ireg_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0); virtual ~Animated_ireg_object(); // Render. virtual void paint(); // Get coord. where this was placed. virtual Tile_coord get_original_tile_coord() const { return get_tile() + Tile_coord(-animator->get_deltax(), -animator->get_deltay(), 0); } // Write out to IREG file. virtual void write_ireg(DataSource* out); }; /* * An object that cycles through its frames, or wiggles if just one * frame. This is the IFIX version. */ class Animated_ifix_object : public Ifix_game_object { Animator *animator; // Controls animation. public: Animated_ifix_object(unsigned char *ifix); Animated_ifix_object(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft = 0); virtual ~Animated_ifix_object(); // Render. virtual void paint(); // Get coord. where this was placed. virtual Tile_coord get_original_tile_coord() const { return get_tile() + Tile_coord(-animator->get_deltax(), -animator->get_deltay(), 0); } virtual void write_ifix(DataSource* ifix); }; #endif exult-1.2/objs/mappatch.cc0000644000175000001440000000605507504147250011245 /** ** Mappatch.cc - Patches to the game map. ** ** Written: 10-18-2001 **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "mappatch.h" #include "gamewin.h" #include "objs.h" #include "vec.h" /* * Find (first) matching object. */ Game_object *Map_patch::find ( ) { Game_window *gwin = Game_window::get_instance(); Game_object_vector vec; // Pass mask=0xb0 to get any object. Game_object::find_nearby(vec, spec.loc, spec.shapenum, 0, 0xb0, spec.quality, spec.framenum); return vec.empty() ? 0 : vec.front(); } /* * Apply by removing object. * * Output: false if no object found. */ bool Map_patch_remove::apply ( ) { bool found = false; Game_object *obj; while ((obj = find()) != 0) { obj->remove_this(); found = true; if (!all) // Just one? return true; } return found; } /* * Apply by moving/changing object. * * Output: false if no object found. */ bool Map_patch_modify::apply ( ) { Game_object *obj = find(); if (!obj) return false; obj->remove_this(1); // Remove but don't delete. if (mod.shapenum != c_any_shapenum) obj->set_shape(mod.shapenum); if (mod.framenum != c_any_framenum) obj->set_frame(mod.framenum); if (mod.quality != c_any_qual) obj->set_quality(mod.quality); obj->set_invalid(); // To add it back correctly. obj->move(mod.loc); return true; } /* * Delete all the patches. */ Map_patch_collection::~Map_patch_collection ( ) { for (Map_patch_map::iterator it1 = patches.begin(); it1 != patches.end(); it1++) { Map_patch_list& lst = (*it1).second; while (!lst.empty()) { Map_patch *patch = lst.front(); delete patch; lst.pop_front(); } } } /* * Add a new patch. */ void Map_patch_collection::add ( Map_patch *p ) { // Get superchunk coords. int sx = p->spec.loc.tx/c_tiles_per_schunk, sy = p->spec.loc.ty/c_tiles_per_schunk; // Get superchunk # (0-143). int schunk = sy*c_num_schunks + sx; patches[schunk].push_back(p); } /* * Apply all patches for a superchunk. */ void Map_patch_collection::apply ( int schunk ) { Map_patch_map::iterator it1 = patches.find(schunk); if (it1 != patches.end()) // Found list for superchunk? { Map_patch_list& lst = (*it1).second; for (Map_patch_list::const_iterator it2 = lst.begin(); it2 != lst.end(); it2++) (*it2)->apply(); // Apply each one in list. } } exult-1.2/objs/find_nearby.h0000644000175000001440000000624407724430452011575 /* * find_nearby.h - Header for defining static Game_object::find_nearby() * * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef FN_VECTOR #error(Can't Include find_nearby.h if FN_VECTOR is not #define'd) #endif #ifndef FN_OBJECT #error(Can't Include find_nearby.h if FN_OBJECT is not #define'd) #endif #ifndef FN_CAST #error(Can't Include find_nearby.h if FN_CAST is not #define'd) #endif int Game_object::find_nearby ( FN_VECTOR& vec, // Objects appended to this. Tile_coord pos, // Look near this point. int shapenum, // Shape to look for. // -1=any (but always use mask?), // c_any_shapenum=any. int delta, // # tiles to look in each direction. int mask, // See Check_mask() above. int qual, // Quality, or c_any_qual for any. int framenum // Frame #, or c_any_framenum for any. ) { if (delta < 0) // +++++Until we check all old callers. delta = 24; if (shapenum > 0 && mask == 4) // Ignore mask=4 if shape given! mask = 0; int vecsize = vec.size(); Game_window *gwin = Game_window::get_instance(); Game_map *gmap = gwin->get_map(); Rectangle tiles(pos.tx - delta, pos.ty - delta, 1 + 2*delta, 1 + 2*delta); // Stay within world. Rectangle world(0, 0, c_num_chunks*c_tiles_per_chunk, c_num_chunks*c_tiles_per_chunk); tiles = tiles.intersect(world); // Figure range of chunks. int start_cx = tiles.x/c_tiles_per_chunk, end_cx = (tiles.x + tiles.w - 1)/c_tiles_per_chunk; int start_cy = tiles.y/c_tiles_per_chunk, end_cy = (tiles.y + tiles.h - 1)/c_tiles_per_chunk; // Go through all covered chunks. for (int cy = start_cy; cy <= end_cy; cy++) for (int cx = start_cx; cx <= end_cx; cx++) { // Go through objects. Map_chunk *chunk = gmap->get_chunk(cx, cy); Object_iterator next(chunk->get_objects()); Game_object *obj; while ((obj = next.get_next()) != 0) { // Check shape. if (shapenum >= 0) { if (obj->get_shapenum() != shapenum) continue; } if (qual != c_any_qual && obj->get_quality() != qual) continue; if (framenum != c_any_framenum && obj->get_framenum() != framenum) continue; if (!Check_mask(gwin, obj, mask)) continue; Tile_coord t = obj->get_tile(); if (tiles.has_point(t.tx, t.ty)) { FN_OBJECT* castobj = obj FN_CAST; if (castobj) vec.push_back(castobj); } } } // Return # added. return (vec.size() - vecsize); } #undef FN_VECTOR #undef FN_OBJECT #undef FN_CAST exult-1.2/objs/barge.cc0000644000175000001440000004743710040666421010534 /** ** Barge.cc - Ships, carts, flying-carpets. ** ** Written: 7/13/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "barge.h" #include "gamewin.h" #include "gamemap.h" #include "actors.h" #include "Zombie.h" #include "citerate.h" #include "dir.h" #include "chunks.h" #include "objiter.h" #include "game.h" #include "databuf.h" #include "ucsched.h" using std::ostream; /* * Rotate a point 90 degrees to the right around a point. * * In cartesian coords with 'c' as center, the rule is: * (newx, newy) = (oldy, -oldx) */ inline Tile_coord Rotate90r ( Tile_coord t, // Tile to move. Tile_coord c // Center to rotate around. ) { // Get cart. coords. rel. to center. int rx = t.tx - c.tx, ry = c.ty - t.ty; return Tile_coord(c.tx + ry, c.ty + rx, t.tz); } /* * Rotate a point 90 degrees to the left around a point. * * In cartesian coords with 'c' as center, the rule is: * (newx, newy) = (-oldy, oldx) */ inline Tile_coord Rotate90l ( Tile_coord t, // Tile to move. Tile_coord c // Center to rotate around. ) { // Get cart. coords. rel. to center. int rx = t.tx - c.tx, ry = c.ty - t.ty; return Tile_coord(c.tx - ry, c.ty - rx, t.tz); } /* * Rotate a point 180 degrees around a point. * * In cartesian coords with 'c' as center, the rule is: * (newx, newy) = (-oldx, -oldy) */ inline Tile_coord Rotate180 ( Tile_coord t, // Tile to move. Tile_coord c // Center to rotate around. ) { // Get cart. coords. rel. to center. int rx = t.tx - c.tx, ry = c.ty - t.ty; return Tile_coord(c.tx - rx, c.ty + ry, t.tz); } /* * Figure tile where an object will be if it's rotated 90 degrees around * a point counterclockwise, assuming its 'hot spot' * is at its lower-right corner. */ inline Tile_coord Rotate90r ( Game_window *gwin, Game_object *obj, int xtiles, int ytiles, // Object dimensions. Tile_coord c // Rotate around this. ) { // Rotate hot spot. Tile_coord r = Rotate90r(obj->get_tile(), c); // New hotspot is what used to be the // upper-right corner. r.tx = (r.tx + ytiles + c_num_tiles)%c_num_tiles; r.ty = (r.ty + c_num_tiles)%c_num_tiles; return r; } /* * Figure tile where an object will be if it's rotated 90 degrees around * a point, assuming its 'hot spot' is at its lower-right corner. */ inline Tile_coord Rotate90l ( Game_window *gwin, Game_object *obj, int xtiles, int ytiles, // Object dimensions. Tile_coord c // Rotate around this. ) { // Rotate hot spot. Tile_coord r = Rotate90l(obj->get_tile(), c); // New hot-spot is old lower-left. r.ty = (r.ty + xtiles + c_num_tiles)%c_num_tiles; r.tx = (r.tx + c_num_tiles)%c_num_tiles; return r; } /* * Figure tile where an object will be if it's rotated 180 degrees around * a point, assuming its 'hot spot' is at its lower-right corner. */ inline Tile_coord Rotate180 ( Game_window *gwin, Game_object *obj, int xtiles, int ytiles, // Object dimensions. Tile_coord c // Rotate around this. ) { // Rotate hot spot. Tile_coord r = Rotate180(obj->get_tile(), c); // New hotspot is what used to be the // upper-left corner. r.tx = (r.tx + xtiles + c_num_tiles)%c_num_tiles; r.ty = (r.ty + ytiles + c_num_tiles)%c_num_tiles; return r; } /* * Swap dimensions. */ inline void Barge_object::swap_dims ( ) { int tmp = xtiles; // Swap dims. xtiles = ytiles; ytiles = tmp; } /* * Get footprint in tiles. */ Rectangle Barge_object::get_tile_footprint ( ) { Tile_coord pos = get_tile(); int xts = get_xtiles(), yts = get_ytiles(); Rectangle foot((pos.tx - xts + 1 + c_num_tiles)%c_num_tiles, (pos.ty - yts + 1 + c_num_tiles)%c_num_tiles, xts, yts); return foot; } /* * Set center. */ inline void Barge_object::set_center ( ) { center = get_tile(); center.tx = (center.tx - xtiles/2 + c_num_tiles)%c_num_tiles; center.ty = (center.ty - ytiles/2 + c_num_tiles)%c_num_tiles; } /* * See if okay to rotate. +++++++++++Handle wrapping here+++++++++++ */ int Barge_object::okay_to_rotate ( Tile_coord pos // New position (bottom-right). ) { int lift = get_lift(); // Special case for carpet. int move_type = (lift >= 10) ? (MOVE_LEVITATE) : MOVE_ALL_TERRAIN; // Get footprint in tiles. Rectangle foot = get_tile_footprint(); int xts = get_xtiles(), yts = get_ytiles(); // Get where new footprint will be. Rectangle newfoot(pos.tx - yts + 1, pos.ty - xts + 1, yts, xts); int new_lift; if (newfoot.y < foot.y) // Got a piece above the old one? // Check area. (No dropping allowed.) if (Map_chunk::is_blocked(4, lift, newfoot.x, newfoot.y, newfoot.w, foot.y - newfoot.y, new_lift, move_type, 0) || new_lift != lift) return 0; if (foot.y + foot.h < newfoot.y + newfoot.h) // A piece below old one. if (Map_chunk::is_blocked(4, lift, newfoot.x, foot.y + foot.h, newfoot.w, newfoot.y + newfoot.h - (foot.y + foot.h), new_lift, move_type, 0) || new_lift != lift) return 0; if (newfoot.x < foot.x) // Piece to the left? if (Map_chunk::is_blocked(4, lift, newfoot.x, newfoot.y, foot.x - newfoot.x, newfoot.h, new_lift, move_type, 0) || new_lift != lift) return 0; if (foot.x + foot.w < newfoot.x + newfoot.w) // Piece to the right. if (Map_chunk::is_blocked(4, lift, foot.x + foot.w, newfoot.y, newfoot.x + newfoot.w - (foot.x + foot.w), newfoot.h, new_lift, move_type, 0) || new_lift != lift) return 0; return 1; } /* * Delete. */ Barge_object::~Barge_object ( ) { delete path; } /* * Gather up all objects that appear to be on this barge. * Also inits. 'center'. */ void Barge_object::gather ( ) { if (!gmap->get_chunk_safely(get_cx(), get_cy())) return; // Not set in world yet. ice_raft = false; // We'll just detect it each time. objects.resize(perm_count); // Start fresh. // Get footprint in tiles. Rectangle foot = get_tile_footprint(); int lift = get_lift(); // How high we are. // Go through intersected chunks. Chunk_intersect_iterator next_chunk(foot); Rectangle tiles; int cx, cy; bool si = Game::get_game_type() == SERPENT_ISLE; while (next_chunk.get_next(tiles, cx, cy)) { Map_chunk *chunk = gmap->get_chunk(cx, cy); tiles.x += cx*c_tiles_per_chunk; tiles.y += cy*c_tiles_per_chunk; Game_object *obj; Object_iterator next(chunk->get_objects()); while ((obj = next.get_next()) != 0) { // Look at each object. if (obj == this) continue; if (obj->is_egg()) // don't pick up eggs continue; Tile_coord t = obj->get_tile(); Shape_info& info = obj->get_info(); // Above barge, within 5-tiles up? if (tiles.has_point(t.tx, t.ty) && t.tz >= lift - 1 && t.tz + info.get_3d_height() > lift && (info.is_barge_part() || t.tz < lift + 5) && obj->get_owner() != this) { objects.append(obj); if (si) { if (obj->get_shapenum() == 0x1f8) ice_raft = true; // Kludge for SI turtle. else if (obj->get_shapenum() == 0xd7) xtiles = 20; } } } } set_center(); // Test for boat. Map_chunk *chunk = gmap->get_chunk_safely( center.tx/c_tiles_per_chunk, center.ty/c_tiles_per_chunk); if (boat == -1 && chunk != 0) { ShapeID flat = chunk->get_flat(center.tx%c_tiles_per_chunk, center.ty%c_tiles_per_chunk); if (flat.is_invalid()) boat = 0; else { Shape_info& info = flat.get_info(); boat = info.is_water(); } } gathered = true; } /* * Add a dirty rectangle for our current position. */ void Barge_object::add_dirty ( ) { int x, y; // Get lower-right corner. gwin->get_shape_location(this, x, y); int w = xtiles*c_tilesize, h = ytiles*c_tilesize; Rectangle box(x - w, y - h, w, h); box.enlarge(10); // Make it a bit bigger. if (dir%2) // Horizontal? Stretch. { box.x -= 18; box.w += 36; } else { box.y -= 18; box.h += 36; } box = gwin->clip_to_win(box); // Intersect with screen. gwin->add_dirty(box); } /* * Finish up moving all the objects by adding them back and deleting the * saved list of positions. */ void Barge_object::finish_move ( Tile_coord *positions // New positions. Deleted when done. ) { set_center(); // Update center. int cnt = objects.size(); // We'll move each object. for (int i = 0; i < cnt; i++) // Now add them back in new location. { Game_object *obj = get_object(i); if (i < perm_count) // Restore us as owner. obj->set_owner(this); obj->move(positions[i]); } delete [] positions; // Check for scrolling. gwin->scroll_if_needed(center); } /* * Turn to face a given direction. */ void Barge_object::face_direction ( int ndir // 0-7 0==North. ) { ndir /= 2; // Convert to 0-3. switch ((4 + ndir - dir)%4) { case 1: // Rotate 90 degrees right. turn_right(); break; case 2: turn_around(); // 180 degrees. break; case 3: turn_left(); break; default: break; } } /* * Travel towards a given tile. */ void Barge_object::travel_to_tile ( Tile_coord dest, // Destination. int speed // Time between frames (msecs). ) { if (!path) path = new Zombie(); // Set up new path. if (path->NewPath(get_tile(), dest, 0)) { frame_time = speed; // Figure new direction. Tile_coord cur = get_tile(); int dy = Tile_coord::delta(cur.ty, dest.ty), dx = Tile_coord::delta(cur.tx, dest.tx); int ndir = Get_direction4(-dy, dx); if (!ice_raft) // Ice-raft doesn't rotate. face_direction(ndir); if (!in_queue()) // Not already in queue? gwin->get_tqueue()->add(Game::get_ticks(), this, 0L); } else frame_time = 0; // Not moving. } /* * Turn 90 degrees to the right. */ void Barge_object::turn_right ( ) { add_dirty(); // Want to repaint old position. // Move the barge itself. Tile_coord rot = Rotate90r(gwin, this, xtiles, ytiles, center); if (!okay_to_rotate(rot)) // Check for blockage. return; Container_game_object::move(rot.tx, rot.ty, rot.tz); swap_dims(); // Exchange xtiles, ytiles. dir = (dir + 1)%4; // Increment direction. int cnt = objects.size(); // We'll move each object. // But 1st, remove & save new pos. Tile_coord *positions = new Tile_coord[cnt]; for (int i = 0; i < cnt; i++) { Game_object *obj = get_object(i); int frame = obj->get_framenum(); Shape_info& info = obj->get_info(); positions[i] = Rotate90r(gwin, obj, info.get_3d_xtiles(frame), info.get_3d_ytiles(frame), center); obj->remove_this(1); // Remove object from world. // Set to rotated frame. obj->set_frame(obj->get_rotated_frame(1)); obj->set_invalid(); // So it gets added back right. } finish_move(positions); // Add back & del. positions. } /* * Turn 90 degrees to the left. */ void Barge_object::turn_left ( ) { add_dirty(); // Want to repaint old position. // Move the barge itself. Tile_coord rot = Rotate90l(gwin, this, xtiles, ytiles, center); if (!okay_to_rotate(rot)) // Check for blockage. return; Container_game_object::move(rot.tx, rot.ty, rot.tz); swap_dims(); // Exchange xtiles, ytiles. dir = (dir + 3)%4; // Increment direction. int cnt = objects.size(); // We'll move each object. // But 1st, remove & save new pos. Tile_coord *positions = new Tile_coord[cnt]; for (int i = 0; i < cnt; i++) { Game_object *obj = get_object(i); int frame = obj->get_framenum(); Shape_info& info = obj->get_info(); positions[i] = Rotate90l(gwin, obj, info.get_3d_xtiles(frame), info.get_3d_ytiles(frame), center); obj->remove_this(1); // Remove object from world. // Set to rotated frame. obj->set_frame(obj->get_rotated_frame(3)); obj->set_invalid(); // So it gets added back right. } finish_move(positions); // Add back & del. positions. } /* * Turn 180 degrees. */ void Barge_object::turn_around ( ) { add_dirty(); // Want to repaint old position. // Move the barge itself. Tile_coord rot = Rotate180(gwin, this, xtiles, ytiles, center); Container_game_object::move(rot.tx, rot.ty, rot.tz); dir = (dir + 2)%4; // Increment direction. int cnt = objects.size(); // We'll move each object. // But 1st, remove & save new pos. Tile_coord *positions = new Tile_coord[cnt]; for (int i = 0; i < cnt; i++) { Game_object *obj = get_object(i); int frame = obj->get_framenum(); Shape_info& info = obj->get_info(); positions[i] = Rotate180(gwin, obj, info.get_3d_xtiles(frame), info.get_3d_ytiles(frame), center); obj->remove_this(1); // Remove object from world. // Set to rotated frame. obj->set_frame(obj->get_rotated_frame(2)); obj->set_invalid(); // So it gets added back right. } finish_move(positions); // Add back & del. positions. } /* * Ending 'barge mode'. */ void Barge_object::done ( ) { gathered = false; // Clear for next time. static int norecurse = 0; // Don't recurse on the code below. if (norecurse > 0) return; norecurse++; if (boat == 1) // Look for sails on boat. { // Pretend they were clicked on. int cnt = objects.size(); // Look for open sail. for (int i = 0; i < cnt; i++) { Game_object *obj = objects[i]; if (obj->get_shapenum() == 251 && (obj->get_framenum()&7) < 4) { obj->activate(); break; } } } norecurse--; } /* * Is it okay to land? */ int Barge_object::okay_to_land ( ) { Rectangle foot = get_tile_footprint(); int lift = get_lift(); // How high we are. // Go through intersected chunks. Chunk_intersect_iterator next_chunk(foot); Rectangle tiles; int cx, cy; while (next_chunk.get_next(tiles, cx, cy)) { // Check each tile. Map_chunk *chunk = gmap->get_chunk(cx, cy); for (int ty = tiles.y; ty < tiles.y + tiles.h; ty++) for (int tx = tiles.x; tx < tiles.x + tiles.w; tx++) if (chunk->get_highest_blocked(lift, tx, ty) != -1) return (0); } return (1); } /* * Handle a time event (for animation). */ void Barge_object::handle_event ( unsigned long curtime, // Current time of day. long udata // Ignored. ) { if (!path || !frame_time || gwin->get_moving_barge() != this) return; // We shouldn't be doing anything. Tile_coord tile; // Get spot & walk there. // Take two steps for speed. if (!path->GetNextStep(tile) || !step(tile)) frame_time = 0; // But not when just starting. else if (!first_step && (!path->GetNextStep(tile) || !step(tile))) frame_time = 0; else gwin->get_tqueue()->add(curtime + frame_time, this, udata); first_step = false; // After 1st, move 2 at a time. } /* * Move to a new absolute location. */ void Barge_object::move ( int newtx, int newty, int newlift ) { if (!gathered) // Happens in SI with turtle. gather(); // Want to repaint old position. add_dirty(); // Get current location. Tile_coord old = get_tile(); // Move the barge itself. Container_game_object::move(newtx, newty, newlift); // Get deltas. int dx = newtx - old.tx, dy = newty - old.ty, dz = newlift - old.tz; int cnt = objects.size(); // We'll move each object. // But 1st, remove & save new pos. Tile_coord *positions = new Tile_coord[cnt]; int i; for (i = 0; i < cnt; i++) { Game_object *obj = get_object(i); Tile_coord ot = obj->get_tile(); // Watch for world-wrapping. positions[i] = Tile_coord( (ot.tx + dx + c_num_tiles)%c_num_tiles, (ot.ty + dy + c_num_tiles)%c_num_tiles, ot.tz + dz); obj->remove_this(1); // Remove object from world. obj->set_invalid(); // So it gets added back right. // Animate a few shapes. int frame = obj->get_framenum(); switch (obj->get_shapenum()) { case 774: // Cart wheel. obj->set_frame(((frame + 1)&3)|(frame&32)); break; case 796: // Draft horse. obj->set_frame(((frame + 4)&15)|(frame&32)); break; } } finish_move(positions); // Add back & del. positions. } /* * Remove an object. */ void Barge_object::remove ( Game_object *obj ) { obj->set_owner(0); obj->remove_this(1); // Now remove from outside world. } /* * Add an object. * * Output: 0, meaning object should also be added to chunk. */ bool Barge_object::add ( Game_object *obj, bool dont_check, bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { objects.append(obj); // Add to list. return (false); // We want it added to the chunk. } /* * Drop another onto this. * * Output: 0 to reject, 1 to accept. */ int Barge_object::drop ( Game_object *obj ) { return 0; //++++++Later. } /* * Paint at given spot in world. */ void Barge_object::paint ( ) { // DON'T paint barge shape itself. // The objects are in the chunk too. if(gwin->paint_eggs) Container_game_object::paint(); } /* * Step onto an adjacent tile. * * Output: 0 if blocked. * Dormant is set if off screen. */ int Barge_object::step ( Tile_coord t, // Tile to step onto. int // Frame (ignored). ) { if (!gathered) // Happens in SI with turtle. gather(); Tile_coord cur = get_tile(); // Blocked? (Assume ht.=4, for now.) int move_type; if (cur.tz >= 10) { // Definitely a carpet. move_type = MOVE_LEVITATE; boat = 0; } else if (boat) { move_type = MOVE_SWIM; // Hawk's boat gets grounded in SI. if (Game::get_game_type() == SERPENT_ISLE) { int sx = cur.tx/c_tiles_per_schunk, sy = cur.ty/c_tiles_per_schunk; if (sx == 8 && sy == 9) // Hawk's ship. move_type |= MOVE_WALK; } } else move_type = MOVE_WALK; // No rising/dropping. if (Map_chunk::is_blocked(get_xtiles(), get_ytiles(), 4, cur, t, move_type, 0, 0)) return (0); // Done. move(t.tx, t.ty, t.tz); // Move it & its objects. // Near an egg? Map_chunk *nlist = gmap->get_chunk(get_cx(), get_cy()); nlist->activate_eggs(gwin->get_main_actor(), t.tx, t.ty, t.tz, cur.tx, cur.ty); return (1); // Add back to queue for next time. } /* * Write out. */ void Barge_object::write_ireg ( DataSource *out ) { unsigned char buf[13]; // 13-byte entry + length-byte. buf[0] = 12; unsigned char *ptr = &buf[1]; // To avoid confusion about offsets. write_common_ireg(ptr); // Fill in bytes 1-4. ptr += 4; // Write size. *ptr++ = xtiles; *ptr++ = ytiles; *ptr++ = 0; // Unknown. // Flags (quality). Taking B3 to in- // dicate barge mode. *ptr++ = (dir<<1) | ((gwin->get_moving_barge() == this)<<3); *ptr++ = 0; // (Quantity). *ptr++ = (get_lift()&15)<<4; *ptr++ = 0; // Data2. *ptr++ = 0; // out->write((char*)buf, sizeof(buf)); // Write permanent objects. for (int i = 0; i < perm_count; i++) { Game_object *obj = get_object(i); obj->write_ireg(out); } out->write1(0x01); // A 01 terminates the list. // Write scheduled usecode. Game_map::write_scheduled(out, this); } // Get size of IREG. Returns -1 if can't write to buffer int Barge_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gwin->get_moving_barge() == this || Usecode_script::find(this)) return -1; int total_size = 13; for (int i = 0; i < perm_count; i++) { Game_object *obj = get_object(i); int size = obj->get_ireg_size(); if (size < 0) return -1; total_size += size; } total_size += 1; return total_size; } /* * This is called after all elements have been read in and added. */ void Barge_object::elements_read ( ) { perm_count = 0; // So we don't get haystack! complete = true; } exult-1.2/objs/chunkter.h0000644000175000001440000000626207515737227011150 /** ** Chunkter.h - Chunk terrain (16x16 flat tiles) on the map. ** ** Written: 7/6/01 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CHUNKTER_H #define CHUNKTER_H #include "shapeid.h" class Image_buffer8; class GL_texshape; /* * The flat landscape, 16x16 tiles: */ class Chunk_terrain : public Game_singletons { ShapeID shapes[256]; // Id's. The flat (non-RLE's) are // rendered here, the others are // turned into Game_objects in the // chunks that point to us. ShapeID *undo_shapes; // Set to prev. values when editing. int num_clients; // # of Chunk's that point to us. bool modified; // Changed (by map-editor). Image_buffer8 *rendered_flats; // Flats rendered for entire chunk. GL_texshape *glflats; // OpenGL texture from rendered_flats. // Most-recently used circular queue // for rendered_flats: static Chunk_terrain *render_queue; static int queue_size; Chunk_terrain *render_queue_next, *render_queue_prev; // Kept only for nearby chunks. void insert_in_queue(); // Queue methods. void remove_from_queue(); // Create rendered_flats. void paint_tile(int tilex, int tiley); Image_buffer8 *render_flats(); void free_rendered_flats(); public: // Create from 16x16x2 data: Chunk_terrain(unsigned char *data); // Copy-constructor: Chunk_terrain(const Chunk_terrain& c2); ~Chunk_terrain(); inline void add_client() { num_clients++; } inline void remove_client() { num_clients--; } inline bool is_modified() { return modified; } inline void set_modified(bool tf = true) { modified = tf; } #if 0 // Less-than c2 (for STL Map)? bool operator<(const Chunk_terrain& c2) const; #endif // Get tile's shape ID. inline ShapeID get_flat(int tilex, int tiley) const { return shapes[16*tiley + tilex]; } inline Shape_frame *get_shape(int tilex, int tiley) { return shapes[16*tiley + tilex].get_shape(); } // Set tile's shape. void set_flat(int tilex, int tiley, ShapeID id); bool commit_edits(); // Commit changes. Rets. true if // edited. void abort_edits(); // Undo changes. Image_buffer8 *get_rendered_flats() { if (render_queue != this)// Not already first in queue? // Move to front of queue. insert_in_queue(); return rendered_flats ? rendered_flats : render_flats(); } GL_texshape *get_glflats() { get_rendered_flats(); return glflats; } void render_all(int cx, int cy);// Render (in terrain-editing mode). // Write out to chunk. void write_flats(unsigned char *chunk_data); }; #endif exult-1.2/objs/virstone.cc0000644000175000001440000000461207513127023011312 /** ** Virstone.cc - Virtue stones. ** ** Written: 10/27/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "virstone.h" #include #include "databuf.h" #include "gamewin.h" #include "ucsched.h" #include "Gump_manager.h" using std::ostream; /* * Set position from IREG data. */ void Virtue_stone_object::set_pos ( unsigned char tilex, // Tx within superchunk. unsigned char tiley, // Ty within superchunk, unsigned char schunk, // Superchunk unsigned char lift ) { pos.tx = (schunk%12)*c_tiles_per_schunk + tilex; pos.ty = (schunk/12)*c_tiles_per_schunk + tiley; pos.tz = lift; } /* * Write out container and its members. */ void Virtue_stone_object::write_ireg ( DataSource *out ) { unsigned char buf[13]; // 13-byte entry + length-byte. buf[0] = 12; unsigned char *ptr = &buf[1]; // To avoid confusion about offsets. write_common_ireg(ptr); // Fill in bytes 1-4. ptr += 4; // Write tilex, tiley. *ptr++ = pos.tx%c_tiles_per_schunk; *ptr++ = pos.ty%c_tiles_per_schunk; // Get superchunk index. int sx = pos.tx/c_tiles_per_schunk, sy = pos.ty/c_tiles_per_schunk; *ptr++ = sy*12 + sx; // Write superchunk #. *ptr++ = pos.tz; // Finally, lift in entry[7].??Guess+++ *ptr++ = 0; // Entry[8] unknown. *ptr++ = (get_lift()&15)<<4; // Stone's lift in entry[9]. *ptr++ = 0; // Entry[10]. Unknown. *ptr++ = 0; // Entry[11]. Unknown. out->write((char*)buf, sizeof(buf)); } // Get size of IREG. Returns -1 if can't write to buffer int Virtue_stone_object::get_ireg_size() { // These shouldn't ever happen, but you never know if (gumpman->find_gump(this) || Usecode_script::find(this)) return -1; return 13; } exult-1.2/combat.cc0000644000175000001440000007442510054030530007750 /* * combat.h - Combat scheduling. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "combat.h" #include "combat_opts.h" #include "gamewin.h" #include "gameclk.h" #include "gamemap.h" #include "actors.h" #include "paths.h" #include "Astar.h" #include "actions.h" #include "items.h" #include "effects.h" #include "Audio.h" #include "ready.h" #include "game.h" #include "monstinf.h" #include "ucmachine.h" #include "game.h" #include "Gump_manager.h" #include "spellbook.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::rand; #endif unsigned long Combat_schedule::battle_time = (unsigned long) (-30000); unsigned long Combat_schedule::battle_end_time = 0; bool Combat::paused = false; int Combat::difficulty = 0; Combat::Mode Combat::mode = Combat::original; bool Combat::show_hits = false; extern bool combat_trace; /* * Is a given ammo shape in a given family. */ bool In_ammo_family(int shnum, int family) { if (shnum == family) return true; Ammo_info *ainf = ShapeID::get_info(shnum).get_ammo_info(); return (ainf != 0 && ainf->get_family_shape() == family); } /* * Start music if battle has recently started. */ void Combat_schedule::start_battle ( ) { if (started_battle) return; // But only if Avatar is main char. if (gwin->get_camera_actor() != gwin->get_main_actor()) return; unsigned long curtime = Game::get_ticks(); // .5 minute since last start? if (curtime - battle_time >= 30000) { Audio::get_ptr()->start_music_combat(rand()%2 ? CSAttacked1 : CSAttacked2, 0); battle_time = curtime; battle_end_time = curtime - 1; } started_battle = true; } /* * This (static) method is called when a monster dies. It checks to * see if there are still hostile NPC's around. If not, it plays * 'victory' music. */ void Combat_schedule::monster_died ( ) { if (battle_end_time >= battle_time)// Battle raging? return; // No, it's over. Actor_queue nearby; // Get all nearby NPC's. gwin->get_nearby_npcs(nearby); for (Actor_queue::const_iterator it = nearby.begin(); it != nearby.end(); ++it) { Actor *actor = *it; if (!actor->is_dead() && actor->get_attack_mode() != Actor::flee && actor->get_alignment() >= Npc_actor::hostile) return; // Still possible enemies. } battle_end_time = Game::get_ticks(); // Figure #seconds battle lasted. unsigned long len = (battle_end_time - battle_time)/1000; bool hard = len > 15 && (rand()%60 < len); Audio::get_ptr()->start_music_combat (hard ? CSBattle_Over : CSVictory, 0); } /* * Can a given shape teleport? */ inline bool Can_teleport ( Actor *npc ) { switch (npc->get_shapenum()) { case 534: // Wisp. case 445: case 446: // Mages. case 519: // Liche. return true; default: return false; } } /* * Certain monsters (wisps, mages) can teleport during battle. */ bool Combat_schedule::teleport ( ) { Game_object *trg = npc->get_target(); // Want to get close to targ. if (!trg) return false; unsigned int curtime = SDL_GetTicks(); if (curtime < teleport_time) return false; teleport_time = curtime + 2000 + rand()%2000; Tile_coord dest = trg->get_tile(); dest.tx += 4 - rand()%8; dest.ty += 4 - rand()%8; dest = Map_chunk::find_spot(dest, 3, npc, 1); if (dest.tx == -1) return false; // No spot found. Tile_coord src = npc->get_tile(); if (dest.distance(src) > 6 && rand()%5 != 0) return false; // Got to give Avatar a chance to // get away. // Create fire-field where he was. src.tz = npc->get_chunk()->get_highest_blocked(src.tz, src.tx%c_tiles_per_chunk, src.ty%c_tiles_per_chunk); if (src.tz < 0) src.tz = 0; eman->add_effect(new Fire_field_effect(src)); npc->move(dest.tx, dest.ty, dest.tz); // Show the stars. eman->add_effect(new Sprites_effect(7, npc, 0, 0, 0, 0)); return true; } /* * Off-screen? */ inline bool Off_screen ( Game_window *gwin, Game_object *npc ) { // See if off screen. Tile_coord t = npc->get_tile(); Rectangle screen = gwin->get_win_tile_rect().enlarge(2); return (!screen.has_point(t.tx, t.ty)); } /* * Find nearby opponents in the 9 surrounding chunks. */ void Combat_schedule::find_opponents ( ) { opponents.clear(); Game_window *gwin = Game_window::get_instance(); if (npc->get_alignment() >= Npc_actor::hostile) { Actor *party[10]; int cnt = gwin->get_party(party, 1); Actor *cact = gwin->get_camera_actor(); // Watch for companion on List Field. if (cact && cact != gwin->get_main_actor() && cact->get_alignment() == Npc_actor::friendly && cact->get_flag(Obj_flags::si_tournament)) party[cnt++] = cact; for (int i = 0; i < cnt; i++) // But ignore invisible ones. if (!party[i]->get_flag(Obj_flags::invisible) && party[i] != npc) opponents.push(party[i]); return; } Actor_queue nearby; // Get all nearby NPC's. gwin->get_nearby_npcs(nearby); // See if we're a party member. bool in_party = npc->is_in_party(); for (Actor_queue::const_iterator it = nearby.begin(); it != nearby.end(); ++it) { Actor *actor = *it; if (actor->is_dead() || actor->get_flag(Obj_flags::invisible)) continue; // Dead or invisible. if (actor->get_alignment() >= Npc_actor::hostile) { opponents.push(actor); } else if (in_party) { // Attacking party member? Game_object *t = actor->get_target(); if (t && t->get_flag(Obj_flags::in_party)) opponents.push(actor); } } // None found? Use Avatar's. if (opponents.empty() && npc->is_in_party() && npc != gwin->get_main_actor()) { Game_object *opp = gwin->get_main_actor()->get_target(); Actor *oppnpc = opp ? opp->as_actor() : 0; if (oppnpc && oppnpc != npc) opponents.push(oppnpc); } } /* * Find 'protected' party member's attackers. * * Output: ->attacker, or 0 if not found. */ Actor *Combat_schedule::find_protected_attacker ( ) { if (!npc->is_in_party()) // Not in party? return 0; Game_window *gwin = Game_window::get_instance(); Actor *party[9]; // Get entire party, including Avatar. int cnt = gwin->get_party(party, 1); Actor *prot_actor = 0; for (int i = 0; i < cnt; i++) if (party[i]->is_combat_protected()) { prot_actor = party[i]; break; } if (!prot_actor) // Not found? return 0; // Find closest attacker. int dist, best_dist = 4*c_tiles_per_chunk; Actor *best_opp = 0; for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ++it) { Actor *opp = *it; if (opp->get_target() == prot_actor && (dist = npc->distance(opp)) < best_dist) { best_dist = dist; best_opp = opp; } } if (!best_opp) return 0; if (failures < 5 && yelled && rand()%2 && npc != prot_actor) npc->say(first_will_help, last_will_help); return best_opp; } /* * Find a foe. * * Output: Opponent that was found. */ Game_object *Combat_schedule::find_foe ( int mode // Mode to use. ) { if (combat_trace) { cout << "'" << npc->get_name() << "' is looking for a foe" << endl; } // Remove any that died. for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ) { Actor_queue::const_iterator next = it; ++next; // Point to next. if ((*it)->is_dead()) opponents.remove(*it); it = next; } if (opponents.empty()) // No more from last scan? { find_opponents(); // Find all nearby. if (practice_target) // For dueling. return practice_target; } Actor *new_opponent = 0; switch ((Actor::Attack_mode) mode) { case Actor::weakest: { int str, least_str = 100; for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ++it) { Actor *opp = *it; str = opp->get_property(Actor::strength); if (str < least_str) { least_str = str; new_opponent = opp; } } break; } case Actor::strongest: { int str, best_str = -100; for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ++it) { Actor *opp = *it; str = opp->get_property(Actor::strength); if (str > best_str) { best_str = str; new_opponent = opp; } } break; } case Actor::nearest: { int best_dist = 4*c_tiles_per_chunk; for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ++it) { Actor *opp = *it; int dist = npc->distance(opp); if (opp->get_attack_mode() == Actor::flee) dist += 16; // Avoid fleeing. if (dist < best_dist) { best_dist = dist; new_opponent = opp; } } break; } case Actor::protect: new_opponent = find_protected_attacker(); if (new_opponent) break; // Found one. // FALL THROUGH to 'random'. case Actor::random: default: // Default to random. if (!new_opponent && !opponents.empty()) new_opponent = opponents.front(); break; } if (new_opponent) opponents.remove(new_opponent); return new_opponent; } /* * Find a foe. * * Output: Opponent that was found. */ inline Game_object *Combat_schedule::find_foe ( ) { if (npc->get_attack_mode() == Actor::manual) return 0; // Find it yourself. return find_foe(static_cast(npc->get_attack_mode())); } /* * Handle the 'approach' state. */ void Combat_schedule::approach_foe ( ) { Game_object *opponent = npc->get_target(); // Find opponent. if (!opponent && !(opponent = find_foe())) { failures++; npc->start(200, 400); // Try again in 2/5 sec. return; // No one left to fight. } npc->set_target(opponent); Actor::Attack_mode mode = npc->get_attack_mode(); Game_window *gwin = Game_window::get_instance(); // Time to run? if (mode == Actor::flee || (mode != Actor::beserk && (npc->get_type_flags()&MOVE_ALL) != 0 && npc != gwin->get_main_actor() && npc->get_property(Actor::health) < 3)) { run_away(); return; } if (Can_teleport(npc) && rand()%4 == 0 && // Try 1/4 to teleport. teleport()) { start_battle(); npc->start(gwin->get_std_delay(), gwin->get_std_delay()); return; } PathFinder *path = new Astar(); // Try this for now: Monster_pathfinder_client cost(npc, max_range, opponent); Tile_coord pos = npc->get_tile(); if (!path->NewPath(pos, opponent->get_tile(), &cost)) { // Failed? Try nearest opponent. failures++; bool retry_ok = false; if (npc->get_attack_mode() != Actor::manual) { Game_object *closest = find_foe(Actor::nearest); if (closest && closest != opponent) { opponent = closest; npc->set_target(opponent); Monster_pathfinder_client cost(npc, max_range, opponent); retry_ok = (opponent != 0 && path->NewPath( pos, opponent->get_tile(), &cost)); } } if (!retry_ok) { delete path; // Really failed. Try again in // after wandering. // Just try to walk somewhere. Tile_coord pos = opponent->get_tile(); if (rand()%3 == 0) pos = pos + Tile_coord(rand()%12 - 6, rand()%12 - 6, 0); npc->walk_to_tile(pos, 2*gwin->get_std_delay(), 500 + rand()%500); failures++; return; } } failures = 0; // Clear count. We succeeded. start_battle(); // Music if first time. if (combat_trace) { cout << npc->get_name() << " is pursuing " << opponent->get_name() << endl; } // First time (or 256th), visible? if (!yelled && gwin->add_dirty(npc)) { yelled++; if (can_yell && rand()%2)// Half the time. { // Goblin? if (Game::get_game_type() == SERPENT_ISLE && (npc->get_shapenum() == 0x1de || npc->get_shapenum() == 0x2b3 || npc->get_shapenum() == 0x2d5 || npc->get_shapenum() == 0x2e8)) npc->say(0x4c9, 0x4d1); else npc->say(first_to_battle, last_to_battle); } } // Walk there, & check half-way. npc->set_action(new Approach_actor_action(path, opponent)); // Start walking. Delay a bit if // opponent is off-screen. npc->start(gwin->get_std_delay(), Off_screen(gwin, opponent) ? 5*gwin->get_std_delay() : gwin->get_std_delay()); } /* * Swap weapon with the one in the belt. * * Output: 1 if successful. */ static int Swap_weapons ( Actor *npc ) { Game_object *bobj = npc->get_readied(Actor::belt); if (!bobj) { bobj = npc->get_readied(Actor::back2h_spot); if (!bobj) return 0; } Shape_info& info = bobj->get_info(); Weapon_info *winf = info.get_weapon_info(); if (!winf) return 0; // Not a weapon. int ammo = winf->get_ammo_consumed(); if (ammo) // Check for readied ammo. {//+++++Needs improvement. Ammo could be in pack. Game_object *aobj = npc->get_readied(Actor::ammo); if (!aobj || !In_ammo_family(aobj->get_shapenum(), ammo)) return 0; } if (info.get_ready_type() == two_handed_weapon && npc->get_readied(Actor::rhand) != 0) return 0; // Needs two free hands. Game_object *oldweap = npc->get_readied(Actor::lhand); if (oldweap) npc->remove(oldweap); npc->remove(bobj); npc->add(bobj, 1); // Should go into weapon hand. if (oldweap) npc->add(oldweap, 1); return 1; } /* * Begin a strike at the opponent. */ void Combat_schedule::start_strike ( ) { Game_object *opponent = npc->get_target(); Rectangle npctiles = npc->get_footprint(), opptiles = opponent->get_footprint(); Rectangle stiles = npctiles, // Get copy for weapon range. ptiles = npctiles; // Get difference in lift. int dz = npc->get_lift() - opponent->get_lift(); if (dz < 0) dz = -dz; // Close enough to strike? if (strike_range && dz < 5 && // Same floor? stiles.enlarge(strike_range).intersects(opptiles)) state = strike; else if (dz >= 5 || // FOR NOW, since is_straight_path() // doesn't check z-coord. !projectile_range || // Enlarge to projectile range. !ptiles.enlarge(projectile_range).intersects(opptiles)) { state = approach; approach_foe(); // Get a path. return; } else // See if we can fire spell/projectile. { Game_object *aobj; bool weapon_dead = false; if (spellbook) weapon_dead = !spellbook->can_do_spell(npc); else if (ammo_shape && (!(aobj = npc->get_readied(Actor::ammo)) || !In_ammo_family(aobj->get_shapenum(), ammo_shape))) weapon_dead = true; if (weapon_dead) { // Out of ammo/reagents. if (npc->get_schedule_type() != Schedule::duel) { // Look in pack for ammo. if (spellbook || !npc->ready_ammo()) Swap_weapons(npc); Combat_schedule::set_weapon(); } state = approach; npc->set_target(0); npc->start(200, 500); return; } Tile_coord pos = npc->get_tile(); Tile_coord opos = opponent->get_tile(); if (opos.tx < pos.tx) // Going left? pos.tx = npctiles.x; else // Right? opos.tx = opptiles.x; if (opos.ty < pos.ty) // Going north? pos.ty = npctiles.y; else // South. opos.ty = opptiles.y; if (!no_blocking && !Fast_pathfinder_client::is_straight_path(pos, opos)) { // Blocked. Find another spot. pos.tx += rand()%7 - 3; pos.ty += rand()%7 - 3; npc->walk_to_tile(pos, gwin->get_std_delay(), 0); state = approach; npc->set_target(0); // And try another enemy. return; } if (!started_battle) start_battle(); // Play music if first time. state = fire; // Clear to go. } if (combat_trace) { cout << npc->get_name() << " attacks " << opponent->get_name() << endl; } int dir = npc->get_direction(opponent); signed char frames[12]; // Get frames to show. int cnt = npc->get_attack_frames(weapon_shape, projectile_range > 0, dir, frames); if (cnt) npc->set_action(new Frames_actor_action(frames, cnt)); npc->start(); // Get back into time queue. int sfx; // Play sfx. Game_window *gwin = Game_window::get_instance(); Weapon_info *winf = ShapeID::get_info(weapon_shape).get_weapon_info(); if (winf && (sfx = winf->get_sfx()) >= 0 && // But only if Ava. involved. (npc == gwin->get_main_actor() || opponent == gwin->get_main_actor())) Audio::get_ptr()->play_sound_effect(sfx); } /* * Run away. */ void Combat_schedule::run_away ( ) { Game_window *gwin = Game_window::get_instance(); fleed++; // Might be nice to run from opp... int rx = rand(); // Get random position away from here. int ry = rand(); int dirx = 2*(rx%2) - 1; // Get 1 or -1. int diry = 2*(ry%2) - 1; Tile_coord pos = npc->get_tile(); pos.tx += dirx*(8 + rx%8); pos.ty += diry*(8 + ry%8); npc->walk_to_tile(pos, gwin->get_std_delay(), 0); if (fleed == 1 && !npc->get_flag(Obj_flags::si_tournament) && rand()%3 && gwin->add_dirty(npc)) { yelled++; if (can_yell) npc->say(first_flee, last_flee); } } /* * See if a spellbook is readied with a spell * available. * * Output: ->spellbook if so, else 0. */ Spellbook_object *Combat_schedule::readied_spellbook ( ) { Spellbook_object *book = 0; // Check both hands. Game_object *obj = npc->get_readied(Actor::lhand); if (obj && obj->get_info().get_shape_class() == Shape_info::spellbook) { book = static_cast (obj); if (book->can_do_spell(npc)) return book; } obj = npc->get_readied(Actor::rhand); if (obj && obj->get_info().get_shape_class() == Shape_info::spellbook) { book = static_cast (obj); if (book->can_do_spell(npc)) return book; } return 0; } /* * Set weapon 'max_range' and 'ammo'. Ready a new weapon if needed. */ void Combat_schedule::set_weapon ( ) { int points; spellbook = 0; Weapon_info *info = npc->get_weapon(points, weapon_shape); if (!info && // No weapon? !(spellbook = readied_spellbook()) && // No spellbook? // Not dragging? !gwin->is_dragging() && // And not dueling? npc->get_schedule_type() != Schedule::duel && state != wait_return) // And not waiting for boomerang. { npc->ready_best_weapon(); info = npc->get_weapon(points, weapon_shape); } if (!info) // Still nothing. { projectile_shape = ammo_shape = 0; projectile_range = 0; strike_range = 1; // Can always bite. is_thrown = returns = no_blocking = false; if (spellbook) // Did we find a spellbook? { projectile_range = 10; // Guessing. no_blocking = true; } } else { projectile_shape = info->get_projectile(); ammo_shape = info->get_ammo_consumed(); strike_range = info->get_striking_range(); projectile_range = info->get_projectile_range(); returns = info->returns(); is_thrown = info->is_thrown(); no_blocking = info->no_blocking(); if (ammo_shape) { Ammo_info *ainfo = ShapeID::get_info(ammo_shape).get_ammo_info(); if (ainfo) no_blocking = no_blocking || ainfo->no_blocking(); } } max_range = projectile_range > strike_range ? projectile_range : strike_range; if (state == strike || state == fire) state = approach; // Got to restart attack. } /* * See if we need a new opponent. */ inline int Need_new_opponent ( Game_window *gwin, Actor *npc ) { Game_object *opponent = npc->get_target(); Actor *act; // Nonexistent or dead? if (!opponent || ((act = opponent->as_actor()) != 0 && act->is_dead()) || // Or invisible? opponent->get_flag(Obj_flags::invisible)) return 1; // See if off screen. return Off_screen(gwin, opponent) && !Off_screen(gwin, npc); } /* * Use one unit of ammo. * * Output: Actual ammo shape. * 0 if failed. */ static int Use_ammo ( Actor *npc, int ammo, // Ammo family shape. int proj // Projectile shape. ) { Game_object *aobj = npc->get_readied(Actor::ammo); if (!aobj) return 0; int actual_ammo = aobj->get_shapenum(); if (!In_ammo_family(actual_ammo, ammo)) return 0; npc->remove(aobj); // Remove all. int quant = aobj->get_quantity(); aobj->modify_quantity(-1); // Reduce amount. if (quant > 1) // Still some left? Put back. npc->add_readied(aobj, Actor::ammo); // Use actual shape unless a different // projectile was specified. return ammo == proj ? actual_ammo : proj; } /* * Create. */ Combat_schedule::Combat_schedule ( Actor *n, Schedule_types prev_sched ) : Schedule(n), state(initial), prev_schedule(prev_sched), weapon_shape(0), ammo_shape(0), projectile_shape(0), spellbook(0), strike_range(0), projectile_range(0), max_range(0), practice_target(0), is_thrown(false), yelled(0), no_blocking(false), started_battle(false), fleed(0), failures(0), teleport_time(0) { Combat_schedule::set_weapon(); // Cache some data. Game_window *gwin = Game_window::get_instance(); Monster_info *minf = npc->get_info().get_monster_info(); can_yell = !minf || !minf->cant_yell(); } /* * Previous action is finished. */ void Combat_schedule::now_what ( ) { Game_window *gwin = Game_window::get_instance(); if (state == initial) // Do NOTHING in initial state so { // usecode can, e.g., set opponent. // Way far away (50 tiles)? if (npc->distance(gwin->get_camera_actor()) > 50) { npc->set_dormant(); return; // Just go dormant. } state = approach; npc->start(200, 200); return; } if (npc->get_flag(Obj_flags::asleep)) { npc->start(200, 1000); // Check again in a second. return; } // Running away? if (npc->get_attack_mode() == Actor::flee) { // If not in combat, stop running. if (fleed > 2 && !gwin->in_combat() && npc->get_party_id() >= 0) // WARNING: Destroys ourself. npc->set_schedule_type(Schedule::follow_avatar); else run_away(); return; } // Check if opponent still breathes. if (Need_new_opponent(gwin, npc)) { npc->set_target(0); state = approach; } Game_object *opponent = npc->get_target(); // Flag for slimes: bool strange = npc->get_info().has_strange_movement() != false; switch (state) // Note: state's action has finished. { case approach: if (opponent) start_strike(); else approach_foe(); break; case strike: // He hasn't moved away? state = approach; // Back into queue. npc->start(gwin->get_std_delay(), strange ? 4*gwin->get_std_delay() : gwin->get_std_delay()); if (npc->get_footprint().enlarge(strike_range).intersects( opponent->get_footprint())) { int dir = npc->get_direction(opponent); if (!strange) // Avoid messing up slimes. npc->change_frame(npc->get_dir_framenum(dir, Actor::standing)); // Glass sword? Only 1 use. if (weapon_shape == 604) { npc->remove_quantity(1, weapon_shape, c_any_qual, c_any_framenum); Combat_schedule::set_weapon(); } // This may delete us! Actor *safenpc = npc; safenpc->set_target(opponent->attacked(npc)); // Strike but once at objects. Game_object *newtarg = safenpc->get_target(); if (newtarg && !newtarg->as_actor()) safenpc->set_target(0); return; // We may no longer exist! } break; case fire: // Range weapon. { failures = 0; state = approach; // Save shape (it might change). int ashape = ammo_shape, wshape = weapon_shape, pshape = projectile_shape; int delay = (strange || spellbook) ? 6*gwin->get_std_delay() : gwin->get_std_delay(); if (is_thrown) // Throwing the weapon? { if (returns) // Boomerang? { ashape = wshape; delay = (1 + npc->distance(opponent))* gwin->get_std_delay(); state = wait_return; } if (npc->remove_quantity(1, wshape, c_any_qual, c_any_framenum) == 0) { npc->add_dirty(); ashape = wshape; Combat_schedule::set_weapon(); } } else if (spellbook) { // Cast the spell. ashape = 0; // Just to be on the safe side... if (!spellbook->do_spell(npc, true)) Combat_schedule::set_weapon(); } else // Ammo required? ashape = ashape ? Use_ammo(npc, ashape, pshape) : (pshape ? pshape : wshape); if (ashape > 0) gwin->get_effects()->add_effect( new Projectile_effect(npc, opponent, ashape, wshape)); npc->start(gwin->get_std_delay(), delay); break; } case wait_return: // Boomerang should have returned. state = approach; npc->start(gwin->get_std_delay(), gwin->get_std_delay()); break; default: break; } if (failures > 5 && npc != gwin->get_camera_actor()) { // Too many failures. Give up for now. if (combat_trace) { cout << npc->get_name() << " is giving up" << endl; } if (npc->get_party_id() >= 0) { // Party member. npc->walk_to_tile( gwin->get_main_actor()->get_tile(), gwin->get_std_delay()); // WARNING: Destroys ourself. npc->set_schedule_type(Schedule::follow_avatar); } else if (!gwin->get_win_rect().intersects( gwin->get_shape_rect(npc))) { // Off screen? Stop trying. gwin->get_tqueue()->remove(npc); npc->set_dormant(); } else if (npc->get_alignment() == Npc_actor::friendly && prev_schedule != Schedule::combat) { // Return to normal schedule. npc->update_schedule(gclock->get_hour()/3, 7); if (npc->get_schedule_type() == Schedule::combat) npc->set_schedule_type(prev_schedule); } else { // Wander randomly. Tile_coord t = npc->get_tile(); int dist = 2+rand()%3; int newx = t.tx - dist + rand()%(2*dist); int newy = t.ty - dist + rand()%(2*dist); // Wait a bit. npc->walk_to_tile(newx, newy, t.tz, 2*gwin->get_std_delay(), rand()%1000); } } } /* * Npc just went dormant (probably off-screen). */ void Combat_schedule::im_dormant ( ) { if (npc->get_alignment() == Npc_actor::friendly && prev_schedule != npc->get_schedule_type() && npc->is_monster()) // Friendly, so end combat. npc->set_schedule_type(prev_schedule); } /* * Leaving combat. */ void Combat_schedule::ending ( int /* newtype */ ) { Game_window *gwin = Game_window::get_instance(); if (gwin->get_main_actor() == npc && // Not if called from usecode. !gwin->get_usecode()->in_usecode()) { // See if being a coward. find_opponents(); bool found = false; // Find a close-by enemy. Tile_coord pos = npc->get_tile(); for (Actor_queue::const_iterator it = opponents.begin(); it != opponents.end(); ++it) { Actor *opp = *it; Tile_coord opppos = opp->get_tile(); if (opppos.distance(pos) < (300/2)/c_tilesize && Fast_pathfinder_client::is_grabable(pos, opppos)) { found = true; break; } } if (found) Audio::get_ptr()->start_music_combat(CSRun_Away, false); } } /* * Create duel schedule. */ Duel_schedule::Duel_schedule ( Actor *n ) : Combat_schedule(n, duel), start(n->get_tile()), attacks(0) { started_battle = true; // Avoid playing music. } /* * Ready a bow-and-arrows. */ void Ready_duel_weapon ( Actor *npc, int wshape, // Weapon shape. int ashape // Ammo shape, or -1. ) { Game_map *gmap = Game_window::get_instance()->get_map(); Game_object *weap = npc->get_readied(Actor::lhand); if (!weap || weap->get_shapenum() != wshape) { // Need a bow. Game_object *newweap = npc->find_item(wshape, c_any_qual, c_any_framenum); if (newweap) // Have it? newweap->remove_this(1); else // Create new one. newweap = gmap->create_ireg_object(wshape, 0); if (weap) // Remove old item. weap->remove_this(1); npc->add(newweap, 1); // Should go in correct spot. if (weap) npc->add(weap, 1); } if (ashape == -1) // No ammo needed. return; // Now provide 1-3 arrows. Game_object *aobj = npc->get_readied(Actor::ammo); if (aobj) aobj->remove_this(); // Toss current ammo. Game_object *arrows = gmap->create_ireg_object(ashape, 0); int extra = rand()%3; // Add 1 or 2. if (extra) arrows->modify_quantity(extra); npc->add(arrows, 1); // Should go to right spot. } /* * Find dueling opponents. */ void Duel_schedule::find_opponents ( ) { opponents.clear(); attacks = 0; practice_target = 0; int r = rand()%3; if (r == 0) // First look for practice targets. { // Archery target: practice_target = npc->find_closest(735); if (practice_target) // Need bow-and-arrows. Ready_duel_weapon(npc, 597, 722); } if (!practice_target) // Fencing dummy or dueling opponent. { Ready_duel_weapon(npc, 602, -1); if (r == 1) practice_target = npc->find_closest(860); } Combat_schedule::set_weapon(); if (practice_target) { npc->set_target(practice_target); return; // Just use that. } Actor_vector vec; // Find all nearby NPC's. npc->find_nearby_actors(vec, c_any_shapenum, 24); for (Actor_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Actor *opp = *it; Game_object *oppopp = opp->get_target(); if (opp != npc && opp->get_schedule_type() == duel && (!oppopp || oppopp == npc)) if (rand()%2) opponents.push(opp); else opponents.push_front(opp); } } /* * Previous action is finished. */ void Duel_schedule::now_what ( ) { if (state == strike || state == fire) { attacks++; // Practice target full? if (practice_target && practice_target->get_shapenum() == 735 && practice_target->get_framenum() > 0 && practice_target->get_framenum()%3 == 0) { attacks = 0; // Break off. //++++++Should walk there. practice_target->change_frame(0); } } else { Combat_schedule::now_what(); return; } if (attacks%8 == 0) // Time to break off. { npc->set_target(0); Tile_coord pos = start; pos.tx += rand()%24 - 12; pos.ty += rand()%24 - 12; // Find a free spot. Tile_coord dest = Map_chunk::find_spot(pos, 3, npc, 1); if (dest.tx == -1 || !npc->walk_path_to_tile(dest, gwin->get_std_delay(), rand()%2000)) // Failed? Try again a little later. npc->start(250, rand()%3000); } else Combat_schedule::now_what(); } /* * Pause/unpause while in combat. */ void Combat::toggle_pause ( ) { if (!paused && mode == original) return; // Not doing that sort of thing. if (paused) { resume(); // Text is probably for debugging. eman->center_text("Combat resumed"); } else { gwin->get_tqueue()->pause(SDL_GetTicks()); eman->center_text("Combat paused"); paused = true; } } /* * Resume. */ void Combat::resume ( ) { if (!paused) return; gwin->get_tqueue()->resume(SDL_GetTicks()); paused = false; } exult-1.2/delobjs.cc0000644000175000001440000000342007726531050010127 /* * delobjs.cc - Game objects that have been removed, but need deleting. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "objs.h" #include #include "delobjs.h" using std::vector; struct Obj_with_time { Game_object *obj; unsigned int ticks; Obj_with_time(Game_object *o, unsigned int t) : obj(o), ticks(t) { } }; /* * Remove and delete all objects. */ void Deleted_objects::flush ( ) { typedef vector Obj_time_list; if (empty()) return; Obj_time_list keep; keep.reserve(100); // Wait at least 3 minutes. unsigned int curtime = SDL_GetTicks(); for(std::map::iterator X = begin(); X != end(); ++X) { Game_object *obj = (*X).first; int ticks = (*X).second; if (ticks < curtime) delete obj; else keep.push_back(Obj_with_time(obj, ticks)); } clear(); // Clear map. for (Obj_time_list::iterator it = keep.begin(); it != keep.end(); ++it) (*this)[(*it).obj] = (*it).ticks; } exult-1.2/txtscroll.h0000644000175000001440000000234407724430450010411 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TEXT_SCROLLER_H #define TEXT_SCROLLER_H #include #include class Game_window; class Shape_file; class Font; class Palette; class TextScroller { private: Font *font; Shape *shapes; std::vector *text; public: TextScroller(const char *archive, int index, Font *fnt, Shape *shp); ~TextScroller(); bool run(Game_window *gwin); int show_line(Game_window *gwin, int left, int right, int y, int index); int get_count(); }; #endif exult-1.2/palette.h0000644000175000001440000000537510003012476010004 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PALETTE_H #define PALETTE_H class Image_window8; /* * Palette #'s in 'palettes.flx': */ const int PALETTE_DAY = 0; const int PALETTE_DUSK = 1; const int PALETTE_DAWN = 1; // Think this is it. const int PALETTE_NIGHT = 2; const int PALETTE_INVISIBLE = 3; // When Avatar is invisible. // 4 looks just like #1. const int PALETTE_HAZE = 5; // 6 looks a little brighter than #2. // 7 is somewhat warmer. Torch? const int PALETTE_RED = 8; // Used when hit in combat. // 9 has lots of black. const int PALETTE_LIGHTNING = 10; class Palette { Image_window8 *win; unsigned char pal1[768]; unsigned char pal2[768]; int brightness; int max_val; int palette; // Palette #. bool faded_out; // true if faded palette to black. bool fades_enabled; public: Palette(); ~Palette(); // Fade palette in/out. void fade(int cycles, int inout, int pal_num = -1); bool is_faded_out() { return faded_out; } void flash_red(); // Flash red for a moment. // Set desired palette. void set(int pal_num, int new_brightness = -1, bool repaint=true); int get_brightness() // Percentage: 100 = normal. { return brightness; } // the user. void set_fades_enabled(bool f) { fades_enabled = f; } bool get_fades_enabled() const { return fades_enabled; } void apply(bool repaint=true); void load(const char *fname, int index, const char *xfname = 0, int xindex = -1); void set_brightness(int bright); void set_max_val(int max); int get_max_val(); void fade_in(int cycles); void fade_out(int cycles); int find_color(int r, int g, int b); void create_trans_table(unsigned char br, unsigned bg, unsigned bb, int alpha, unsigned char *table); void show(); void set_color(int nr, int r, int g, int b); unsigned char get_red(int nr) { return pal1[3*nr]; } unsigned char get_green(int nr) { return pal1[3*nr + 1]; } unsigned char get_blue(int nr) { return pal1[3*nr + 2]; } void set_palette (unsigned char palnew[768]); }; #endif exult-1.2/depcomp0000755000175000001440000002752510013577157007570 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # `libtool' can also be set to `yes' or `no'. depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. This file always lives in the current directory. # Also, the AIX compiler puts `$object:' at the start of each line; # $object doesn't have directory information. stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; tru64) # The Tru64 AIX compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. tmpdepfile1="$object.d" tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` if test "$libtool" = yes; then "$@" -Wc,-MD else "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a space and a tab in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. test -z "$dashmflag" && dashmflag=-M ( IFS=" " case " $* " in *" --mode=compile "*) # this is libtool, let us make it quiet for arg do # cycle over the arguments case "$arg" in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) # X makedepend ( shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift;; -*) ;; *) set fnord "$@" "$arg"; shift;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tail +3 "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 exult-1.2/desktop/0000777000175000001440000000000010062225335007725 5exult-1.2/desktop/exult.desktop0000644000175000001440000000025310026506303012372 [Desktop Entry] Encoding=UTF-8 Name=Exult Comment=Exult Ultima 7 Engine Exec=exult Icon=exult.png Terminal=false Type=Application Categories=Application;Game;RolePlaying; exult-1.2/desktop/Makefile.am0000644000175000001440000000021710026506303011672 icondir = $(datadir)/icons dist_icon_DATA = exult.png desktopdir = $(datadir)/applications dist_desktop_DATA = exult.desktop CLEANFILES = *~ exult-1.2/desktop/Makefile.in0000644000175000001440000001702210061527071011711 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ icondir = $(datadir)/icons dist_icon_DATA = exult.png desktopdir = $(datadir)/applications dist_desktop_DATA = exult.desktop CLEANFILES = *~ subdir = desktop mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(dist_desktop_DATA) $(dist_icon_DATA) DIST_COMMON = $(dist_desktop_DATA) $(dist_icon_DATA) Makefile.am \ Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu desktop/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: install-dist_desktopDATA: $(dist_desktop_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(desktopdir) @list='$(dist_desktop_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(desktopdir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(desktopdir)/$$f; \ done uninstall-dist_desktopDATA: @$(NORMAL_UNINSTALL) @list='$(dist_desktop_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(desktopdir)/$$f"; \ rm -f $(DESTDIR)$(desktopdir)/$$f; \ done install-dist_iconDATA: $(dist_icon_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(icondir) @list='$(dist_icon_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(icondir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(icondir)/$$f; \ done uninstall-dist_iconDATA: @$(NORMAL_UNINSTALL) @list='$(dist_icon_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(icondir)/$$f"; \ rm -f $(DESTDIR)$(icondir)/$$f; \ done tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(desktopdir) $(DESTDIR)$(icondir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-dist_desktopDATA install-dist_iconDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-dist_desktopDATA uninstall-dist_iconDATA \ uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-dist_desktopDATA install-dist_iconDATA \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool uninstall \ uninstall-am uninstall-dist_desktopDATA uninstall-dist_iconDATA \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/desktop/exult.png0000644000175000001440000000447007333356410011523 PNG  IHDR00WgAMA aIDATxYiLY P 4(.( ڌQ tF#FE}ظB5" ⾎F`DP2tVU㦨W޽FD4JMYY6''qɒ%no ϟ?b_TQQ̴VYRw5ϟP^^n{JKKuzCI$ׯ'Oʉ'dȑ.auhhh˗/mvT۽{u֩O:%ϟ\9} ^۶mԭ[w͛7uV={N-YAeѢErE:W=aևQ{7nNϘ1Ck׮j*9xN|=z888 (O'$$3A&߲eG%|GGNJ1cHaa;vLYtԪUK6lXco޼zxx8p*>I -`M6MΜ9:tH"""pwMݻw_.**V͛7[ EbU'"Ƅ (f >>>  `JXXz 'R8h z f@pB7$SZ@ oG+`'shIHH) #Li' $F:!ջaY86ƚ5k\>EIƦ;|{}ZЪ'f7o^ݒe0tM6mjkqjQ:f+%IENDB`exult-1.2/menulist.cc0000644000175000001440000001663507724430450010361 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "menulist.h" #include "exult.h" #include "font.h" #include "gamewin.h" #include "mouse.h" #include "rect.h" #include "shapeid.h" // MenuEntry: a selectable menu entry (a button) MenuEntry::MenuEntry(Shape_frame *on, Shape_frame *off, int xpos, int ypos) { frame_on = on; frame_off = off; int max_width = on->get_width()>off->get_width()?on->get_width():off->get_width(); int max_height = on->get_height()>off->get_height()?on->get_height():off->get_height(); x = xpos; y1 = y = ypos; x1 = xpos-max_width/2; x2 = x1+max_width; y2 = y1+max_height; selected = false; dirty = true; } void MenuEntry::paint(Game_window *gwin) { if (!dirty) return; dirty = false; Shape_frame *shape; if(selected) shape = frame_on; else shape = frame_off; Shape_manager::get_instance()->paint_shape( x-shape->get_width()/2, y, shape); gwin->get_win()->show(x1,y1,x2-x1+1,y2-y1+1); } bool MenuEntry::handle_event(SDL_Event& event) { return((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN) || event.type == SDL_MOUSEBUTTONUP); } // MenuChoice: a multiple-choice menu entry MenuChoice::MenuChoice(Shape_frame *on, Shape_frame *off, int xpos, int ypos, Font *fnt) { frame_on = on; frame_off = off; int max_width = on->get_width()>off->get_width()?on->get_width():off->get_width(); int max_height = on->get_height()>off->get_height()?on->get_height():off->get_height(); x = xpos; x1 = x-max_width; y1 = y = ypos; x2 = x1 + max_width; y2 = y1 + max_height; selected = false; choice = -1; font = fnt; max_choice_width = 0; choices = new std::vector(); } void MenuChoice::add_choice(const char *s) { choices->push_back(std::string(s)); int len = font->get_text_width(s); max_choice_width = (len>max_choice_width)?len:max_choice_width; x2 = x+32+max_choice_width; } void MenuChoice::paint(Game_window *gwin) { if (!dirty) return; dirty = false; Shape_frame *shape; if(selected) shape = frame_on; else shape = frame_off; Shape_manager::get_instance()->paint_shape( x-shape->get_width(), y, shape); gwin->get_win()->show(x1,y1,x2-x1+1,y2-y1+1); if(choice>=0) { gwin->get_win()->fill8(0, max_choice_width, font->get_text_height(), x+32, y); font->draw_text(gwin->get_win()->get_ib8(), x+32, y, (*choices)[choice].c_str()); gwin->get_win()->show(x+32,y, x+32+max_choice_width, y+font->get_text_height()); } } bool MenuChoice::handle_event(SDL_Event& event) { if(event.type==SDL_MOUSEBUTTONUP) { dirty = true; choice++; if(choice>=choices->size()) choice = 0; } else if(event.type==SDL_KEYDOWN) { switch(event.key.keysym.sym) { case SDLK_LEFT: dirty = true; choice--; if(choice<0) choice = choices->size()-1; break; case SDLK_RIGHT: dirty = true; choice++; if(choice>=choices->size()) choice = 0; break; default: break; } } return false; } MenuList::~MenuList() { MenuObject *entry; for(int i=0; isize(); i++) { entry = (*entries)[i]; delete entry; } delete entries; } void MenuList::set_selection(int sel) { MenuObject *entry; // deselect the previous entry if (selected) { entry = (*entries)[selection]; entry->set_selected(false); } // select the new one selected = true; selection = sel; entry = (*entries)[selection]; entry->set_selected(true); } void MenuList::set_selection(int x, int y) { MenuObject *entry; // deselect the previous one, unless nothing changed if (selected) { entry = (*entries)[selection]; if (entry->is_mouse_over(x, y)) return; entry->set_selected(false); } // select the new one, and return when found for(int i=0; isize(); i++) { entry = (*entries)[i]; if(entry->is_mouse_over(x, y)) { entry->set_selected(true); selected = true; selection = i; return; } } // nothing has been selected selected = false; } int MenuList::handle_events(Game_window *gwin, Mouse *mouse) { unsigned char mouse_visible; int count = entries->size(); bool exit_loop = false; int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); SDL_Event event; for(int i=0; idirty = true; gwin->show(1); mouse->show(); do { mouse_visible = mouse->is_onscreen(); if (mouse_visible) mouse->hide(); // redraw items if they're dirty for(int i=0; ipaint(gwin); } // redraw mouse if visible if (mouse_visible) { mouse->show(); mouse->blit_dirty(); } SDL_WaitEvent(&event); if(event.type==SDL_MOUSEMOTION) { mouse->hide(); mouse->move(event.motion.x / scale, event.motion.y / scale); set_selection(event.motion.x / scale, event.motion.y / scale); mouse->show(); mouse->blit_dirty(); } else if(event.type==SDL_MOUSEBUTTONDOWN) { if (!mouse_visible) { // if invisible, redraw mouse set_selection(event.button.x / scale, event.button.y / scale); mouse->show(); mouse->blit_dirty(); } } else if(event.type==SDL_MOUSEBUTTONUP) { MenuObject *entry = (*entries)[selection]; if (entry->is_mouse_over( event.button.x / scale, event.button.y / scale)) { exit_loop = entry->handle_event(event); } } else if(event.type==SDL_KEYDOWN) { mouse->hide(); mouse->blit_dirty(); switch(event.key.keysym.sym) { case SDLK_x: if(event.key.keysym.mod & KMOD_ALT) { return -1; } break; #if defined(MACOS) || defined(MACOSX) case SDLK_q: if(event.key.keysym.mod & KMOD_META) { return -1; } break; #endif case SDLK_UP: if (!selected) { // if unselected (by 'MouseOut' event), just re-select set_selection(selection); continue; } if(selection<=0) set_selection(count-1); else set_selection(selection-1); continue; case SDLK_DOWN: if (!selected) { // if unselected (by 'MouseOut' event), just re-select set_selection(selection); continue; } if(selection>=(count-1)) set_selection(0); else set_selection(selection+1); continue; case SDLK_s: if ((event.key.keysym.mod & KMOD_ALT) && (event.key.keysym.mod & KMOD_CTRL)) make_screenshot(true); default: { // let key be processed by selected menu-item if(selected) { MenuObject *entry = (*entries)[selection]; exit_loop = entry->handle_event(event); } } break; } } else if(event.type==SDL_QUIT) { return -1; } } while(!exit_loop); mouse->hide(); return selection; } exult-1.2/windrag.h0000644000175000001440000001157210054030532007774 #ifndef INCL_WINDRAG #define INCL_WINDRAG #if defined(WIN32) && defined(USE_EXULTSTUDIO) && !defined(UNDER_CE) #include "u7drag.h" #include #include "utils.h" // A useful structure for Winstudioobj class windragdata { sint32 id; uint32 size; // Size of data unsigned char * data; public: inline unsigned char *get_data() { return data; } inline const int get_id() { return id; } inline const int get_size() { return size; } // Default constructor inline windragdata() : size(0), data(0) { } // Copy constructor inline windragdata(windragdata &o) : id(o.id), size(o.size), data(new unsigned char [o.size]) { std::memcpy(data, o.data, size); } // Read from buffer inline windragdata(unsigned char *buf) :data(0) { operator = (buf); } inline windragdata(sint32 i, uint32 s, unsigned char * d) : id(i), size(s), data(new unsigned char [s]) { std::memcpy(data, d, size); } // Destructor inline ~windragdata() { delete [] data; } inline void serialize(unsigned char *buf) { Write4(buf, id); Write4(buf, size); std::memcpy(buf, data, size); } inline windragdata & operator = (unsigned char *buf) { delete [] data; id = Read4(buf); size = Read4(buf); data = new unsigned char [size]; std::memcpy(data, buf, size); return *this; } // Copy constructor inline windragdata & operator = (windragdata &o) { delete [] data; id = o.id; size = o.size; data = new unsigned char [size]; std::memcpy(data, o.data, size); return *this; } inline void assign(sint32 i, uint32 s, unsigned char * d) { delete [] data; id = i; size = s; data = new unsigned char [s]; std::memcpy(data, d, size); } }; /* * The 'IDropTarget' implementation */ class FAR Windnd : public IDropTarget { private: HWND gamewin; DWORD m_cRef; void *udata; Move_shape_handler_fun move_shape_handler; Move_combo_handler_fun move_combo_handler; Drop_shape_handler_fun shape_handler; Drop_chunk_handler_fun chunk_handler; Drop_shape_handler_fun face_handler; Drop_combo_handler_fun combo_handler; // Used for when dragging the mouse over the exult window int drag_id; int prevx, prevy; union { struct { int file,shape,frame; } shape; struct { int chunknum; } chunk; struct { int xtiles, ytiles; int right, below, cnt; U7_combo_data *combo; } combo; } data; public: Windnd(HWND hgwnd, Move_shape_handler_fun, Move_combo_handler_fun, Drop_shape_handler_fun, Drop_chunk_handler_fun, Drop_combo_handler_fun); Windnd(HWND hgwnd, Drop_shape_handler_fun shapefun, Drop_chunk_handler_fun cfun, Drop_shape_handler_fun facefun, void *d); ~Windnd(); STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); STDMETHOD(DragEnter)(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect); STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect); STDMETHOD(DragLeave)(void); STDMETHOD(Drop)(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect); bool is_valid(IDataObject * pDataObject); static void CreateStudioDropDest(Windnd *& windnd, HWND &hWnd, Drop_shape_handler_fun shapefun, Drop_chunk_handler_fun cfun, Drop_shape_handler_fun facefun, void *udata); static void DestroyStudioDropDest(Windnd *& windnd, HWND &hWnd); }; /* * The IDropSource implementation */ class FAR Windropsource : public IDropSource { private: DWORD m_cRef; HWND drag_shape; HBITMAP drag_bitmap; int shw, shh; public: Windropsource(HBITMAP pdrag_bitmap, int x0, int y0); ~Windropsource(); STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed,DWORD grfKeyState); STDMETHOD(GiveFeedback)(DWORD dwEffect); }; /* * The IDataObject implementation */ class FAR Winstudioobj : public IDataObject { private: DWORD m_cRef; HBITMAP drag_image; windragdata data; public: Winstudioobj(windragdata pdata); ~Winstudioobj(); STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); STDMETHOD(GetData)(FORMATETC * pFormatetc, STGMEDIUM * pmedium); STDMETHOD(GetDataHere)(FORMATETC * pFormatetc, STGMEDIUM * pmedium); STDMETHOD(QueryGetData)( FORMATETC * pFormatetc ); STDMETHOD(GetCanonicalFormatEtc)( FORMATETC * pFormatetcIn, FORMATETC * pFormatetcOut ); STDMETHOD(SetData)( FORMATETC * pFormatetc, STGMEDIUM * pmedium, BOOL fRelease ); STDMETHOD(EnumFormatEtc)( DWORD dwDirection, IEnumFORMATETC ** ppenumFormatetc ); STDMETHOD(DAdvise)( FORMATETC * pFormatetc, DWORD advf, IAdviseSink * pAdvSink, DWORD * pdwConnection ); STDMETHOD(DUnadvise)( DWORD dwConnection ); STDMETHOD(EnumDAdvise)( IEnumSTATDATA ** ppenumAdvise ); }; #endif #endif exult-1.2/ready.h0000644000175000001440000000354307724430450007461 /* * ready.h - Information from the 'ready.dat' file. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_READY #define INCL_READY 1 /* * Types from 'ready.dat' describing how a shape may be worn: */ enum Ready_type { other = 0x00, // Anything else. spell = 0x01, // 1-handed spell. one_handed_weapon = 0x08, neck_armor = 0x20, torso_armor = 0x28, ring = 0x30, ammunition = 0x40, head_armor = 0x48, // I.e., helm. leg_armor = 0x50, // I.e., leggings. foot_armor = 0x58, // I.e., boots. // triple_crossbow_bolts? = 0x78, tongs = 0x90, two_handed_weapon = 0xa0, other_spell = 0xa1, // #676, gloves = 0xa8 }; // Serpent Isle Ready types enum Ready_type_SI { other_si = 0x00, // Anything else. spell_si = 0x01, // 1-handed spell. one_handed_si = 0x08, cloak_si = 0x10, amulet_si = 0x18, helm_si = 0x20, gloves_si = 0x28, usecode_container_si = 0x30, ring_si = 0x40, earrings_si = 0x48, ammo_si = 0x50, belt_si = 0x58, armour_si = 0x60, boots_si = 0x68, leggings_si = 0x70, backpack_si = 0x78, // Diaper as well????? two_handed_si = 0xa0, other_spell_si = 0xa1 // #676, }; #endif /* INCL_READY */ exult-1.2/exult.cc0000644000175000001440000015306710054031466007655 /** ** Exult.cc - Multiplatform Ultima 7 game engine ** ** Written: 7/22/98 - JSF **/ /* * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include #endif #include #define Font _XFont_ #include #undef Font #ifdef USE_EXULTSTUDIO /* Only needed for communication with exult studio */ #if HAVE_SYS_TIME_H #include #endif #ifdef WIN32 #include "windrag.h" #elif defined(XWIN) #include "xdrag.h" #endif #include "server.h" #include "chunks.h" #include "chunkter.h" #endif #if (defined(USECODE_DEBUGGER) && defined(XWIN)) #include #endif #include "Audio.h" #include "Configuration.h" #include "Gump_manager.h" #include "Scroll_gump.h" #include "actors.h" #include "args.h" #include "cheat.h" #include "effects.h" #include "exult.h" #include "exultmenu.h" #include "fnames.h" #include "font.h" #include "game.h" #include "gamewin.h" #include "gamemap.h" #include "gump_utils.h" #include "keyactions.h" #include "keys.h" #include "mouse.h" #include "ucmachine.h" #include "utils.h" #include "version.h" #include "u7drag.h" #include "drag.h" #include "palette.h" #include "glshape.h" #include "combat_opts.h" #include "exult_flx.h" #include "exult_bg_flx.h" #include "exult_si_flx.h" #include "crc.h" #ifndef UNDER_CE using std::atof; using std::cerr; using std::cout; using std::endl; using std::atexit; using std::exit; using std::toupper; using std::string; using std::vector; #endif Configuration *config = 0; KeyBinder *keybinder = 0; /* * Globals: */ Game_window *gwin = 0; quitting_time_enum quitting_time = QUIT_TIME_NO; bool intrinsic_trace = false; // Do we trace Usecode-intrinsics? int usecode_trace = 0; // Do we trace Usecode-instructions? // 0 = no, 1 = short, 2 = long bool combat_trace = false; // show combat messages? // Save game compression level int save_compression = 1; bool ignore_crc = false; const std::string c_empty_string; #if 0 && USECODE_DEBUGGER bool usecode_debugging=false; // Do we enable the usecode debugger? extern void initialise_usecode_debugger(void); #endif struct resolution { int x; int y; int scale; } res_list[] = { { 320, 200, 1 }, { 320, 240, 1 }, { 400, 300, 1 }, { 320, 200, 2 }, { 320, 240, 2 }, { 400, 300, 2 }, { 512, 384, 1 }, { 640, 480, 1 }, { 800, 600, 1 } }; int num_res = sizeof(res_list)/sizeof(struct resolution); int current_res = 0; #ifdef XWIN int xfd = 0; // X connection #. static class Xdnd *xdnd = 0; #elif defined(WIN32) static HWND hgwin; static class Windnd *windnd = 0; #endif /* * Local functions: */ static int exult_main(const char *); static void Init(); static int Play(); static int Get_click(int& x, int& y, char *chr, bool drag_ok, Paintable *p); static int find_resolution(int w, int h, int s); static void set_resolution (int new_res, bool save); #ifdef USE_EXULTSTUDIO static void Move_dragged_shape(int shape, int frame, int x, int y, int prevx, int prevy, bool show); static void Move_dragged_combo(int xtiles, int ytiles, int tiles_right, int tiles_below, int x, int y, int prevx, int prevy, bool show); static void Drop_dragged_shape(int shape, int frame, int x, int y, void *d); static void Drop_dragged_chunk(int chunknum, int x, int y, void *d); static void Drop_dragged_combo(int cnt, U7_combo_data *combo, int x, int y, void *d); #endif static void BuildGameMap(); static void Handle_events(); static void Handle_event(SDL_Event& event); static void get_game_paths(const string &gametitle); /* * Statics: */ static bool dragging = false; // Object or gump being moved. static bool dragged = false; // Flag for when obj. moved. static bool run_bg = false; // skip menu and run bg static bool run_si = false; // skip menu and run si static string arg_gamename = "default"; // cmdline arguments static string arg_configfile = ""; static int arg_buildmap = -1; static bool arg_nomenu = false; /* * A handy breakpoint. */ static void Breakpoint ( ) { return; } #if (defined(XWIN) && HAVE_SIGNAL_H && HAVE_SYS_WAIT_H) // a SIGCHLD handler to properly clean up forked playmidi processes (if any) #include #include void sigchld_handler(int sig) { waitpid(-1, 0, WNOHANG); } #endif /* * Main program. */ int main ( int argc, char *argv[] ) { #ifdef BEOS // get exult path int counti; char datapath[256]; for (counti=strlen(argv[0]) ; argv[0][counti]!='/' ; counti--); strncpy(datapath, argv[0], counti); chdir(datapath); #endif #if (defined(XWIN) && HAVE_SIGNAL_H && HAVE_SYS_WAIT_H) signal(SIGCHLD, sigchld_handler); #endif bool needhelp=false; bool showversion=false; int result; Args parameters; // Declare everything from the commandline that we're interested in. parameters.declare("-h",&needhelp,true); parameters.declare("--help",&needhelp,true); parameters.declare("/?",&needhelp,true); parameters.declare("/h",&needhelp,true); parameters.declare("--bg",&run_bg,true); parameters.declare("--si",&run_si,true); parameters.declare("--nomenu", &arg_nomenu, true); parameters.declare("-v",&showversion,true); parameters.declare("--version",&showversion,true); parameters.declare("--game",&arg_gamename,"default"); parameters.declare("--buildmap",&arg_buildmap,-1); parameters.declare("--nocrc",&ignore_crc,true); parameters.declare("-c",&arg_configfile,""); // Process the args parameters.process(argc,argv); if(needhelp) { cerr << "Usage: exult [--help|-h] [-v|--version] [-c configfile]"<\tRun original game" << endl << "--buildmap\tCreate a fullsize map of the game world in u7map??.pcx" << endl << "\t\t(0 = all roofs, 1 = no level 2 roofs, 2 = no roofs)" << endl << "\t\tonly valid when used together with --bg or --si" << endl << "\t\t(WARNING: requires big amounts of RAM, HD space and time!)" << endl << "--nocrc\t\tDon't check crc's of .flx files" << endl; exit(1); } if (run_bg && run_si) { cerr << "Error: You may only specify either -bg or -si!" << endl; exit(1); } if(showversion) { getVersionInfo(cerr); return 0; } try { result = exult_main(argv[0]); } catch( const quit_exception & e ) { result = 0; } catch( const exult_exception & e ) { cerr << "============================" << endl << "An exception occured: " << endl << e.what() << endl << "errno: " << e.get_errno() << endl; if( e.get_errno() != 0) perror("Error Description"); cerr << "============================" << endl; } return result; } /* * Main program. */ int exult_main(const char *runpath) { string data_path; string music_path; // output version info getVersionInfo(cout); // Read in configuration file config = new Configuration; if (arg_configfile != "") { config->read_abs_config_file(arg_configfile); } else { config->read_config_file(USER_CONFIGURATION_FILE); } // Setup virtual directories config->value("config/disk/data_path",data_path,EXULT_DATADIR); add_system_path("", data_path); if (!U7exists("/exult.flx")) { add_system_path("", EXULT_DATADIR); if (!U7exists("/exult.flx")) { add_system_path("", "data"); if(!U7exists("/exult.flx")) { char *sep = std::strrchr(runpath,'/'); if (!sep) sep = std::strrchr(runpath,'\\'); int plen = sep-runpath; char *dpath = new char[plen+10]; std::strncpy(dpath, runpath, plen+1); dpath[plen+1] = 0; std::strcat(dpath,"data"); cerr << "dpath = " << dpath << endl; add_system_path("",dpath); if(!U7exists("/exult.flx")) { // We've tried them all... cerr << "Could not find 'exult.flx' anywhere." << endl; cerr << "Please make sure Exult is correctly installed," << endl; cerr << "and the Exult data path is specified in the configuration file." << endl; cerr << "(See the README file for more information)" << endl; exit(-1); } } } } std::string default_music = get_system_path("/music"); config->value("config/disk/music_path",music_path,default_music.c_str()); add_system_path("", music_path); add_system_path("", "static"); add_system_path("", "gamedat"); add_system_path("", "patch"); // add_system_path("", "savegame"); add_system_path("", "."); std::cout << "Exult path settings:" << std::endl; std::cout << "Data : " << get_system_path("") << std::endl; std::cout << "Digital music : " << get_system_path("") << std::endl; std::cout << std::endl; // Check CRCs of our .flx files bool crc_ok = true; uint32 crc = crc32_syspath("/exult.flx"); if (crc != EXULT_FLX_CRC32) { crc_ok = false; cerr << "exult.flx has a wrong checksum!" << endl; } if (U7exists("/exult_bg.flx")) { if (crc32_syspath("/exult_bg.flx") != EXULT_BG_FLX_CRC32) { crc_ok = false; cerr << "exult_bg.flx has a wrong checksum!" << endl; } } if (U7exists("/exult_si.flx")) { if (crc32_syspath("/exult_si.flx") != EXULT_SI_FLX_CRC32) { crc_ok = false; cerr << "exult_si.flx has a wrong checksum!" << endl; } } bool config_ignore_crc; config->value("config/disk/no_crc",config_ignore_crc); ignore_crc |= config_ignore_crc; if (!ignore_crc && !crc_ok) { cerr << "This usually means the file(s) mentioned above are " << "from a different version" << endl << "of Exult than this one. Please re-install Exult" << endl << endl << "(Note: if you modified the .flx files yourself, " << "you can skip this check" << endl << "by passing the --nocrc parameter.)" << endl; return 1; } // Convert from old format if needed vector vs=config->listkeys("config/disk/game",false); if(vs.size()==0) { // Convert from the older format string data_directory; config->value("config/disk/u7path",data_directory,"."); config->set("config/disk/game/blackgate/path",data_directory,true); const string s("blackgate"); config->set("config/disk/game/blackgate/title",s,true); vs.push_back(s); } get_game_paths("blackgate"); get_game_paths("serpentisle"); // Enable tracing of intrinsics? config->value("config/debug/trace/intrinsics",intrinsic_trace); // Enable tracing of UC-instructions? string uctrace; config->value("config/debug/trace/usecode", uctrace, "no"); to_uppercase(uctrace); if (uctrace == "YES") usecode_trace = 1; else if (uctrace == "VERBOSE") usecode_trace = 2; else usecode_trace = 0; config->value("config/debug/trace/combat",combat_trace); // Save game compression level config->value("config/disk/save_compression_level", save_compression, 1); if (save_compression < 0 || save_compression > 2) save_compression = 1; config->set("config/disk/save_compression_level", save_compression, true); #if 0 && USECODE_DEBUGGER // Enable usecode debugger config->value("config/debug/debugger/enable",usecode_debugging); initialise_usecode_debugger(); #endif #if (defined(USECODE_DEBUGGER) && defined(XWIN)) signal(SIGUSR1, SIG_IGN); #endif cheat.init(); #ifdef UNDER_CE GXOpenInput(); GXKeyList keys = GXGetDefaultKeys(GX_LANDSCAPEKEYS); std::cout << "Up " << keys.vkUp << std::endl; std::cout << "Down " << keys.vkDown << std::endl; std::cout << "Left " << keys.vkLeft << std::endl; std::cout << "Right " << keys.vkRight << std::endl; std::cout << "A " << keys.vkA << std::endl; std::cout << "B " << keys.vkB << std::endl; std::cout << "C " << keys.vkC << std::endl; std::cout << "Start " << keys.vkStart << std::endl; #endif Init(); // Create main window. cheat.finish_init(); Mouse::mouse = new Mouse(gwin); Mouse::mouse->set_shape(Mouse::hand); int result = Play(); // start game #ifdef UNDER_CE GXCloseInput(); #endif #if defined(WIN32) && defined(USE_EXULTSTUDIO) // Currently, leaving the game results in destruction of the window. // Maybe sometime in the future, there is an option like "return to // main menu and select another scenario". Becaule DnD isn't registered until // you really enter the game, we remove it here to prevent possible bugs // invilved with registering DnD a second time over an old variable. RevokeDragDrop(hgwin); delete windnd; #endif return result; } /* * Calculate paths for the given game, using the config file and * falling back to defaults if necessary. These are stored in * per-game system_path entries, which are then used later once the * game is selected. */ static void get_game_paths(const string &gametitle) { std::string data_directory, static_dir, gamedat_dir, savegame_dir, default_dir, system_path_tag(to_uppercase(gametitle)), config_path("config/disk/game/" + gametitle + "/path"); config->value(config_path.c_str(), data_directory, "."); if (data_directory == ".") config->set(config_path.c_str(), data_directory, true); #if 0 cout << "setting " << gametitle << " game directories to: " << data_directory << endl; #endif config_path = "config/disk/game/" + gametitle + "/static_path"; default_dir = data_directory + "/static"; config->value(config_path.c_str(), static_dir, default_dir.c_str()); add_system_path("<" + system_path_tag + "_STATIC>", static_dir); #if 0 cout << "setting " << gametitle << " static directory to: " << static_dir << endl; #endif const char *home = 0; // Will get $HOME. string home_game(""); // Gets $HOME/.exult/gametitle. config_path = "config/disk/game/" + gametitle + "/gamedat_path"; default_dir = data_directory + "/gamedat"; config->value(config_path.c_str(), gamedat_dir, ""); #if (!defined(WIN32) && !defined(MACOS)) if (gamedat_dir == "" && // Not set? // And default doesn't exist? !U7exists(default_dir.c_str()) && (home = getenv("HOME")) != 0) { home_game = home; home_game += "/.exult"; // Create $HOME/.exult/gametitle. U7mkdir(home_game.c_str(), 0755); home_game = home_game + '/' + gametitle; U7mkdir(home_game.c_str(), 0755); // Successfully created dir? if (U7exists(home_game.c_str())) { // Use $HOME/.exult/gametitle/gamedat. gamedat_dir = home_game + "/gamedat"; config->set(config_path.c_str(), gamedat_dir.c_str(), true); } else home_game = ""; // Failed. } #endif if (gamedat_dir == "") // Didn't create it in $HOME/.exult? gamedat_dir = default_dir; add_system_path("<" + system_path_tag + "_GAMEDAT>", gamedat_dir); #if 0 cout << "setting " << gametitle << " gamedat directory to: " << gamedat_dir << endl; #endif config_path = "config/disk/game/" + gametitle + "/savegame_path"; if (home_game == "") config->value(config_path.c_str(), savegame_dir, data_directory.c_str()); else { // Store saves under $HOME/.... config->value(config_path.c_str(), savegame_dir, home_game.c_str()); config->set(config_path.c_str(), savegame_dir.c_str(), true); } add_system_path("<" + system_path_tag + "_SAVEGAME>", savegame_dir); #if 0 cout << "setting " << gametitle << " savegame directory to: " << savegame_dir << endl; #endif config_path = "config/disk/game/" + gametitle + "/patch"; string patch_directory; default_dir = data_directory + "/patch"; config->value(config_path.c_str(), patch_directory, default_dir.c_str()); add_system_path("<" + system_path_tag + "_PATCH>", patch_directory.c_str()); } namespace ExultIcon { #include "exulticon.h" } static void SetIcon() { SDL_Surface* iconsurface = SDL_CreateRGBSurfaceFrom(ExultIcon::header_data, ExultIcon::width, ExultIcon::height, 8, ExultIcon::width, 0, 0, 0, 0); SDL_Color iconpal[256]; for (int i = 0; i < 256; ++i) { iconpal[i].r = ExultIcon::header_data_cmap[i][0]; iconpal[i].g = ExultIcon::header_data_cmap[i][1]; iconpal[i].b = ExultIcon::header_data_cmap[i][2]; } SDL_SetPalette(iconsurface, SDL_LOGPAL, iconpal, 0, 256); SDL_SetColorKey(iconsurface, SDL_SRCCOLORKEY, 0); SDL_WM_SetIcon(iconsurface, 0); SDL_FreeSurface(iconsurface); } /* * Initialize and create main window. */ static void Init ( ) { Uint32 init_flags = SDL_INIT_VIDEO|SDL_INIT_TIMER; #ifdef NO_SDL_PARACHUTE init_flags |= SDL_INIT_NOPARACHUTE; #endif if (SDL_Init(init_flags) < 0) { cerr << "Unable to initialize SDL: " << SDL_GetError() << endl; exit(-1); } std::atexit(SDL_Quit); SDL_SysWMinfo info; // Get system info. SDL_GetWMInfo(&info); #ifdef USE_EXULTSTUDIO // Want drag-and-drop events. SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); #endif // KBD repeat should be nice. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); SDL_ShowCursor(0); SDL_VERSION(&info.version); SetIcon(); int w, h, sc, sclr; // Default resolution is 320x200 with 2x scaling w = 320; h = 200; sc = 2; sclr = Image_window::SaI; int sw, sh, scaleval; string gr, gg, gb, scaler; config->value("config/video/width", sw, w); config->value("config/video/height", sh, h); config->value("config/video/scale_method", scaler, "---"); config->value("config/video/gamma/red", gr, "1.0"); config->value("config/video/gamma/green", gg, "1.0"); config->value("config/video/gamma/blue", gb, "1.0"); config->value("config/video/scale", scaleval, sc); sclr = Image_window::get_scaler_for_name(scaler); if (sclr == Image_window::NoScaler) config->set("config/video/scale_method","2xSaI",true); if (arg_buildmap >= 0) BuildGameMap(); Image_window8::set_gamma(atof(gr.c_str()), atof(gg.c_str()), atof(gb.c_str())); gwin = new Game_window(sw, sh, scaleval, sclr); current_res = find_resolution(sw, sh, scaleval); Audio::Init(); bool disable_fades; config->value("config/video/disable_fades", disable_fades, false); gwin->get_pal()->set_fades_enabled(!disable_fades); SDL_SetEventFilter(0); // Show the banner Exult_Game mygame; game = 0; // Figure out all the games' paths, before we store them. That // way, we don't have to recalculate them if we come back to the // main menu and make another selection. if (arg_gamename != "default") { // The user gave us a game title, so load that one's // paths. get_game_paths(arg_gamename); } store_system_paths(); do { reset_system_paths(); fontManager.reset(); U7FileManager::get_ptr()->reset(); const char *title = 0; if(game) delete game; if (run_bg) { mygame = BLACK_GATE; run_bg = false; } else if (run_si) { mygame = SERPENT_ISLE; run_si = false; } else if (arg_buildmap < 0 && arg_gamename != "default") { mygame = EXULT_DEVEL_GAME; title = arg_gamename.c_str(); } else { ExultMenu exult_menu(gwin); mygame = exult_menu.run(); } Game::create_game(mygame, title); Audio::get_ptr()->Init_sfx(); // Skip splash screen? bool skip_splash; config->value("config/gameplay/skip_splash", skip_splash); if(!skip_splash && // Skip intro. if devel. game. (Game::get_game_type() != EXULT_DEVEL_GAME || U7exists("/intro.dat"))) game->play_intro(); } while(!game->show_menu(arg_nomenu)); gwin->init_files(); gwin->read_gwin(); gwin->setup_game(); // This will start the scene. // Get scale factor for mouse. #ifdef USE_EXULTSTUDIO #ifndef WIN32 SDL_GetWMInfo(&info); xfd = ConnectionNumber(info.info.x11.display); Server_init(); // Initialize server (for map-editor). xdnd = new Xdnd(info.info.x11.display, info.info.x11.wmwindow, info.info.x11.window, Move_dragged_shape, Move_dragged_combo, Drop_dragged_shape, Drop_dragged_chunk, Drop_dragged_combo); #elif !defined(UNDER_CE) SDL_GetWMInfo(&info); Server_init(); // Initialize server (for map-editor). hgwin = info.window; OleInitialize(NULL); windnd = new Windnd(hgwin, Move_dragged_shape, Move_dragged_combo, Drop_dragged_shape, Drop_dragged_chunk, Drop_dragged_combo); if (FAILED(RegisterDragDrop(hgwin, windnd))) { cout << "Something's wrong with OLE2 ..." << endl; }; #endif #endif } /* * Play game. */ static int Play() { do { quitting_time = QUIT_TIME_NO; Handle_events(); if( quitting_time == QUIT_TIME_RESTART ) { Mouse::mouse->hide(); // Turn off mouse. gwin->read(); // Restart /////gwin->setup_game(); //// setup_game is already being called from inside //// of gwin->read(), so no need to call it here, I hope... } } while (quitting_time == QUIT_TIME_RESTART); delete gwin; delete Mouse::mouse; Audio::Destroy(); // Deinit the sound system. delete config; return (0); } #ifdef USE_EXULTSTUDIO // Shift-click means 'paint'. /* * Add a shape while map-editing. */ static void Paint_with_shape ( SDL_Event& event, bool dragging // Painting terrain. ) { static int lasttx = -1, lastty = -1; int scale = gwin->get_win()->get_scale(); int x = event.button.x/scale, y = event.button.y/scale; int tx = (gwin->get_scrolltx() + x/c_tilesize); int ty = (gwin->get_scrollty() + y/c_tilesize); if (dragging) // See if moving to a new tile. { if (tx == lasttx && ty == lastty) return; } lasttx = tx; lastty = ty; int shnum = cheat.get_edit_shape(); int frnum; SDLMod mod = SDL_GetModState(); if (mod & KMOD_ALT) // ALT? Pick random frame. { ShapeID id(shnum, 0); frnum = std::rand()%id.get_num_frames(); } else if (mod & KMOD_CTRL) // Cycle through frames. { frnum = cheat.get_edit_frame(); ShapeID id(shnum, 0); int nextframe = (frnum + 1)%id.get_num_frames(); cheat.set_edit_shape(shnum, nextframe); } else frnum = cheat.get_edit_frame(); Drop_dragged_shape(shnum, frnum, event.button.x, event.button.y, 0); } /* * Set a complete chunk while map-editing. */ static void Paint_with_chunk ( SDL_Event& event, bool dragging // Painting terrain. ) { static int lastcx = -1, lastcy = -1; int scale = gwin->get_win()->get_scale(); int x = event.button.x/scale, y = event.button.y/scale; int cx = (gwin->get_scrolltx() + x/c_tilesize)/c_tiles_per_chunk; int cy = (gwin->get_scrollty() + y/c_tilesize)/c_tiles_per_chunk; if (dragging) // See if moving to a new chunk. { if (cx == lastcx && cy == lastcy) return; } lastcx = cx; lastcy = cy; int chnum = cheat.get_edit_chunknum(); Drop_dragged_chunk(chnum, event.button.x, event.button.y, 0); } #endif /* * Handle events until a flag is set. */ static void Handle_events ( ) { uint32 last_repaint = 0; // For insuring animation repaints. uint32 last_rotate = 0; /* * Main event loop. */ while (!quitting_time) { #ifdef USE_EXULTSTUDIO Server_delay(); // Handle requests. #else Delay(); // Wait a fraction of a second. #endif // Mouse scale factor int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); Mouse::mouse->hide(); // Turn off mouse. Mouse::mouse_update = false; // Get current time. uint32 ticks = SDL_GetTicks(); Game::set_ticks(ticks); SDL_Event event; while (!quitting_time && SDL_PollEvent(&event)) Handle_event(event); // Animate unless dormant. if (gwin->have_focus() && !dragging) gwin->get_tqueue()->activate(ticks); // Moved this out of the animation loop, since we want movement to be // more responsive. Also, if the step delta is only 1 tile, // always check every loop if (!gwin->is_moving() || gwin->get_step_tile_delta() == 1) { int x, y;// Check for 'stuck' Avatar. int ms = SDL_GetMouseState(&x, &y); if (SDL_BUTTON(3) & ms) gwin->start_actor(x/scale, y/scale, Mouse::mouse->avatar_speed); else gwin->get_main_actor()->resting(50); } // Show animation every 1/20 sec. if (ticks > last_repaint + 50 || gwin->was_painted()) // This avoids jumpy walking: { // OpenGL? Repaint all each time. if (GL_manager::get_instance()) gwin->paint(); else gwin->paint_dirty(); while (ticks > last_repaint+50)last_repaint += 50; } Mouse::mouse->show(); // Re-display mouse. // Rotate less often if scaling and // not paletized. int rot_speed = 100 << (gwin->get_win()->is_palettized() || scale==1?0:1); if (ticks > last_rotate + rot_speed && !GL_manager::get_instance()) //++++Disable in OGL. { // (Blits in simulated 8-bit mode.) gwin->get_win()->rotate_colors(0xfc, 3, 0); gwin->get_win()->rotate_colors(0xf8, 4, 0); gwin->get_win()->rotate_colors(0xf4, 4, 0); gwin->get_win()->rotate_colors(0xf0, 4, 0); gwin->get_win()->rotate_colors(0xe8, 8, 0); gwin->get_win()->rotate_colors(0xe0, 8, 1); while (ticks > last_rotate + rot_speed) last_rotate += rot_speed; // Non palettized needs explicit blit. if (!gwin->get_win()->is_palettized()) gwin->set_painted(); } if (!gwin->show() && // Blit to screen if necessary. Mouse::mouse_update) // If not, did mouse change? Mouse::mouse->blit_dirty(); } } /* * Handle an event. This should work for all platforms, and should only * be called in 'normal' and 'gump' modes. */ static void Handle_event ( SDL_Event& event ) { // Mouse scale factor int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); bool dont_move_mode = gwin->main_actor_dont_move(); // We want this Gump_manager *gump_man = gwin->get_gump_man(); static bool right_on_gump = false; Gump *gump = 0; // For detecting double-clicks. static uint32 last_b1_click = 0, last_b3_click = 0; //cout << "Event " << (int) event.type << " received"<= 0 && // But always if painting. (cheat.get_edit_mode() == Cheat::paint || (SDL_GetModState() & KMOD_SHIFT))) { Paint_with_shape(event, false); break; } else if (cheat.get_edit_chunknum() >= 0 && cheat.get_edit_mode() == Cheat::paint_chunks) { Paint_with_chunk(event, false); break; } // Don't drag if not in 'move' mode. else if (cheat.get_edit_mode() != Cheat::move) break; } #endif dragging = gwin->start_dragging(x, y); //Mouse::mouse->set_shape(Mouse::hand); dragged = false; } // Move sprite toward mouse // when right button pressed. if (gwin->get_mouse3rd()) if (event.button.button == 2) { ActionTarget(0); } if (event.button.button == 3) { // Try removing old queue entry. gwin->get_tqueue()->remove(gwin->get_main_actor()); if (!dragging && // Causes crash if dragging. gump_man->can_right_click_close() && gump_man->gump_mode() && gump_man->find_gump(x, y, false)) { gump = 0; right_on_gump = true; } else gwin->start_actor(x, y, Mouse::mouse->avatar_speed); } if (event.button.button == 4 || event.button.button == 5) { if (!cheat()) break; SDLMod mod = SDL_GetModState(); if (event.button.button == 4) if (mod & KMOD_ALT) ActionScrollLeft(0); else ActionScrollUp(0); else if (mod & KMOD_ALT) ActionScrollRight(0); else ActionScrollDown(0); } break; } case SDL_MOUSEBUTTONUP: { if (dont_move_mode) break; int x = event.button.x/scale, y = event.button.y/scale; if (event.button.button == 3) { uint32 curtime = SDL_GetTicks(); // Last click within .5 secs? if (gwin->get_allow_double_right_move() && curtime - last_b3_click < 500) gwin->start_actor_along_path(x, y, Mouse::mouse->avatar_speed); else if (right_on_gump && (gump = gump_man->find_gump(x, y, false))) { Rectangle dirty = gump->get_dirty(); gwin->add_dirty(dirty); gump_man->close_gump(gump); gump = 0; right_on_gump = false; } else { gwin->stop_actor(); if (Combat::is_paused() && gwin->in_combat()) gwin->paused_combat_select(x, y); } last_b3_click = curtime; } else if (event.button.button == 1) { uint32 curtime = SDL_GetTicks(); bool click_handled = false; if (dragging) { click_handled = gwin->drop_dragged(x, y, dragged); } // Last click within .5 secs? if (curtime - last_b1_click < 500) { dragging = dragged = false; gwin->double_clicked(x, y); Mouse::mouse->set_speed_cursor(); break; } if (!dragging || !dragged) last_b1_click = curtime; if (!click_handled) { // Identify item(s) clicked on. gwin->show_items(x, y, (SDL_GetModState() & KMOD_CTRL) != 0); } dragging = dragged = false; } break; } case SDL_MOUSEMOTION: { Mouse::mouse->move(event.motion.x / scale, event.motion.y / scale); Mouse::mouse->set_speed_cursor(); Mouse::mouse_update = true; // Need to blit mouse. right_on_gump = false; // Dragging with left button? if (event.motion.state & SDL_BUTTON(1)) { #ifdef USE_EXULTSTUDIO // Painting? if (cheat.in_map_editor()) { if (cheat.get_edit_shape() >= 0 && (cheat.get_edit_mode() == Cheat::paint || (SDL_GetModState() & KMOD_SHIFT))) { Paint_with_shape(event, true); break; } else if (cheat.get_edit_chunknum() >= 0 && cheat.get_edit_mode() == Cheat::paint_chunks) { Paint_with_chunk(event, true); break; } } #endif dragged = gwin->drag(event.motion.x / scale, event.motion.y / scale); } // Dragging with right? else if ((event.motion.state & SDL_BUTTON(3))) gwin->start_actor(event.motion.x / scale, event.motion.y / scale, Mouse::mouse->avatar_speed); #ifdef USE_EXULTSTUDIO // Painting? else if (cheat.in_map_editor() && cheat.get_edit_shape() >= 0 && (cheat.get_edit_mode() == Cheat::paint || (SDL_GetModState() & KMOD_SHIFT))) { static int prevx = -1, prevy = -1; Move_dragged_shape(cheat.get_edit_shape(), cheat.get_edit_frame(), event.motion.x, event.motion.y, prevx, prevy, false); prevx = event.motion.x; prevy = event.motion.y; } #endif break; } case SDL_ACTIVEEVENT: if (event.active.state & SDL_APPMOUSEFOCUS) { if (event.active.gain) { int x, y; SDL_GetMouseState(&x, &y); Mouse::mouse->set_location(x/scale, y/scale); } gwin->set_painted(); } if (event.active.state & SDL_APPINPUTFOCUS) { if (event.active.gain) gwin->get_focus(); else gwin->lose_focus(); } #if 0 if (event.active.state & SDL_APPACTIVE) // Became active. if (event.active.gain) gwin->init_actors(); #endif break; #if 0 case ConfigureNotify: // Resize. gwin->resized(event.xconfigure.window, event.xconfigure.width, event.xconfigure.height); break; #endif case SDL_QUIT: gwin->get_gump_man()->okay_to_quit(); break; case SDL_KEYDOWN: // Keystroke. case SDL_KEYUP: if (!dragging) // ESC while dragging causes crashes. keybinder->HandleEvent(event); break; #ifdef USE_EXULTSTUDIO #ifndef WIN32 case SDL_SYSWMEVENT: { XEvent& ev = event.syswm.msg->event.xevent; if (ev.type == ClientMessage) xdnd->client_msg((XClientMessageEvent&) ev); else if (ev.type == SelectionNotify) xdnd->select_msg((XSelectionEvent&) ev); break; } #endif #endif #if 0 //#ifdef WIN32 case SDL_SYSWMEVENT: // printf("SYSWMEVENT received, %x\n", event.syswm.msg->msg); if (event.syswm.msg->msg == MM_MCINOTIFY) { #if DEBUG cerr << "MM_MCINOTIFY message received"<get_midi()))->callback(event.syswm.msg->wParam, event.syswm.msg->hwnd); } break; #endif } } /* * Wait for a click, or optionally, a kbd. chr. * * Output: 0 if user hit ESC. */ static int Get_click ( int& x, int& y, char *chr, // Char. returned if not null. bool drag_ok, // Okay to drag/close while here. Paintable *paint // Paint this each cycle if OpenGL. ) { dragging = false; // Init. while (1) { SDL_Event event; Delay(); // Wait a fraction of a second. uint32 ticks = SDL_GetTicks(); Game::set_ticks(ticks); Mouse::mouse->hide(); // Turn off mouse. Mouse::mouse_update = false; // Mouse scale factor int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); static bool rightclick; while (SDL_PollEvent(&event)) switch (event.type) { case SDL_MOUSEBUTTONDOWN: if (event.button.button == 3) rightclick = true; else if (drag_ok && event.button.button == 1) { x = event.button.x / scale; y = event.button.y / scale; dragging = gwin->start_dragging(x, y); dragged = false; } break; case SDL_MOUSEBUTTONUP: if (event.button.button == 1) { x = event.button.x / scale; y = event.button.y / scale; bool drg = dragging, drged = dragged; dragging = dragged = false; if (!drg || !gwin->drop_dragged(x, y, drged)) { if (chr) *chr = 0; return (1); } } else if (event.button.button == 3) { // Just stop. Don't get followers! gwin->get_main_actor()->stop(); if (gwin->get_mouse3rd() && rightclick) { rightclick = false; return 0; } } break; case SDL_MOUSEMOTION: { int mx = event.motion.x / scale, my = event.motion.y / scale; Mouse::mouse->move(mx, my); Mouse::mouse_update = true; if (drag_ok && (event.motion.state & SDL_BUTTON(1))) dragged = gwin->drag(mx, my); break; } case SDL_KEYDOWN: { //+++++ convert to unicode first? int c = event.key.keysym.sym; switch(c) { case SDLK_ESCAPE: return 0; case SDLK_RSHIFT: case SDLK_LSHIFT: case SDLK_RCTRL: case SDLK_LCTRL: case SDLK_RALT: case SDLK_LALT: case SDLK_RMETA: case SDLK_LMETA: case SDLK_RSUPER: case SDLK_LSUPER: case SDLK_NUMLOCK: case SDLK_CAPSLOCK: case SDLK_SCROLLOCK: break; default: if ((c == 's') && (event.key.keysym.mod & KMOD_ALT) && (event.key.keysym.mod & KMOD_CTRL)){ make_screenshot(true); break; } if (chr)// Looking for a character? { *chr = (event.key.keysym.mod & KMOD_SHIFT) ? toupper(c) : c; return (1); } break; } break; } case SDL_ACTIVEEVENT: if (event.active.state & SDL_APPINPUTFOCUS) { if (event.active.gain) gwin->get_focus(); else gwin->lose_focus(); } } if (GL_manager::get_instance()) { gwin->paint(); if (paint) paint->paint(); } else if (dragging) gwin->paint_dirty(); Mouse::mouse->show(); // Turn on mouse. if (!gwin->show() && // Blit to screen if necessary. Mouse::mouse_update) Mouse::mouse->blit_dirty(); } return (0); // Shouldn't get here. } /* * Get a click, or, optionally, a keyboard char. * * Output: 0 if user hit ESC. * Chr gets keyboard char., or 0 if it's was a mouse click. */ int Get_click ( int& x, int& y, // Location returned (if not ESC). Mouse::Mouse_shapes shape, // Mouse shape to use. char *chr, // Char. returned if not null. bool drag_ok, // Okay to drag/close while here. Paintable *paint // Paint this over everything else. ) { if (chr) *chr = 0; // Init. Mouse::Mouse_shapes saveshape = Mouse::mouse->get_shape(); if (shape != Mouse::dontchange) Mouse::mouse->set_shape(shape); if (paint) paint->paint(); Mouse::mouse->show(); gwin->show(1); // Want to see new mouse. gwin->get_tqueue()->pause(Game::get_ticks()); int ret = Get_click(x, y, chr, drag_ok, paint); gwin->get_tqueue()->resume(Game::get_ticks()); Mouse::mouse->set_shape(saveshape); return (ret); } /* * Wait for someone to stop walking. If a timeout is given, at least * one animation cycle will still always occur. */ void Wait_for_arrival ( Actor *actor, // Whom to wait for. Tile_coord dest, // Where he's going. long maxticks // Max. # msecs. to wait, or 0. ) { // Mouse scale factor int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); unsigned char os = Mouse::mouse->is_onscreen(); uint32 last_repaint = 0; // For insuring animation repaints. Actor_action *orig_action = actor->get_action(); uint32 stop_time = SDL_GetTicks() + maxticks; bool timeout = false; while (actor->is_moving() && actor->get_action() == orig_action && actor->get_tile() != dest && !timeout) { Delay(); // Wait a fraction of a second. Mouse::mouse->hide(); // Turn off mouse. Mouse::mouse_update = false; SDL_Event event; while (SDL_PollEvent(&event)) switch (event.type) { case SDL_MOUSEMOTION: Mouse::mouse->move(event.motion.x / scale, event.motion.y / scale); Mouse::mouse_update = true; break; } // Get current time, & animate. uint32 ticks = SDL_GetTicks(); Game::set_ticks(ticks); if (maxticks && ticks > stop_time) timeout = true; if (gwin->have_focus()) gwin->get_tqueue()->activate(ticks); // Show animation every 1/20 sec. if (ticks > last_repaint + 50 || gwin->was_painted()) { gwin->paint_dirty(); while (ticks > last_repaint+50)last_repaint += 50; } Mouse::mouse->show(); // Re-display mouse. if (!gwin->show() && // Blit to screen if necessary. Mouse::mouse_update) // If not, did mouse change? Mouse::mouse->blit_dirty(); } if (!os) Mouse::mouse->hide(); } /* * Shift 'wizard's view' according to mouse position. */ static void Shift_wizards_eye ( int mx, int my ) { // Figure dir. from center. int cx = gwin->get_width()/2, cy = gwin->get_height()/2; int dy = cy - my, dx = mx - cx; Direction dir = Get_direction(dy, dx); static int deltas[16] = {0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0, -1,-1}; int dirx = deltas[2*dir], diry = deltas[2*dir + 1]; if (dirx == 1) gwin->view_right(); else if (dirx == -1) gwin->view_left(); if (diry == 1) gwin->view_down(); else if (diry == -1) gwin->view_up(); } /* * Do the 'wizard's eye' spell by letting the user browse around. */ void Wizard_eye ( long msecs // Length of time in milliseconds. ) { // Mouse scale factor int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); // Center of screen. int cx = gwin->get_width()/2, cy = gwin->get_height()/2; unsigned char os = Mouse::mouse->is_onscreen(); uint32 last_repaint = 0; // For insuring animation repaints. uint32 stop_time = SDL_GetTicks() + msecs; bool timeout = false; while (!timeout) { Delay(); // Wait a fraction of a second. Mouse::mouse->hide(); // Turn off mouse. Mouse::mouse_update = false; SDL_Event event; while (SDL_PollEvent(&event)) switch (event.type) { case SDL_MOUSEMOTION: { int mx = event.motion.x/scale, my = event.motion.y/scale; Mouse::mouse->move(mx, my); Mouse::mouse->set_shape( Mouse::mouse->get_short_arrow( Get_direction(cy - my, mx - cx))); Mouse::mouse_update = true; break; } case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) timeout = true; } // Get current time, & animate. uint32 ticks = SDL_GetTicks(); Game::set_ticks(ticks); if (ticks > stop_time) timeout = true; if (gwin->have_focus()) gwin->get_tqueue()->activate(ticks); // Show animation every 1/20 sec. if (ticks > last_repaint + 50 || gwin->was_painted()) { // Right mouse button down? int x, y; int ms = SDL_GetMouseState(&x, &y); if (SDL_BUTTON(3) & ms) Shift_wizards_eye(x/scale, y/scale); gwin->set_all_dirty(); gwin->paint_dirty(); // Paint sprite over view. ShapeID eye(10, 0, SF_SPRITES_VGA); Shape_frame *spr = eye.get_shape(); // Center it. int w = gwin->get_width(), h = gwin->get_height(); int sw = spr->get_width(), sh = spr->get_height(); int topx = (w - sw)/2, topy = (h - sh)/2; eye.paint_shape(topx + spr->get_xleft(), topy + spr->get_yabove()); if (topy > 0) // Black-fill area around sprite. { gwin->get_win()->fill8(0, w, topy, 0, 0); gwin->get_win()->fill8(0, w, h - topy - sh, 0, topy + sh); } if (topx > 0) { gwin->get_win()->fill8(0, topx, sh, 0, topy); gwin->get_win()->fill8(0, w - topx - sw, sh, topx + sw, topy); } while (ticks > last_repaint+50)last_repaint += 50; } Mouse::mouse->show(); // Re-display mouse. if (!gwin->show() && // Blit to screen if necessary. Mouse::mouse_update) // If not, did mouse change? Mouse::mouse->blit_dirty(); } if (!os) Mouse::mouse->hide(); gwin->center_view(gwin->get_main_actor()->get_tile()); } int find_resolution(int w, int h, int s) { int res = 0; for(int i=0; i=0 && new_resget_win()->get_scaler(); current_res = new_res; gwin->resized(res_list[current_res].x, res_list[current_res].y, res_list[current_res].scale, scaler); if(save) { char val[20]; snprintf(val, 20, "%d", res_list[current_res].x); config->set("config/video/width",val,true); snprintf(val, 20, "%d", res_list[current_res].y); config->set("config/video/height",val,true); snprintf(val, 20, "%d", res_list[current_res].scale); config->set("config/video/scale",val,true); // Scaler if (scaler > Image_window::NoScaler && scaler < Image_window::NumScalers) config->set("config/video/scale_method",Image_window::get_name_for_scaler(scaler),true); } } } void increase_resolution() { if (!cheat()) return; current_res++; if(current_res>=num_res) current_res = 0; set_resolution(current_res,false); } void decrease_resolution() { if (!cheat()) return; current_res--; if(current_res<0) current_res = num_res-1; set_resolution(current_res,false); } void make_screenshot (bool silent) { char fn[15]; int i; FILE *f; bool namefound = false; Effects_manager *eman = gwin->get_effects(); // look for the next available exult???.pcx file for (i = 0; i < 1000 && !namefound; i++) { snprintf(fn, 15, "exult%03i.pcx", i); f = fopen(fn, "rb"); if (f) { fclose(f); } else { namefound = true; } } if (!namefound) { if (!silent) eman->center_text("Too many screenshots"); } else { SDL_RWops *dst = SDL_RWFromFile(fn, "wb"); if (gwin->get_win()->screenshot(dst)) { cout << "Screenshot saved in " << fn << endl; if (!silent) eman->center_text("Screenshot"); } else { if (!silent) eman->center_text("Screenshot failed"); } } } void change_gamma (bool down) { float r,g,b; char text[256]; float delta = down?0.05:-0.05; Image_window8::get_gamma(r, g, b); Image_window8::set_gamma(r+delta, g+delta, b+delta); gwin->get_pal()->set(-1, -1); // Message #ifdef HAVE_SNPRINTF Image_window8::get_gamma(r, g, b); snprintf (text, 256, "Gamma Set to R: %01.2f G: %01.2f B: %01.2f", r, g, b); #else strncpy (text, "Gamma Changed", 256); #endif gwin->get_effects()->center_text(text); int igam = (int) ((r*10000)+0.5); snprintf (text, 256, "%d.%04d", igam/10000, igam%10000); config->set("config/video/gamma/red", text, true); igam = (int) ((b*10000)+0.5); snprintf (text, 256, "%d.%04d", igam/10000, igam%10000); config->set("config/video/gamma/green", text, true); igam = (int) ((g*10000)+0.5); snprintf (text, 256, "%d.%04d", igam/10000, igam%10000); config->set("config/video/gamma/blue", text, true); } void BuildGameMap() { int w, h, sc, sclr; // create 2048x2048 screenshots of the full Ultima 7 map. // WARNING!! Takes up lots of memory and diskspace! if (arg_buildmap >= 0) { int maplift = 16; Exult_Game gametype; switch(arg_buildmap) { case 0: maplift = 16; break; case 1: maplift = 10; break; case 2: maplift = 5; break; } if (run_bg) { gametype = BLACK_GATE; get_game_paths("blackgate"); } else if (run_si) { gametype = SERPENT_ISLE; get_game_paths("serpentisle"); } else { cerr << "You have to specify --bg or --si when using --buildmap" << endl; exit(1); } h = w = c_tilesize * c_tiles_per_schunk; sc = 1, sclr = Image_window::point; Image_window8::set_gamma(1, 1, 1); string fullscreenstr; // Check config. for fullscreen mode. config->value("config/video/fullscreen",fullscreenstr,"no"); // set windowed mode config->set("config/video/fullscreen","no",false); gwin = new Game_window(w, h, sc, sclr); // restore original fullscreen setting config->set("config/video/fullscreen",fullscreenstr,true); Audio::Init(); current_res = find_resolution(w, h, sc); Game::create_game(gametype); gwin->init_files(false); //init, but don't show plasma gwin->get_map()->init();// +++++Got to clean this up. gwin->get_pal()->set(0); for (int x = 0; x < c_num_chunks / c_chunks_per_schunk; x++) { for (int y = 0; y < c_num_chunks / c_chunks_per_schunk; y++) { gwin->paint_map_at_tile(0,0,w,h,x * c_tiles_per_schunk, y * c_tiles_per_schunk, maplift); char fn[15]; snprintf(fn, 15, "u7map%x%x.pcx", x, y); SDL_RWops *dst = SDL_RWFromFile(fn, "wb"); cerr << x << "," << y << ": "; gwin->get_win()->screenshot(dst); } } Audio::Destroy(); exit(0); } } #ifdef USE_EXULTSTUDIO /* * Show a grid being dragged. */ static void Move_grid ( int x, int y, // Mouse coords. within window. int prevx, int prevy, // Prev. coords, or -1. bool ireg, // A single IREG object? int xtiles, int ytiles, // Dimension of grid to show. int tiles_right, int tiles_below// # tiles to show to right of and // below (x, y). ) { int scale = gwin->get_win()->get_scale(); x /= scale; // Watch for scaled window. y /= scale; int lift = cheat.get_edit_lift(); x += lift*4 - 1; // Take lift into account, round. y += lift*4 - 1; int tx = x/c_tilesize; // Figure tile on ground. int ty = y/c_tilesize; tx += tiles_right; ty += tiles_below; if (prevx != -1) // See if moved to a new tile. { prevx /= scale; prevy /= scale; prevx += lift*4 - 1; // Take lift into account, round. prevy += lift*4 - 1; int ptx = prevx/c_tilesize, pty = prevy/c_tilesize; if (tx == ptx && ty == pty) return; // Will be in same tile. // Repaint over old area. const int pad = 8; Rectangle r((ptx - xtiles + 1)*c_tilesize - pad, (pty - ytiles + 1)*c_tilesize - pad, xtiles*c_tilesize + 2*pad, ytiles*c_tilesize + 2*pad); r = gwin->clip_to_win(r); gwin->add_dirty(r); gwin->paint_dirty(); } // First see if it's a gump. if (ireg && gwin->get_gump_man()->find_gump(x, y)) return; // Skip if so. tx -= xtiles - 1; // Get top-left of footprint. ty -= ytiles - 1; // Let's try a green outline. int pix = Shape_manager::get_instance()->get_special_pixel( POISON_PIXEL); Image_window8 *win = gwin->get_win(); win->set_clip(0, 0, win->get_width(), win->get_height()); for (int Y = 0; Y <= ytiles; Y++) win->fill8(pix, xtiles*c_tilesize, 1, tx*c_tilesize, (ty + Y)*c_tilesize); for (int X = 0; X <= xtiles; X++) win->fill8(pix, 1, ytiles*c_tilesize, (tx + X)*c_tilesize, ty*c_tilesize); win->clear_clip(); gwin->set_painted(); } /* * Show where a shape dragged from a shape-chooser will go. * ALSO, this is called with shape==-1 to just force a repaint. */ static void Move_dragged_shape ( int shape, int frame, // What to create, OR -1 to just // repaint window. int x, int y, // Mouse coords. within window. int prevx, int prevy, // Prev. coords, or -1. bool show // Blit window. ) { if (shape == -1) { gwin->set_all_dirty(); return; } Shape_info& info = ShapeID::get_info(shape); // Get footprint in tiles. int xtiles = info.get_3d_xtiles(frame), ytiles = info.get_3d_ytiles(frame); int sclass = info.get_shape_class(); // Is it an ireg (changeable) obj? bool ireg = (sclass != Shape_info::unusable && sclass != Shape_info::building); Move_grid(x, y, prevx, prevy, ireg, xtiles, ytiles, 0, 0); if (show) gwin->show(); } /* * Show where a shape dragged from a shape-chooser will go. */ static void Move_dragged_combo ( int xtiles, int ytiles, // Dimensions in tiles. int tiles_right, // Tiles right of & below hot-spot. int tiles_below, int x, int y, // Mouse coords. within window. int prevx, int prevy, // Prev. coords, or -1. bool show // Blit window. ) { Move_grid(x, y, prevx, prevy, false, xtiles, ytiles, tiles_right, tiles_below); if (show) gwin->show(); } /* * Create an object as moveable (IREG) or fixed. */ static Game_object *Create_object ( int shape, int frame, // What to create. bool& ireg // Rets. TRUE if ireg (moveable). ) { Shape_info& info = ShapeID::get_info(shape); int sclass = info.get_shape_class(); // Is it an ireg (changeable) obj? ireg = (sclass != Shape_info::unusable && sclass != Shape_info::building); Game_object *newobj; if (ireg) newobj = gwin->get_map()->create_ireg_object( info, shape, frame, 0, 0, 0); else newobj = gwin->get_map()->create_ifix_object(shape, frame); return newobj; } /* * Drop a shape dragged from a shape-chooser via drag-and-drop. Dnd is * only supported under X for now. */ static void Drop_dragged_shape ( int shape, int frame, // What to create. int x, int y, // Mouse coords. within window. void *data // Passed data, unused by exult ) { int scale = gwin->get_win()->get_scale(); if (!cheat.in_map_editor()) // Get into editing mode. cheat.toggle_map_editor(); cheat.clear_selected(); // Remove old selected. gwin->get_map()->set_map_modified(); x /= scale; // Watch for scaled window. y /= scale; ShapeID sid(shape, frame); if (gwin->skip_lift == 0) // Editing terrain? { int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles; int ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles; int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; Map_chunk *chunk = gwin->get_map()->get_chunk(cx, cy); Chunk_terrain *ter = chunk->get_terrain(); tx %= c_tiles_per_chunk; ty %= c_tiles_per_chunk; ShapeID curid = ter->get_flat(tx, ty); if (sid.get_shapenum() != curid.get_shapenum() || sid.get_framenum() != curid.get_framenum()) { ter->set_flat(tx, ty, sid); gwin->set_all_dirty(); // ++++++++For now.++++++++++ } return; } Shape_frame *sh = sid.get_shape(); if (!sh || !sh->is_rle()) // Flats are only for terrain. return; // Shouldn't happen. cout << "Last drag pos: (" << x << ", " << y << ')' << endl; cout << "Create shape (" << shape << '/' << frame << ')' << endl; bool ireg; // Create object. Game_object *newobj = Create_object(shape, frame, ireg); Dragging_info drag(newobj); drag.drop(x, y, true); // (Dels if it fails.) } /* * Drop a chunk dragged from a chunk-chooser via drag-and-drop. Dnd is * only supported under X for now. */ static void Drop_dragged_chunk ( int chunknum, // Index in 'u7chunks'. int x, int y, // Mouse coords. within window. void *data // Passed data, unused by exult ) { int scale = gwin->get_win()->get_scale(); if (!cheat.in_map_editor()) // Get into editing mode. cheat.toggle_map_editor(); x /= scale; // Watch for scaled window. y /= scale; cout << "Last drag pos: (" << x << ", " << y << ')' << endl; cout << "Set chunk (" << chunknum << ')' << endl; // Need chunk-coordinates. int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles, ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles; int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; gwin->get_map()->set_chunk_terrain(cx, cy, chunknum); gwin->paint(); } /* * Drop a combination object dragged from ExultStudio. */ void Drop_dragged_combo ( int cnt, // # shapes. U7_combo_data *combo, // The shapes. int x, int y, // Mouse coords. within window. void *data // Passed data, unused by exult ) { int scale = gwin->get_win()->get_scale(); if (!cheat.in_map_editor()) // Get into editing mode. cheat.toggle_map_editor(); cheat.clear_selected(); // Remove old selected. x /= scale; // Watch for scaled window. y /= scale; int at_lift = cheat.get_edit_lift(); x += at_lift*4 - 1; // Take lift into account, round. y += at_lift*4 - 1; // Figure tile at mouse pos. int tx = (gwin->get_scrolltx() + x/c_tilesize)%c_num_tiles, ty = (gwin->get_scrollty() + y/c_tilesize)%c_num_tiles; for (int i = 0; i < cnt; i++) { // Drop each shape. U7_combo_data& elem = combo[i]; // Figure new tile coord. int ntx = (tx + elem.tx)%c_num_tiles, nty = (ty + elem.ty)%c_num_tiles, ntz = at_lift + elem.tz; if (ntz < 0) ntz = 0; ShapeID sid(elem.shape, elem.frame); if (gwin->skip_lift == 0)// Editing terrain? { int cx = ntx/c_tiles_per_chunk, cy = nty/c_tiles_per_chunk; Map_chunk *chunk = gwin->get_map()->get_chunk(cx, cy); Chunk_terrain *ter = chunk->get_terrain(); ntx %= c_tiles_per_chunk; nty %= c_tiles_per_chunk; ter->set_flat(ntx, nty, sid); continue; } bool ireg; // Create object. Game_object *newobj = Create_object(elem.shape, elem.frame, ireg); newobj->set_invalid(); // Not in world. newobj->move(ntx, nty, ntz); // Add to selection. cheat.append_selected(newobj); } gwin->set_all_dirty(); // For now, until we clear out grid. } #endif exult-1.2/keys.cc0000644000175000001440000004152410054030531007451 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_keyboard.h" #include "actors.h" #include "keys.h" #include "exult.h" #include "game.h" #include "cheat.h" #include "U7file.h" #include "Scroll_gump.h" #include "mouse.h" #include "gamewin.h" #include "utils.h" #include "keyactions.h" #ifndef UNDER_CE using std::pair; using std::atoi; using std::cerr; using std::cout; using std::clog; using std::endl; using std::ifstream; using std::isspace; using std::strchr; using std::string; using std::strlen; using std::vector; #endif static class Chardata // ctype-like character lists { public: std::string whitespace; Chardata() { for(size_t i=0;i<256;i++) if(isspace(i)) whitespace+=static_cast(i); } } chardata; typedef void(*ActionFunc)(int*); const struct Action { const char *s; ActionFunc func; ActionFunc func_release; const char* desc; bool show; bool cheat; Exult_Game game; bool allow_during_dont_move; } ExultActions[] = { { "QUIT", ActionQuit, 0, "Quit", true, false, NONE, true }, { "SAVE_RESTORE", ActionFileGump, 0, "Save/restore", true, false, NONE, true }, { "QUICKSAVE", ActionQuicksave, 0, "Quick-save", true, false, NONE, false }, { "QUICKRESTORE", ActionQuickrestore, 0, "Quick-restore", true, false, NONE, true }, { "ABOUT", ActionAbout, 0, "About Exult", true, false, NONE, false }, { "HELP", ActionHelp, 0, "List keys", true, false, NONE, false }, { "CLOSE_GUMPS", ActionCloseGumps, 0, "Close gumps", false, false, NONE, false}, { "CLOSE_OR_MENU", ActionCloseOrMenu, 0, "Game menu", true, false, NONE, true }, { "SCREENSHOT", ActionScreenshot, 0, "Take screenshot", true, false, NONE, true }, { "GAME_MENU", ActionMenuGump, 0, "Game Menu", true, false, NONE, true }, { "OLD_FILE_GUMP", ActionOldFileGump, 0, "Save/restore", true, false, NONE, true }, { "REPAINT", ActionRepaint, 0, "Repaint screen", false, false, NONE, true }, { "RESOLUTION_INCREASE", ActionResIncrease, 0, "Increase resolution", true, true, NONE, true }, { "RESOLUTION_DECREASE", ActionResDecrease, 0, "Decrease resolution", true, true, NONE, true }, { "BRIGHTER", ActionBrighter, 0, "Increase brightness", true, false, NONE, true }, { "DARKER", ActionDarker, 0, "Decrease brightness", true, false, NONE, true }, { "TOGGLE_FULLSCREEN", ActionFullscreen, 0, "Toggle fullscreen", true, false, NONE, true }, { "USEITEM", ActionUseItem, 0, "Use item", false, false, NONE, false }, { "USEFOOD", ActionUseFood, 0, "Use food", false, false, NONE, false }, { "TOGGLE_COMBAT", ActionCombat, 0, "Toggle combat", true, false, NONE, false }, { "PAUSE_COMBAT", ActionCombatPause, 0, "Pause combat", true, false, NONE, false }, { "TARGET_MODE", ActionTarget, 0, "Target mode", true, false, NONE, false }, { "INVENTORY", ActionInventory, 0, "Show inventory", true, false, NONE, false }, { "TRY_KEYS", ActionTryKeys, 0, "Try keys", true, false, NONE, false }, { "STATS", ActionStats, 0, "Show stats", true, false, NONE, false }, { "COMBAT_STATS", ActionCombatStats, 0, "Show combat stats", true, false, SERPENT_ISLE, false }, { "FACE_STATS", ActionFaceStats, 0, "Change Face Stats State", true, false, NONE, false }, { "SHOW_SI_INTRO", ActionSIIntro, 0, "Show Alternate SI intro", true, true, SERPENT_ISLE, false }, { "SHOW_ENDGAME", ActionEndgame, 0, "Show endgame", true, true, NONE, false }, { "SCROLL_LEFT", ActionScrollLeft, 0, "Scroll left", true, true, NONE, false }, { "SCROLL_RIGHT", ActionScrollRight, 0, "Scroll right", true, true, NONE, false }, { "SCROLL_UP", ActionScrollUp, 0, "Scroll up", true, true, NONE, false }, { "SCROLL_DOWN", ActionScrollDown, 0, "Scroll down", true, true, NONE, false }, { "WALK_WEST", ActionWalkWest, ActionStopWalking, "Walk west", true, false, NONE, false }, { "WALK_EAST", ActionWalkEast, ActionStopWalking, "Walk east", true, false, NONE, false }, { "WALK_NORTH", ActionWalkNorth, ActionStopWalking, "Walk north", true, false, NONE, false }, { "WALK_SOUTH", ActionWalkSouth, ActionStopWalking, "Walk south", true, false, NONE, false }, { "WALK_NORTH_EAST", ActionWalkNorthEast, ActionStopWalking, "Walk north-east", true, false, NONE, false }, { "WALK_SOUTH_EAST", ActionWalkSouthEast, ActionStopWalking, "Walk south-east", true, false, NONE, false }, { "WALK_NORTH_WEST", ActionWalkNorthWest, ActionStopWalking, "Walk north-west", true, false, NONE, false }, { "WALK_SOUTH_WEST", ActionWalkSouthWest, ActionStopWalking, "Walk south-west", true, false, NONE, false }, { "CENTER_SCREEN", ActionCenter, 0, "Center screen", true, true, NONE, false }, { "SHAPE_BROWSER", ActionShapeBrowser, 0, "Shape browser", true, true, NONE, false }, { "CREATE_ITEM", ActionCreateShape, 0, "Create last shape", true, true, NONE, false }, { "DELETE_OBJECT", ActionDeleteObject, 0, "Delete object", true, true, NONE, false }, { "DELETE_SELECTED", ActionDeleteSelected, 0, "Delete selected", true, true, NONE, true }, { "MOVE_SELECTED", ActionMoveSelected, 0, "Move selected", true, true, NONE, true }, { "TOGGLE_EGGS", ActionToggleEggs, 0, "Toggle egg display", true, true, NONE, false }, { "TOGGLE_GOD_MODE", ActionGodMode, 0, "Toggle god mode", true, true, NONE, false }, { "CHANGE_GENDER", ActionGender, 0, "Change gender", true, true, NONE, false }, { "CHEAT_HELP", ActionCheatHelp, 0, "List cheat keys", true, true, NONE, false }, { "TOGGLE_INFRAVISION", ActionInfravision, 0, "Toggle infravision", true, true, NONE, false }, { "SKIPLIFT_DECREMENT", ActionSkipLift, 0, "Decrement skiplift", true, true, NONE, false }, { "TOGGLE_MAP_EDITOR", ActionMapEditor, 0, "Toggle map-editor mode", true, true, NONE, true }, { "TOGGLE_HACK_MOVER", ActionHackMover, 0, "Toggle hack-mover mode", true, true, NONE, false }, { "MAP_TELEPORT", ActionMapTeleport, 0, "Map teleport", true, true, NONE, false }, { "CURSOR_TELEPORT", ActionTeleport, 0, "Teleport to cursor", true, true, NONE, false }, { "NEXT_TIME_PERIOD", ActionTime, 0, "Next time period", true, true, NONE, false }, { "TOGGLE_WIZARD_MODE", ActionWizard, 0, "Toggle archwizard mode", true, true, NONE, false }, { "PARTY_HEAL", ActionHeal, 0, "Heal party", true, true, NONE, false }, { "PARTY_INCREASE_LEVEL", ActionLevelup, 0, "Level-up party", true, true, NONE, false }, { "CHEAT_SCREEN", ActionCheatScreen, 0, "Cheat Screen", true, true, NONE, true }, { "PICK_POCKET", ActionPickPocket, 0, "Toggle Pick Pocket", true, true, NONE, false }, { "NPC_NUMBERS", ActionNPCNumbers, 0, "Toggle NPC Numbers", true, true, NONE, false }, { "GRAB_ACTOR", ActionGrabActor, 0, "Grab NPC for Cheat Screen", true, true, NONE, false }, { "CUT", ActionCut, 0, "Cut Selected Objects", true, false, NONE, true}, { "COPY", ActionCopy, 0, "Copy Selected Objects", true, false, NONE, true}, { "PASTE", ActionPaste, 0, "Paste Selected Objects", true, false, NONE, true}, { "PLAY_MUSIC", ActionPlayMusic, 0, "Play song", false, true, NONE, false }, { "TOGGLE_NAKED", ActionNaked, 0, "Toggle naked mode", true, true, SERPENT_ISLE, false }, { "TOGGLE_PETRA", ActionPetra, 0, "Toggle Petra mode", true, true, SERPENT_ISLE, false }, { "CHANGE_SKIN", ActionSkinColour, 0, "Change skin colour", true, true, NONE, false }, { "SOUND_TESTER", ActionSoundTester, 0, "Sound tester", false, true, NONE, false }, { "TEST", ActionTest, 0, "Test", false, false, NONE, false }, { "", 0, 0, "", false, false, NONE, false } //terminator }; const struct { const char *s; SDLKey k; } SDLKeyStringTable[] = { {"BACKSPACE", SDLK_BACKSPACE}, {"TAB", SDLK_TAB}, {"ENTER", SDLK_RETURN}, {"PAUSE", SDLK_PAUSE}, {"ESC", SDLK_ESCAPE}, {"SPACE", SDLK_SPACE}, {"DEL", SDLK_DELETE}, {"KP0", SDLK_KP0}, {"KP1", SDLK_KP1}, {"KP2", SDLK_KP2}, {"KP3", SDLK_KP3}, {"KP4", SDLK_KP4}, {"KP5", SDLK_KP5}, {"KP6", SDLK_KP6}, {"KP7", SDLK_KP7}, {"KP8", SDLK_KP8}, {"KP9", SDLK_KP9}, {"KP.", SDLK_KP_PERIOD}, {"KP/", SDLK_KP_DIVIDE}, {"KP*", SDLK_KP_MULTIPLY}, {"KP-", SDLK_KP_MINUS}, {"KP+", SDLK_KP_PLUS}, {"KP_ENTER", SDLK_KP_ENTER}, {"UP", SDLK_UP}, {"DOWN", SDLK_DOWN}, {"RIGHT", SDLK_RIGHT}, {"LEFT", SDLK_LEFT}, {"INSERT", SDLK_INSERT}, {"HOME", SDLK_HOME}, {"END", SDLK_END}, {"PAGEUP", SDLK_PAGEUP}, {"PAGEDOWN", SDLK_PAGEDOWN}, {"F1", SDLK_F1}, {"F2", SDLK_F2}, {"F3", SDLK_F3}, {"F4", SDLK_F4}, {"F5", SDLK_F5}, {"F6", SDLK_F6}, {"F7", SDLK_F7}, {"F8", SDLK_F8}, {"F9", SDLK_F9}, {"F10", SDLK_F10}, {"F11", SDLK_F11}, {"F12", SDLK_F12}, {"F13", SDLK_F13}, {"F14", SDLK_F14}, {"F15", SDLK_F15}, {"", SDLK_UNKNOWN} // terminator }; typedef std::map ParseKeyMap; typedef std::map ParseActionMap; static ParseKeyMap keys; static ParseActionMap actions; KeyBinder::KeyBinder() { FillParseMaps(); } KeyBinder::~KeyBinder() { } void KeyBinder::AddKeyBinding( SDLKey key, int mod, const Action* action, int nparams, int* params) { SDL_keysym k; ActionType a; k.scancode = 0; k.sym = key; k.mod = (SDLMod) mod; k.unicode = 0; a.action = action; int i; // For MSVC for (i = 0; i < c_maxparams && i < nparams; i++) a.params[i] = params[i]; for (i = nparams; i < c_maxparams; i++) a.params[i] = -1; bindings[k] = a; } bool KeyBinder::DoAction(ActionType a, bool press) { if (a.action->cheat && !cheat()) return true; if (a.action->game != NONE && a.action->game != Game::get_game_type()) return true; // Restrict key actions in dont_move mode if (a.action->allow_during_dont_move || !Game_window::get_instance()->main_actor_dont_move() || cheat.in_map_editor()) // But not if map-editing. { if (press) a.action->func(a.params); else { if(a.action->func_release != NULL) a.action->func_release(a.params); } } return true; } bool KeyBinder::HandleEvent(SDL_Event &ev) { SDL_keysym key = ev.key.keysym; KeyMap::iterator sdlkey_index; if (ev.type != SDL_KEYDOWN && ev.type != SDL_KEYUP) return false; key.mod = KMOD_NONE; if (ev.key.keysym.mod & KMOD_SHIFT) key.mod = (SDLMod)(key.mod | KMOD_SHIFT); if (ev.key.keysym.mod & KMOD_CTRL) key.mod = (SDLMod)(key.mod | KMOD_CTRL); #if defined(MACOS) || defined(MACOSX) // map Meta to Alt on MacOS if (ev.key.keysym.mod & KMOD_META) key.mod = (SDLMod)(key.mod | KMOD_ALT); #else if (ev.key.keysym.mod & KMOD_ALT) key.mod = (SDLMod)(key.mod | KMOD_ALT); #endif sdlkey_index = bindings.find(key); if (sdlkey_index != bindings.end()) return DoAction((*sdlkey_index).second, ev.type==SDL_KEYDOWN); return false; } void KeyBinder::ShowHelp() { Scroll_gump *scroll; scroll = new Scroll_gump(); std::vector::iterator iter; for (iter = keyhelp.begin(); iter != keyhelp.end(); iter++) scroll->add_text(iter->c_str()); scroll->paint(); do { int x, y; Get_click(x,y, Mouse::hand); } while (scroll->show_next_page()); Game_window::get_instance()->paint(); delete scroll; } void KeyBinder::ShowCheatHelp() { Scroll_gump *scroll; scroll = new Scroll_gump(); std::vector::iterator iter; for (iter = cheathelp.begin(); iter != cheathelp.end(); iter++) scroll->add_text(iter->c_str()); scroll->paint(); do { int x, y; Get_click(x,y, Mouse::hand); } while (scroll->show_next_page()); Game_window::get_instance()->paint(); delete scroll; } void KeyBinder::ParseText(char *text, int len) { char *ptr, *end; const char LF = '\n'; ptr = text; // last (useful) line must end with LF while ((ptr - text) < len && (end = strchr(ptr, LF)) != 0) { *end = '\0'; ParseLine(ptr); ptr = end + 1; } } static void skipspace(string &s) { size_t i=s.find_first_not_of(chardata.whitespace); if(i&&i!=string::npos) s.erase(0,i); } void KeyBinder::ParseLine(char *line) { size_t i; SDL_keysym k; ActionType a; k.sym = SDLK_UNKNOWN; k.mod = KMOD_NONE; string s = line, u; string d, desc, keycode; bool show; skipspace(s); // comments and empty lines if (s.length() == 0 || s[0] == '#') return; u = s; to_uppercase(u); // get key while (s.length() && !isspace(s[0])) { // check modifiers // if (u.compare("ALT-",0,4) == 0) { if (u.substr(0,4) == "ALT-") { k.mod = (SDLMod)(k.mod | KMOD_ALT); s.erase(0,4); u.erase(0,4); // } else if (u.compare("CTRL-",0,5) == 0) { } else if (u.substr(0,5) == "CTRL-") { k.mod = (SDLMod)(k.mod | KMOD_CTRL); s.erase(0,5); u.erase(0,5); // } else if (u.compare("SHIFT-",0,6) == 0) { } else if (u.substr(0,6) == "SHIFT-") { k.mod = (SDLMod)(k.mod | KMOD_SHIFT); s.erase(0,6); u.erase(0,6); } else { i=s.find_first_of(chardata.whitespace); keycode = s.substr(0, i); s.erase(0, i); string t(keycode); to_uppercase(t); if (t.length() == 0) { cerr << "Keybinder: parse error in line: " << s << endl; return; } else if (t.length() == 1) { // translate 1-letter keys straight to SDLKey char c = t[0]; if (c >= 33 && c <= 122 && c != 37) { if (c >= 'A' && c <= 'Z') c += 32; // need lowercase k.sym = static_cast(c); } else { cerr << "Keybinder: unsupported key: " << keycode << endl; } } else { // lookup in table ParseKeyMap::iterator key_index; key_index = keys.find(t); if (key_index != keys.end()) { k.sym = (*key_index).second; } else { cerr << "Keybinder: unsupported key: " << keycode << endl; return; } } } } if (k.sym == SDLK_UNKNOWN) { cerr << "Keybinder: parse error in line: " << s << endl; return; } // get function skipspace(s); i=s.find_first_of(chardata.whitespace); string t = s.substr(0, i); s.erase(0, i); to_uppercase(t); ParseActionMap::iterator action_index; action_index = actions.find(t); if (action_index != actions.end()) { a.action = (*action_index).second; } else { cerr << "Keybinder: unsupported action: " << t << endl; return; } // get params skipspace(s); int np = 0; while (s.length() && s[0] != '#' && np < c_maxparams) { i=s.find_first_of(chardata.whitespace); string t = s.substr(0, i); s.erase(0, i); skipspace(s); int p = atoi(t.c_str()); a.params[np++] = p; } // read optional help comment if (s.length() >= 1 && s[0] == '#') { if (s.length() >= 2 && s[1] == '-') { show = false; } else { s.erase(0,1); skipspace(s); d = s; show = true; } } else { d = a.action->desc; show = a.action->show; } if (show) { desc = ""; if (k.mod & KMOD_CTRL) desc += "Ctrl-"; #if defined(MACOS) || defined(MACOSX) if (k.mod & KMOD_ALT) desc += "Cmd-"; #else if (k.mod & KMOD_ALT) desc += "Alt-"; #endif if (k.mod & KMOD_SHIFT) desc += "Shift-"; desc += keycode; desc += " - " + d; // add to help list if (a.action->cheat) cheathelp.push_back(desc); else keyhelp.push_back(desc); } // bind key AddKeyBinding(k.sym, k.mod, a.action, np, a.params); } void KeyBinder::LoadFromFile(const char* filename) { ifstream keyfile; Flush(); cout << "Loading keybindings from file " << filename << endl; U7open(keyfile, filename, true); char temp[1024]; // 1024 should be long enough while(!keyfile.eof()) { keyfile.getline(temp, 1024); if (keyfile.gcount() >= 1023) { cerr << "Keybinder: parse error: line too long. Skipping rest of file." << endl; return; } ParseLine(temp); } keyfile.close(); } void KeyBinder::LoadDefaults() { Flush(); cout << "Loading default keybindings" << endl; str_int_pair resource = game->get_resource("config/defaultkeys"); U7object txtobj(resource.str, resource.num); size_t len; char *txt = txtobj.retrieve(len); ParseText(txt, len); delete [] txt; } // codes used in keybindings-files. (use uppercase here) void KeyBinder::FillParseMaps() { int i; // For MSVC for (i = 0; strlen(SDLKeyStringTable[i].s) > 0; i++) keys[SDLKeyStringTable[i].s] = SDLKeyStringTable[i].k; for (i = 0; strlen(ExultActions[i].s) > 0; i++) actions[ExultActions[i].s] = &(ExultActions[i]); } exult-1.2/README.AmigaOS0000644000175000001440000000167207420541202010333 Exult instructions for AmigaOS ------------------------------ To play ------- First you need to get Ultima 7. Either you own it already, or you buy it somewhere. Then you must install it on a DOS/Windows machine in order to get the data file. If you do not have a DOS/Windows machine, using an emulator like Bochs should do the job. Alternatively, the 'Ultima Collection' already contains a pre-installed version of U7. (in the directory /ultima7) Notes ------ * You can build exult from the source yourself if you want. You'll need a working Geek Gadgets installation and the AmigaOS SDL library (available from http://ggreco.interfree.it/sdl.html). StormC 4 is able as well to compile Exult in GCC mode, but I had some strange problems with it so if you must use StormC and run into trouble you're on your own. To build, copy Makefile.MorphOS to Makefile and run 'make'. If you need help, feel free to contact me at exult-1.2/tqueue.h0000644000175000001440000000670207724430450007665 /* * tqueue.h - A queue of time-based events for animation. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TQUEUE_H #define TQUEUE_H 1 #include #include #include "exult_types.h" /* * An interface for entries in the queue: */ class Time_sensitive { int queue_cnt; // # of entries for this in queue. bool always; // Always do this, even if paused. public: friend class Time_queue; Time_sensitive() : queue_cnt(0), always(false) { } virtual ~Time_sensitive(); int in_queue() { return queue_cnt > 0; } void set_always(bool tf) // Should be called before placing in // queue. { always = tf; } virtual void handle_event(unsigned long curtime, long udata) = 0; }; class Time_queue; /* * A queue entry: */ class Queue_entry { public: // Queue_entry *next, *prev; // Next, prev. in queue. Time_sensitive *handler; // Object to activate. long udata; // Data to pass to handler. uint32 time; // Time when this is due. inline void set(uint32 t, Time_sensitive *h, long ud) { time = t; handler = h; udata = ud; } }; bool operator <(const Queue_entry &q1,const Queue_entry &q2); /* * Time-based queue. The entries are kept sorted in increasing order * by time. */ class Time_queue { typedef std::list Temporal_sequence; Temporal_sequence data; uint32 pause_time; // Time when paused. int paused; // Count of calls to 'pause()'. // Activate head + any others due. void activate0(uint32 curtime); void activate_always(uint32 curtime); public: friend class Time_queue_iterator; // Time_queue() : head(0), free_entries(0) Time_queue() : pause_time(0), paused(0) { } void clear(); // Remove all entries. // Add an entry. void add(uint32 t, Time_sensitive *obj, long ud); // Remove object's entry. int remove(Time_sensitive *obj); int remove(Time_sensitive *obj, long udata); int find(Time_sensitive *obj); // Find an entry. // Find delay when obj. is due. long find_delay(Time_sensitive *obj, uint32 curtime); // Activate entries that are 'due'. inline void activate(uint32 curtime) { // if (head && !(curtime < head->time)) if (paused) activate_always(curtime); else if (data.size() && !(curtime < data.front().time)) activate0(curtime); } void pause(uint32 curtime) // Game paused. { if (!paused++) pause_time = curtime; } void resume(uint32 curtime); }; class Time_queue_iterator { Time_queue::Temporal_sequence::iterator iter; Time_queue *tqueue; Time_sensitive *this_obj; // Only return entries for this obj. public: Time_queue_iterator(Time_queue *tq, Time_sensitive *obj) : iter(tq->data.begin()), tqueue(tq), this_obj(obj) { } int operator()(Time_sensitive *& obj, long& data); }; #endif /* TQUEUE_H */ exult-1.2/audio/0000777000175000001440000000000010062225330007350 5exult-1.2/audio/conv.cc0000644000175000001440000000636207724430450010563 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // sfx with ??? are converted to sfx #135 so you can tell // it's wrong. Some I suspect to be something so it's not set 135 int bgconv[] = { 12, //Bow Twang 0, //Missile ?? 9, //Blade 11, //Blunt 125, //Hit 61, //Graze 92, //Rotating 40, //Explos #1 41, //Explos #2 42, //Explos #3 127, //Whip pta 71, //Thunder 44, //Fireball 65, //Torches 93, //Gumps!!!!! 56, //Gavel 121, //Treadle 117, //Clock tick 118, //Clock tock 16, //Chime 45, //Fire 1 46, //Fire 2 47, //Fire 3 28, //Bell Ding 30, //Bell Dong 72, //Log Saw 78, //Mill Stone 68, //Key 70, //Lever 27, //Roulette 32, //Creeeeaack 31, //Creeeeaack 89, //Portcullis 88, //Portcullis close 34, //Drawbridge 35, //Drawbridge 7, //Fuse ??? 95, //Shadoobie 99, //Splash 126, //W. Anchor 99, //D. Anchor 32, //Creeeeaack 31, //Creeeeaack 2, //gumpster 1, //gumpster 49, //Forge 33, //Douse 7, //Bellows 7, //Fountain 109, //Surf's up 107, //Stream 133, //Waterfall 129, //Wind ??? 50, //Rainman ??? 114, //Swamp 1 110, //Swamp 2 111, //Swamp 3 112, //Swamp 4 113, //Swamp 5 132, //Waterwheel 39, //Eruption ??? 22, //Crickets 116, //Thunder 128, //Whirlpool 64, //Heal 20, //Spell 67, //Spell 130, //Wizard ??? 57, //General 48, //Fizzle 84, //New Spell 82, //MPdrain 83, //MPgain 134, //Footstep L 134, //Footstep R 108, //Success 43, //Failure 55, //Moongate 54, //Moongate B 26, //Entity Hum 101, //Entity Hum 115, //Entity Hum 96, //Shreik 135, //Slap ??? 135, //Oooffff ??? 0, //Whaahh ??? 10, //Blocked !! 52, //Furl 124, //Unfurl 135, //MISSING 36, //Drink ??? 38, //Eat ??? 127, //Whip ptb 31, //Doorslam 89, //Portcullis 88, //Drawbridge 134, //Closed 100, //SpinnWheel 79, //Minning ??? 80, //Minning ??? 9, //Shutters 135, //1armbandit ??? 73, //Loom 103, //Stalags 75, //MagicWeap 86, //Poison 65, //Ignite 62, //Yo yo LA ??? 131, //Wind Spell 90, //Protect 86, //PoisonSpel ??? 66, //IgniteSpel 21, //CradleRock 5, //Beeezzzzz 74, //Machines 255, //Static - not used in SI 136 //Tick Tock }; exult-1.2/audio/xmidi.h0000644000175000001440000001655107753476060010604 /* Copyright (C) 2000 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Tab Size = 4 // Nope, not any more we don't #if 1 #ifndef __XMIDI_h_ #define __XMIDI_h_ #include #include "common_types.h" #include "databuf.h" // Conversion types for Midi files #define XMIDI_CONVERT_NOCONVERSION 0 #define XMIDI_CONVERT_MT32_TO_GM 1 #define XMIDI_CONVERT_MT32_TO_GS 2 #define XMIDI_CONVERT_MT32_TO_GS127 3 #define XMIDI_CONVERT_GS127_TO_GS 4 // Midi Status Bytes #define MIDI_STATUS_NOTE_OFF 0x8 #define MIDI_STATUS_NOTE_ON 0x9 #define MIDI_STATUS_AFTERTOUCH 0xA #define MIDI_STATUS_CONTROLLER 0xB #define MIDI_STATUS_PROG_CHANGE 0xC #define MIDI_STATUS_PRESSURE 0xD #define MIDI_STATUS_PITCH_WHEEL 0xE #define MIDI_STATUS_SYSEX 0xF // XMIDI Controllers #define XMIDI_CONTROLLER_CHAN_LOCK 0x6e // Channel Lock #define XMIDI_CONTROLLER_CHAN_LOCK_PROT 0x6f // Channel Lock Protect #define XMIDI_CONTROLLER_VOICE_PROT 0x70 // Voice Protect #define XMIDI_CONTROLLER_TIMBRE_PROT 0x71 // Timbre Protect #define XMIDI_CONTROLLER_BANK_CHANGE 0x72 // Bank Change #define XMIDI_CONTROLLER_IND_CTRL_PREFIX 0x73 // Indirect Controller Prefix #define XMIDI_CONTROLLER_FOR_LOOP 0x74 // For Loop #define XMIDI_CONTROLLER_NEXT_BREAK 0x75 // Next/Break #define XMIDI_CONTROLLER_CLEAR_BB_COUNT 0x76 // Clear Beat/Bar Count #define XMIDI_CONTROLLER_CALLBACK_TRIG 0x77 // Callback Trigger #define XMIDI_CONTROLLER_SEQ_BRANCH_INDEX 0x78 // Sequence Branch Index // Maximum number of for loops we'll allow (used by win_midiout) #define XMIDI_MAX_FOR_LOOP_COUNT 4 template class GammaTable; struct midi_event { int time; unsigned char status; unsigned char data[2]; uint32 len; // Length of SysEx Data unsigned char *buffer; // SysEx Data int duration; // Duration of note (120 Hz) midi_event *next_note; // The next note on the stack uint32 note_time; // Time note stops playing (6000th of second) midi_event *next; }; class NoteStack { midi_event *notes; // Top of the stack int polyphony; int max_polyphony; public: NoteStack() : notes(0), polyphony(0), max_polyphony(0) { } // Just clear it. Don't care about what's actually in it void clear() { notes=0; polyphony=0; max_polyphony=0; } // Pops the top of the stack if its off_time is <= time (6000th of second) inline midi_event *PopTime(uint32 time) { if (notes && notes->note_time <= time) { midi_event *note = notes; notes = note->next_note; note->next_note = 0; polyphony--; return note; } return 0; } // Pops the top of the stack inline midi_event *Pop() { if (notes) { midi_event *note = notes; notes = note->next_note; note->next_note = 0; polyphony--; return note; } return 0; } // Pops the top of the stack inline midi_event *Remove(midi_event *event) { midi_event *prev = 0; midi_event *note = notes; while (note) { if (note == event) { if (prev) prev->next_note = note->next_note; else notes = note->next_note; note->next_note = 0; polyphony--; return note; } prev = note; note = note->next_note; } return 0; } // Finds the note that has same pitch and channel, and pops it inline midi_event *FindAndPop(midi_event *event) { midi_event *prev = 0; midi_event *note = notes; while (note) { if ((note->status & 0xF) == (event->status & 0xF) && note->data[0] == event->data[0]) { if (prev) prev->next_note = note->next_note; else notes = note->next_note; note->next_note = 0; polyphony--; return note; } prev = note; note = note->next_note; } return 0; } // Pushes a note onto the top of the stack inline void Push(midi_event *event) { event->next_note = notes; notes = event; polyphony++; if (max_polyphony < polyphony) max_polyphony = polyphony; } inline void Push(midi_event *event, uint32 time) { event->note_time = time; event->next_note = 0; polyphony++; if (max_polyphony < polyphony) max_polyphony = polyphony; if (!notes || time <= notes->note_time) { event->next_note = notes; notes = event; } else { midi_event *prev = notes; while (prev) { midi_event *note = prev->next_note; if (!note || time <= note->note_time) { event->next_note = note; prev->next_note = event; return; } prev = note; } } } inline int GetPolyphony() { return polyphony; } inline int GetMaxPolyphony() { return max_polyphony; } }; class XMIDIEventList { int counter; // Helper funcs for Write int PutVLQ(DataSource *dest, uint32 value); uint32 ConvertListToMTrk (DataSource *dest); static void DeleteEventList (midi_event *list); public: midi_event *events; // Write this list to a file/buffer int Write (const char *filename); int Write (DataSource *dest); // Increments the counter void IncerementCounter () { counter++; } // Decrement the counter and delete the event list, if possible void DecerementCounter (); }; class XMIDI { protected: uint16 num_tracks; private: XMIDIEventList **events; midi_event *list; midi_event *current; midi_event *notes_on; const static char mt32asgm[128]; const static char mt32asgs[256]; bool bank127[16]; int convert_type; bool do_reverb; bool do_chorus; int chorus_value; int reverb_value; // Midi Volume Curve Modification static GammaTable VolumeCurve; public: XMIDI(DataSource *source, int pconvert); ~XMIDI(); int number_of_tracks() { return num_tracks; } // External Event list functions XMIDIEventList *GetEventList (uint32 track); // Not yet implimented // int apply_patch (int track, DataSource *source); private: XMIDI(); // No default constructor struct first_state { // Status, Data[0] midi_event *patch[16]; // 0xC midi_event *bank[16]; // 0xB, 0 midi_event *pan[16]; // 0xB, 7 midi_event *vol[16]; // 0xB, 10 }; // List manipulation void CreateNewEvent (int time); // Variable length quantity int GetVLQ (DataSource *source, uint32 &quant); int GetVLQ2 (DataSource *source, uint32 &quant); void AdjustTimings(uint32 ppqn); // This is used by Midi's ONLY! void ApplyFirstState(first_state &fs, int chan_mask); int ConvertNote (const int time, const unsigned char status, DataSource *source, const int size); int ConvertEvent (const int time, const unsigned char status, DataSource *source, const int size, first_state& fs); int ConvertSystemMessage (const int time, const unsigned char status, DataSource *source); int ConvertFiletoList (DataSource *source, const bool is_xmi, first_state& fs); int ExtractTracksFromXmi (DataSource *source); int ExtractTracksFromMid (DataSource *source, const uint32 ppqn, const int num_tracks, const bool type1); int ExtractTracks (DataSource *source); }; #endif #endif exult-1.2/audio/convmusic.h0000644000175000001440000000361307724430450011462 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Converts the SI OGG track requests to the BG OGG track numbers char bgconvmusic[][5] = { "09bg", // 0 "10bg", // 1 "11bg", // 2 "12bg", // 3 "13bg", // 4 "14bg", // 5 "15bg", // 6 "16bg", // 7 "17bg", // 8 "18bg", // 9 "19bg", // 10 "20bg", // 11 "21bg", // 12 "22bg", // 13 "23bg", // 14 "24bg", // 15 "25bg", // 16 "26bg", // 17 "27bg", // 18 "28bg", // 19 "29bg", // 20 "30bg", // 21 "31bg", // 22 "32bg", // 23 "33bg", // 24 "34bg", // 25 "35bg", // 26 "36bg", // 27 "37bg", // 28 "38bg", // 29 "40bg", // 30 "41bg", // 31 "42bg", // 32 "43bg", // 33 "44bg", // 34 "45bg", // 35 "46bg", // 36 "47bg", // 37 "48bg", // 38 "none", // 39 "none", // 40 "none", // 41 "52bg", // 42 "53bg", // 43 "55bg", // 44 "56bg", // 45 "57bg", // 46 "58bg", // 47 "59bg", // 48 "none", // 49 "si02", // 50 "si08", // 51 "si07", // 52 "si12", // 53 "si10", // 54 "si03", // 55 "si11", // 56 "si05", // 57 "si06", // 58 "none", // 59 "none", // 60 "none", // 61 "none", // 62 "si14", // 63 "si04", // 64 "si09", // 65 "07bg", // 66 "06bg", // 67 "04bg", // 68 "05bg", // 69 "03bg" // 70 }; exult-1.2/audio/Audio.h0000644000175000001440000001002310054030550010471 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef AUDIO_H #define AUDIO_H #include #include #include #include "Midi.h" #include "exceptions.h" //SDL_mixer doesn't like mixing different rates when using OGG //This should match the same as the SFX and OGG Music which is 22khz #define SAMPLERATE 22050 class SFX_cached; class Flex; /* * Music: */ enum Combat_song { CSBattle_Over, CSAttacked1, CSAttacked2, CSVictory, CSRun_Away, CSDanger, CSHidden_Danger }; //---- Audio ----------------------------------------------------------- class Audio { private: UNREPLICATABLE_CLASS(Audio); static Audio *self; static int *bg2si_sfxs; // Converts BG sfx's to SI sfx's. bool truthful_; bool speech_enabled, music_enabled, effects_enabled; bool allow_music_looping; bool SDL_open; SFX_cached *sfxs; // ->list of cached .wav snd. effects. MyMidiPlayer *midi; bool initialized; SDL_AudioSpec wanted; Mix_Chunk *wave; public: bool audio_enabled; SDL_AudioSpec actual; Flex *sfx_file; // Holds .wav sound effects. private: // You never allocate an Audio object directly, you rather access it using get_ptr() Audio(); ~Audio(); void Init(int _samplerate,int _channels); uint8 * convert_VOC(uint8 *,uint32 &); void build_speech_vector(void); public: friend class Tired_of_compiler_warnings; static void Init(void); static void Destroy(void); static Audio* get_ptr(void); // Given BG sfx, get SI if playing SI. static int game_sfx(int sfx) { return bg2si_sfxs ? bg2si_sfxs[sfx] : sfx; } void Init_sfx(void); void honest_sample_rates(void) { truthful_=true; } void cancel_streams(void); // Dump any audio streams void pause_audio(void); void resume_audio(void); void play(uint8 *sound_data,uint32 len,bool); void playfile(const char *,bool); bool playing(void); void start_music(int num,bool continuous,int bank=0); void start_music(const char *fname,int num,bool continuous); void start_music(XMIDIEventList *midfile,bool continuous); void start_music_combat(Combat_song song,bool continuous,int bank=0); void stop_music(); int play_sound_effect (int num, int volume = SDL_MIX_MAXVOLUME, int dir = 0, int repeat = 0); int play_wave_sfx(int num, int volume = SDL_MIX_MAXVOLUME, int dir = 0, int repeat = 0); void stop_sound_effects(); bool start_speech(int num,bool wait=false); bool is_speech_enabled() const { return speech_enabled; } void set_speech_enabled(bool ena) { speech_enabled = ena; } bool is_music_enabled() const { return music_enabled; } void set_music_enabled(bool ena) { music_enabled = ena; } bool are_effects_enabled() const { return effects_enabled; } void set_effects_enabled(bool ena) { effects_enabled = ena; } bool is_audio_enabled() const { return audio_enabled; } void set_audio_enabled(bool ena); bool is_music_looping_allowed() const { return allow_music_looping; } void set_allow_music_looping(bool ena) { allow_music_looping = ena; } bool can_sfx(const std::string &game) const; static void channel_complete_callback(int chan); bool is_track_playing(int num) { return midi && midi->is_track_playing(num); } int get_sample_rate() { return actual.freq; } bool is_stereo() { return actual.channels == 2; } MyMidiPlayer *get_midi() {return midi;} Flex *get_sfx_file() { return sfx_file; } }; #endif exult-1.2/audio/Midi.h0000644000175000001440000001003707753476060010345 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_H_ #define _MIDI_H_ #include #ifndef WIN32 //#include "Mixer.h" #endif #include "xmidi.h" // The 'types' of midi drivers enum MidiDriverType { MIDI_DRIVER_NORMAL = 0, // We are outputting using Normal Midi Drivers MIDI_DRIVER_OGG, // We are outputting using Oggs #ifdef USE_FMOPL_MIDI MIDI_DRIVER_FMSYNTH, // We are outputting using FM Synth Driver #endif #ifdef USE_MT32EMU_MIDI MIDI_DRIVER_MT32EMU, // We are outputting using MT32EMU Driver (Ha, you'll never see this!) #endif NUM_MIDI_DRIVER_TYPES // Count of midi drivers }; #include "SDL_mixer.h" #include //---- MidiAbstract ----------------------------------------------------------- class MidiAbstract { public: virtual void start_track(XMIDIEventList *, bool repeat) = 0; virtual void start_sfx(XMIDIEventList *) { } virtual void stop_track(void)=0; virtual void stop_sfx(void) { }; virtual bool is_playing(void)=0; virtual const char *copyright(void)=0; virtual void load_patches(bool force_xmidi) { } virtual bool is_fm_synth() { return false; } virtual bool use_gs127() { return false; } MidiAbstract() {}; virtual ~MidiAbstract() {}; }; //Pseudo device, used purely to create the OGG_MIDI class with something class OGG_MIDI : virtual public MidiAbstract { static void music_complete_callback(void); public: OGG_MIDI(); virtual ~OGG_MIDI(); virtual void start_track(XMIDIEventList *, bool repeat); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); }; //---- MyMidiPlayer ----------------------------------------------------------- class MyMidiPlayer { public: MyMidiPlayer(); ~MyMidiPlayer(); MyMidiPlayer(const char *flexfile); void start_music(int num,bool continuous=false,int bank=0); void start_music(const char *fname,int num,bool continuous=false); void start_track(int num,bool continuous=false,int bank=0); void start_track(const char *fname,int num,bool continuous=false); void start_track(XMIDIEventList *eventlist, bool continuous=false); void start_sound_effect(int num); void stop_sound_effects(); void load_patches(bool force_xmidi=false) { if (midi_device) midi_device->load_patches(force_xmidi); } void stop_music(); bool add_midi_bank(const char *s); void set_music_conversion(int conv); int get_music_conversion() { return music_conversion; } void set_effects_conversion(int conv); int get_effects_conversion() { return effects_conversion; } int get_output_driver_type() { return output_driver_type; } void set_output_driver_type(int); inline bool is_track_playing(int num) { return midi_device && current_track==num && midi_device->is_playing(); } inline int get_current_track() { return (midi_device!=0)&&midi_device->is_playing()?current_track:-1; } inline int is_repeating() { return repeating; } bool is_fm_synth() { return midi_device?midi_device->is_fm_synth():false; } private: MyMidiPlayer(const MyMidiPlayer &m) ; // Cannot call MyMidiPlayer &operator=(const MyMidiPlayer &); // Cannot call void kmidi_start_track(int num,bool continuous=false); std::vector midi_bank; int current_track; bool repeating; MidiAbstract *midi_device; bool initialized; bool init_device(void); int music_conversion; int effects_conversion; int output_driver_type; }; #endif exult-1.2/audio/README0000644000175000001440000000750507502100754010162 Audio and MIDI information -------------------------- The mixer has recently been replaced by using SDL_mixer. This will allow easier porting to other platforms and removes the need to maintain the complex mixer code. The addition of the SDL_mixer was mainly done so that we could easily support OGG/MP3 music, referred to as "Digital Music" in Exult. All Digital SFX and Digital music currently play at 22Khz. This sample rate is high enough for the SFX and digital music as they rarely go above 11Khz, plus SDL_mixer/SDL currently works better at 22khz than 44khz. SDL_mixer has the ability to play MIDI music directly through MIDI ports or by using Timidity. The MIDI support in Exult does not currently make use of SDL_mixer but uses tailor made midi drivers in the midi_drivers directory. A generic SDL_mixer interface is available in the midi_drivers directory called mixer_midiout. To make use of this mixer_midiout simply use the following in Midi.cc (in the relevant sections): ----------------------------------------- #ifdef WIN32 #include "midi_drivers/mixer_midiout.h" #endif ----------------------------------------- #ifdef WIN32 TRY_MIDI_DRIVER(Mixer_MidiOut) #endif ----------------------------------------- Sound Effects ------------- Sound effects were originally played through MIDI but now that the SFX digital sound packs (jmsfx & sqsfx) are available this has been disabled and will not be developed in future. MIDI now only plays the music. Sound effects are loaded when required from the flx files, each time they are played, but the last 6, or so, played are cached in memory to save disk I/O and conversion processing. MIDI Music ---------- Exult music can be played through MIDI using either MIDI ports or Timidity. Conversion is usually applied to the MIDI music using the XMIDI code to convert from the Roland MT-32 voice assignments to General Midi (GM). It is still possible to play directly to a Roland MT-32 by selecting the "none" midi conversion setting. Timidity support works on Linux and should work on Windows. To use it in Linux the timidity.cfg file must be in the directory where the exult executable is run. This appears to be a quirk with SDL_mixer. Linux MIDI out currently uses playmidi or KMIDI. Digital Music ------------- Digital Music using OGG is now available in Exult. This uses the Digital Music pack recorded by Simon Quinn on the Roland MT-32, available on the Exult sourceforge site. This should work on any platform that supports SDL_mixer and will give the closest musical experience to the original Ultima VII games. Additionally, with the Digital Music support, a number of atmospheric SFX tracks are played when no music is playing. The tracks played are as follows: * Day time outside: wind, bird and frog track * Night time: wind track with randomly generated digital sfx crickets * Dungeon: dungeon music track (atmospheric SFX and music) Music tracks always take priority over these SFX tracks and being "music" tracks they will not play if the music has been switched off. These SFX "music" tracks are not available with the MIDI support as they play Roland MT-32 specific voices that cannot be mapped to GM. NOTE: OGG was chosen over MP3 as SDL_mixer has better support for OGG and has OGG supported compiled into the drivers by default, from v1.2.4. Voice/VOC support ----------------- The VOC decoding is partially customised to Exult and the U7 data files. Samples are converted to 22Khz (or to match the audio output sample rate) and expanded to two channels, and some bytes are cut off each end to eliminate harsh clicking. Sample rate conversion has been left in the VOC decoder as currently, v1.2.4 of SDL, does not have good sample rate conversion. The code currently uses a lot of memory as the whole VOC to be played is loaded and converted in RAM, potentially using many megabytes of memory. exult-1.2/audio/conv.h0000644000175000001440000000151007724430450010413 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CONV_H #define CONV_H extern int bgconv[]; #endif exult-1.2/audio/Makefile.am0000644000175000001440000000106207626467713011350 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../objs -I$(srcdir)/../files -I$(srcdir)/../gumps \ -I$(srcdir)/../conf \ $(SDL_CFLAGS) $(KMID_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -I../files -I../conf SUBDIRS = midi_drivers noinst_LTLIBRARIES = libaudio.la libaudio_la_SOURCES = \ Audio.cc \ Audio.h \ Midi.cc \ Midi.h \ conv.cc \ conv.h \ xmidi.cc \ xmidi.h \ soundtest.cc \ soundtest.h \ convmusic.h EXTRA_DIST = \ README CLEANFILES = *~ exult-1.2/audio/Makefile.in0000644000175000001440000003320310061527054011341 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../objs -I$(srcdir)/../files -I$(srcdir)/../gumps \ -I$(srcdir)/../conf \ $(SDL_CFLAGS) $(KMID_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -I../files -I../conf SUBDIRS = midi_drivers noinst_LTLIBRARIES = libaudio.la libaudio_la_SOURCES = \ Audio.cc \ Audio.h \ Midi.cc \ Midi.h \ conv.cc \ conv.h \ xmidi.cc \ xmidi.h \ soundtest.cc \ soundtest.h \ convmusic.h EXTRA_DIST = \ README CLEANFILES = *~ subdir = audio mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libaudio_la_LDFLAGS = libaudio_la_LIBADD = am_libaudio_la_OBJECTS = Audio.lo Midi.lo conv.lo xmidi.lo soundtest.lo libaudio_la_OBJECTS = $(am_libaudio_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/Audio.Plo $(DEPDIR)/Midi.Plo \ @AMDEP_TRUE@ $(DEPDIR)/conv.Plo $(DEPDIR)/soundtest.Plo \ @AMDEP_TRUE@ $(DEPDIR)/xmidi.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libaudio_la_SOURCES) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = README Makefile.am Makefile.in DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(libaudio_la_SOURCES) all: all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu audio/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libaudio.la: $(libaudio_la_OBJECTS) $(libaudio_la_DEPENDENCIES) $(CXXLINK) $(libaudio_la_LDFLAGS) $(libaudio_la_OBJECTS) $(libaudio_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Audio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Midi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/conv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/soundtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/xmidi.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-recursive distclean distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-recursive \ distclean-tags distdir dvi dvi-am dvi-recursive info info-am \ info-recursive install install-am install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive tags tags-recursive uninstall \ uninstall-am uninstall-info-am uninstall-info-recursive \ uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/audio/soundtest.h0000644000175000001440000000164507724430450011507 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SOUNDTEST_H #define SOUNDTEST_H class SoundTester { int song; int sfx; int voice; int active; bool repeat; public: SoundTester(); ~SoundTester(); void test_sound(); }; #endif exult-1.2/audio/soundtest.cc0000644000175000001440000001172207724430450011642 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "gamewin.h" #include "Audio.h" #include "soundtest.h" #include "Scroll_gump.h" #include "mouse.h" #include "exult.h" #include "font.h" #include "tqueue.h" SoundTester::SoundTester() : song(0), sfx(0), voice(0), active(0), repeat(true) { } SoundTester::~SoundTester() { } void SoundTester::test_sound() { Game_window *gwin = Game_window::get_instance(); Image_buffer8 *ibuf = gwin->get_win()->get_ib8(); Font *font = Shape_manager::get_instance()->get_font(4); Audio *audio = Audio::get_ptr(); Scroll_gump *scroll = NULL; char buf[256]; bool looping = true; bool redraw = true; SDL_Event event; int centerx = gwin->get_width()/2; int centery = gwin->get_height()/2; int left = centerx - 65; int first_line = centery-53; int line; int height = 6; int width = 6; Mouse::mouse->hide(); gwin->get_tqueue()->pause(SDL_GetTicks()); do { if (redraw) { scroll = new Scroll_gump(); scroll->add_text(" ~"); scroll->paint(); line = first_line; font->paint_text_fixedwidth(ibuf, "Sound Tester", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, "------------", left, line, width); line += height*2; font->paint_text_fixedwidth(ibuf, " Up - Previous Type", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, " Down - Next Type", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, " Left - Previous Number", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, "Right - Next Number", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, "Enter - Play it", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, " ESC - Leave", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, " R - Repeat Music", left, line, width); line += height; font->paint_text_fixedwidth(ibuf, " S - Stop Music", left, line, width); snprintf (buf, 256, "%2s Music %c %3i %c %s", active==0?"->":"", active==0?'<':' ', song, active==0?'>':' ', repeat?"- Repeat":""); line += height*2; font->paint_text_fixedwidth(ibuf, buf, left, line, width); snprintf (buf, 256, "%2s SFX %c %3i %c", active==1?"->":"", active==1?'<':' ', sfx, active==1?'>':' '); line += height*2; font->paint_text_fixedwidth(ibuf, buf, left, line, width); snprintf (buf, 256, "%2s Voice %c %3i %c", active==2?"->":"", active==2?'<':' ', voice, active==2?'>':' '); line += height*2; font->paint_text_fixedwidth(ibuf, buf, left, line, width); gwin->show(); delete scroll; redraw = false; } SDL_WaitEvent(&event); if(event.type==SDL_KEYDOWN) { redraw = true; switch(event.key.keysym.sym) { case SDLK_ESCAPE: looping = false; break; case SDLK_RETURN: if (active == 0) { audio->stop_music(); audio->start_music (song, repeat, 0); } else if (active == 1) { audio->play_sound_effect (sfx); } else if (active == 2) { audio->cancel_streams(); audio->start_speech (voice, false); } break; case SDLK_r: repeat = repeat?false:true; break; case SDLK_s: if ((event.key.keysym.mod & KMOD_ALT) && (event.key.keysym.mod & KMOD_CTRL)) make_screenshot(true); else audio->stop_music(); break; case SDLK_UP: active = (active + 2) % 3; break; case SDLK_DOWN: active = (active + 1) % 3; break; case SDLK_LEFT: if (active == 0) { song--; if (song < 0) song = 255; } else if (active == 1) { sfx--; if (sfx < 0) sfx = 255; } else if (active == 2) { voice--; if (voice < 0) voice = 255; } break; case SDLK_RIGHT: if (active == 0) { song++; if (song > 255) song = 0; } else if (active == 1) { sfx++; if (sfx > 255) sfx = 0; } else if (active == 2) { voice++; if (voice > 255) voice = 0; } break; default: break; } } } while(looping); gwin->get_tqueue()->resume(SDL_GetTicks()); gwin->paint(); Mouse::mouse->show(); gwin->show(); } exult-1.2/audio/midi_drivers/0000777000175000001440000000000010062225331012031 5exult-1.2/audio/midi_drivers/fmopl.cc0000644000175000001440000007242710054030551013404 /* * Copyright (C) 1999/2000 Tatsuyuki Satoh * Copyright (C) 2001/2002 The ScummVM project * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Header: /cvsroot/exult/exult/audio/midi_drivers/fmopl.cc,v 1.3 2004/05/21 16:57:13 colourles Exp $ * * LGPL licensed version of MAMEs fmopl (V0.37a modified) by * Tatsuyuki Satoh. Included from LGPL'ed AdPlug. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef USE_FMOPL_MIDI #include "common_types.h" #include #include #include #include #include #include #include "fmopl.h" #ifndef UNDER_CE using std::malloc; using std::free; #endif #ifndef PI #define PI 3.14159265358979323846 #endif /* -------------------- preliminary define section --------------------- */ /* attack/decay rate time rate */ #define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */ #define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */ #define FREQ_BITS 24 /* frequency turn */ /* counter bits = 20 , octerve 7 */ #define FREQ_RATE (1<<(FREQ_BITS-20)) #define TL_BITS (FREQ_BITS+2) /* final output shift , limit minimum and maximum */ #define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ #define OPL_MAXOUT (0x7fff< max ) val = max; else if ( val < min ) val = min; return val; } /* status set and IRQ handling */ inline void OPL_STATUS_SET(FM_OPL *OPL,int flag) { /* set status flag */ OPL->status |= flag; if(!(OPL->status & 0x80)) { if(OPL->status & OPL->statusmask) { /* IRQ on */ OPL->status |= 0x80; /* callback user interrupt handler (IRQ is OFF to ON) */ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); } } } /* status reset and IRQ handling */ inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag) { /* reset status flag */ OPL->status &=~flag; if((OPL->status & 0x80)) { if (!(OPL->status & OPL->statusmask) ) { OPL->status &= 0x7f; /* callback user interrupt handler (IRQ is ON to OFF) */ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); } } } /* IRQ mask set */ inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) { OPL->statusmask = flag; /* IRQ handling check */ OPL_STATUS_SET(OPL,0); OPL_STATUS_RESET(OPL,0); } /* ----- key on ----- */ inline void OPL_KEYON(OPL_SLOT *SLOT) { /* sin wave restart */ SLOT->Cnt = 0; /* set attack */ SLOT->evm = ENV_MOD_AR; SLOT->evs = SLOT->evsa; SLOT->evc = EG_AST; SLOT->eve = EG_AED; } /* ----- key off ----- */ inline void OPL_KEYOFF(OPL_SLOT *SLOT) { if( SLOT->evm > ENV_MOD_RR) { /* set envelope counter from envleope output */ SLOT->evm = ENV_MOD_RR; if( !(SLOT->evc&EG_DST) ) //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<evc = EG_DST; SLOT->eve = EG_DED; SLOT->evs = SLOT->evsr; } } /* ---------- calcrate Envelope Generator & Phase Generator ---------- */ /* return : envelope output */ inline uint32 OPL_CALC_SLOT( OPL_SLOT *SLOT ) { /* calcrate envelope generator */ if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) { switch( SLOT->evm ){ case ENV_MOD_AR: /* ATTACK -> DECAY1 */ /* next DR */ SLOT->evm = ENV_MOD_DR; SLOT->evc = EG_DST; SLOT->eve = SLOT->SL; SLOT->evs = SLOT->evsd; break; case ENV_MOD_DR: /* DECAY -> SL or RR */ SLOT->evc = SLOT->SL; SLOT->eve = EG_DED; if(SLOT->eg_typ) { SLOT->evs = 0; } else { SLOT->evm = ENV_MOD_RR; SLOT->evs = SLOT->evsr; } break; case ENV_MOD_RR: /* RR -> OFF */ SLOT->evc = EG_OFF; SLOT->eve = EG_OFF+1; SLOT->evs = 0; break; } } /* calcrate envelope */ return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0); } /* set algorythm connection */ static void set_algorythm( OPL_CH *CH) { int *carrier = &outd[0]; CH->connect1 = CH->CON ? carrier : &feedback2; CH->connect2 = carrier; } /* ---------- frequency counter for operater update ---------- */ inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) { int ksr; /* frequency step counter */ SLOT->Incr = CH->fc * SLOT->mul; ksr = CH->kcode >> SLOT->KSR; if( SLOT->ksr != ksr ) { SLOT->ksr = ksr; /* attack , decay rate recalcration */ SLOT->evsa = SLOT->AR[ksr]; SLOT->evsd = SLOT->DR[ksr]; SLOT->evsr = SLOT->RR[ksr]; } SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); } /* set multi,am,vib,EG-TYP,KSR,mul */ inline void set_mul(FM_OPL *OPL,int slot,int v) { OPL_CH *CH = &OPL->P_CH[slot/2]; OPL_SLOT *SLOT = &CH->SLOT[slot&1]; SLOT->mul = MUL_TABLE[v&0x0f]; SLOT->KSR = (v&0x10) ? 0 : 2; SLOT->eg_typ = (v&0x20)>>5; SLOT->vib = (v&0x40); SLOT->ams = (v&0x80); CALC_FCSLOT(CH,SLOT); } /* set ksl & tl */ inline void set_ksl_tl(FM_OPL *OPL,int slot,int v) { OPL_CH *CH = &OPL->P_CH[slot/2]; OPL_SLOT *SLOT = &CH->SLOT[slot&1]; int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */ SLOT->ksl = ksl ? 3-ksl : 31; SLOT->TL = (int)((v&0x3f)*(0.75/EG_STEP)); /* 0.75db step */ if( !(OPL->mode&0x80) ) { /* not CSM latch total level */ SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); } } /* set attack rate & decay rate */ inline void set_ar_dr(FM_OPL *OPL,int slot,int v) { OPL_CH *CH = &OPL->P_CH[slot/2]; OPL_SLOT *SLOT = &CH->SLOT[slot&1]; int ar = v>>4; int dr = v&0x0f; SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0; SLOT->evsa = SLOT->AR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; SLOT->evsd = SLOT->DR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; } /* set sustain level & release rate */ inline void set_sl_rr(FM_OPL *OPL,int slot,int v) { OPL_CH *CH = &OPL->P_CH[slot/2]; OPL_SLOT *SLOT = &CH->SLOT[slot&1]; int sl = v>>4; int rr = v & 0x0f; SLOT->SL = SL_TABLE[sl]; if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL; SLOT->RR = &OPL->DR_TABLE[rr<<2]; SLOT->evsr = SLOT->RR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; } /* operator output calcrator */ #define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env] /* ---------- calcrate one of channel ---------- */ inline void OPL_CALC_CH( OPL_CH *CH ) { uint32 env_out; OPL_SLOT *SLOT; feedback2 = 0; /* SLOT 1 */ SLOT = &CH->SLOT[SLOT1]; env_out=OPL_CALC_SLOT(SLOT); if( env_out < EG_ENT-1 ) { /* PG */ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); else SLOT->Cnt += SLOT->Incr; /* connectoion */ if(CH->FB) { int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB; CH->op1_out[1] = CH->op1_out[0]; *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1); } else { *CH->connect1 += OP_OUT(SLOT,env_out,0); } }else { CH->op1_out[1] = CH->op1_out[0]; CH->op1_out[0] = 0; } /* SLOT 2 */ SLOT = &CH->SLOT[SLOT2]; env_out=OPL_CALC_SLOT(SLOT); if( env_out < EG_ENT-1 ) { /* PG */ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); else SLOT->Cnt += SLOT->Incr; /* connectoion */ outd[0] += OP_OUT(SLOT,env_out, feedback2); } } /* ---------- calcrate rythm block ---------- */ #define WHITE_NOISE_db 6.0 inline void OPL_CALC_RH( OPL_CH *CH ) { uint32 env_tam,env_sd,env_top,env_hh; int whitenoise = int((std::rand()&1)*(WHITE_NOISE_db/EG_STEP)); int tone8; OPL_SLOT *SLOT; int env_out; /* BD : same as FM serial mode and output level is large */ feedback2 = 0; /* SLOT 1 */ SLOT = &CH[6].SLOT[SLOT1]; env_out=OPL_CALC_SLOT(SLOT); if( env_out < EG_ENT-1 ) { /* PG */ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); else SLOT->Cnt += SLOT->Incr; /* connectoion */ if(CH[6].FB) { int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB; CH[6].op1_out[1] = CH[6].op1_out[0]; feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1); } else { feedback2 = OP_OUT(SLOT,env_out,0); } }else { feedback2 = 0; CH[6].op1_out[1] = CH[6].op1_out[0]; CH[6].op1_out[0] = 0; } /* SLOT 2 */ SLOT = &CH[6].SLOT[SLOT2]; env_out=OPL_CALC_SLOT(SLOT); if( env_out < EG_ENT-1 ) { /* PG */ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); else SLOT->Cnt += SLOT->Incr; /* connectoion */ outd[0] += OP_OUT(SLOT,env_out, feedback2)*2; } // SD (17) = mul14[fnum7] + white noise // TAM (15) = mul15[fnum8] // TOP (18) = fnum6(mul18[fnum8]+whitenoise) // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise; env_tam=OPL_CALC_SLOT(SLOT8_1); env_top=OPL_CALC_SLOT(SLOT8_2); env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise; /* PG */ if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE); else SLOT7_1->Cnt += 2*SLOT7_1->Incr; if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE); else SLOT7_2->Cnt += (CH[7].fc*8); if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE); else SLOT8_1->Cnt += SLOT8_1->Incr; if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE); else SLOT8_2->Cnt += (CH[8].fc*48); tone8 = OP_OUT(SLOT8_2,whitenoise,0 ); /* SD */ if( env_sd < EG_ENT-1 ) outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8; /* TAM */ if( env_tam < EG_ENT-1 ) outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2; /* TOP-CY */ if( env_top < EG_ENT-1 ) outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2; /* HH */ if( env_hh < EG_ENT-1 ) outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2; } /* ----------- initialize time tabls ----------- */ static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE ) { int i; double rate; /* make attack rate & decay rate tables */ for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; for (i = 4;i <= 60;i++){ rate = OPL->freqbase; /* frequency rate */ if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ rate *= (double)(EG_ENT<AR_TABLE[i] = (int)(rate / ARRATE); OPL->DR_TABLE[i] = (int)(rate / DRRATE); } for (i = 60;i < 76;i++) { OPL->AR_TABLE[i] = EG_AED-1; OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; } } /* ---------- generic table initialize ---------- */ static int OPLOpenTable( void ) { int s,t; double rate; int i,j; double pom; /* allocate dynamic tables */ if( (TL_TABLE = (int *)malloc(TL_MAX*2*sizeof(int))) == NULL) return 0; if( (SIN_TABLE = (int **)malloc(SIN_ENT*4 *sizeof(int *))) == NULL) { free(TL_TABLE); return 0; } if( (AMS_TABLE = (int *)malloc(AMS_ENT*2 *sizeof(int))) == NULL) { free(TL_TABLE); free(SIN_TABLE); return 0; } if( (VIB_TABLE = (int *)malloc(VIB_ENT*2 *sizeof(int))) == NULL) { free(TL_TABLE); free(SIN_TABLE); free(AMS_TABLE); return 0; } /* make total level table */ for (t = 0;t < EG_ENT-1 ;t++){ rate = ((1< voltage */ TL_TABLE[ t] = (int)rate; TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; } /* fill volume off area */ for ( t = EG_ENT-1; t < TL_MAX ;t++){ TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; } /* make sinwave table (total level offet) */ /* degree 0 = degree 180 = off */ SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; for (s = 1;s <= SIN_ENT/4;s++){ pom = std::sin(2*PI*s/SIN_ENT); /* sin */ pom = 20*std::log10(1/pom); /* decibel */ j = int(pom / EG_STEP); /* TL_TABLE steps */ /* degree 0 - 90 , degree 180 - 90 : plus section */ SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; /* degree 180 - 270 , degree 360 - 270 : minus section */ SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; } for (s = 0;s < SIN_ENT;s++) { SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)]; SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s]; } /* envelope counter -> envelope output table */ for (i=0; i= EG_ENT ) pom = EG_ENT-1; */ ENV_CURVE[i] = (int)pom; /* DECAY ,RELEASE curve */ ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; } /* off */ ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; /* make LFO ams table */ for (i=0; iSLOT[SLOT1]; OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; /* all key off */ OPL_KEYOFF(slot1); OPL_KEYOFF(slot2); /* total level latch */ slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); /* key on */ CH->op1_out[0] = CH->op1_out[1] = 0; OPL_KEYON(slot1); OPL_KEYON(slot2); } /* ---------- opl initialize ---------- */ static void OPL_initalize(FM_OPL *OPL) { int fn; /* frequency base */ OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; /* Timer base time */ OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 ); /* make time tables */ init_timetables( OPL , OPL_ARRATE , OPL_DRRATE ); /* make fnumber -> increment counter table */ for( fn=0 ; fn < 1024 ; fn++ ) { OPL->FN_TABLE[fn] = (uint32)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2); } /* LFO freq.table */ OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT*(1<rate * 3.7 * ((double)OPL->clock/3600000) : 0); OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT*(1<rate * 6.4 * ((double)OPL->clock/3600000) : 0); } /* ---------- write a OPL registers ---------- */ void OPLWriteReg(FM_OPL *OPL, int r, int v) { OPL_CH *CH; int slot; uint32 block_fnum; switch(r&0xe0) { case 0x00: /* 00-1f:controll */ switch(r&0x1f) { case 0x01: /* wave selector enable */ if(OPL->type&OPL_TYPE_WAVESEL) { OPL->wavesel = v&0x20; if(!OPL->wavesel) { /* preset compatible mode */ int c; for(c=0;cmax_ch;c++) { OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; } } } return; case 0x02: /* Timer 1 */ OPL->T[0] = (256-v)*4; break; case 0x03: /* Timer 2 */ OPL->T[1] = (256-v)*16; return; case 0x04: /* IRQ clear / mask and Timer enable */ if(v&0x80) { /* IRQ flag clear */ OPL_STATUS_RESET(OPL,0x7f); } else { /* set IRQ mask ,timer enable*/ uint8 st1 = v&1; uint8 st2 = (v>>1)&1; /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ OPL_STATUS_RESET(OPL,v&0x78); OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01); /* timer 2 */ if(OPL->st[1] != st2) { double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; OPL->st[1] = st2; if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); } /* timer 1 */ if(OPL->st[0] != st1) { double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; OPL->st[0] = st1; if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); } } return; } break; case 0x20: /* am,vib,ksr,eg type,mul */ slot = slot_array[r&0x1f]; if(slot == -1) return; set_mul(OPL,slot,v); return; case 0x40: slot = slot_array[r&0x1f]; if(slot == -1) return; set_ksl_tl(OPL,slot,v); return; case 0x60: slot = slot_array[r&0x1f]; if(slot == -1) return; set_ar_dr(OPL,slot,v); return; case 0x80: slot = slot_array[r&0x1f]; if(slot == -1) return; set_sl_rr(OPL,slot,v); return; case 0xa0: switch(r) { case 0xbd: /* amsep,vibdep,r,bd,sd,tom,tc,hh */ { uint8 rkey = OPL->rythm^v; OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0]; OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0]; OPL->rythm = v&0x3f; if(OPL->rythm&0x20) { /* BD key on/off */ if(rkey&0x10) { if(v&0x10) { OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0; OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]); OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]); } else { OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]); OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]); } } /* SD key on/off */ if(rkey&0x08) { if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]); else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]); }/* TAM key on/off */ if(rkey&0x04) { if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]); else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]); } /* TOP-CY key on/off */ if(rkey&0x02) { if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]); else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]); } /* HH key on/off */ if(rkey&0x01) { if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]); else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]); } } } return; } /* keyon,block,fnum */ if( (r&0x0f) > 8) return; CH = &OPL->P_CH[r&0x0f]; if(!(r&0x10)) { /* a0-a8 */ block_fnum = (CH->block_fnum&0x1f00) | v; } else { /* b0-b8 */ int keyon = (v>>5)&1; block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); if(CH->keyon != keyon) { if( (CH->keyon=keyon) ) { CH->op1_out[0] = CH->op1_out[1] = 0; OPL_KEYON(&CH->SLOT[SLOT1]); OPL_KEYON(&CH->SLOT[SLOT2]); } else { OPL_KEYOFF(&CH->SLOT[SLOT1]); OPL_KEYOFF(&CH->SLOT[SLOT2]); } } } /* update */ if(CH->block_fnum != block_fnum) { int blockRv = 7-(block_fnum>>10); int fnum = block_fnum&0x3ff; CH->block_fnum = block_fnum; CH->ksl_base = KSL_TABLE[block_fnum>>6]; CH->fc = OPL->FN_TABLE[fnum]>>blockRv; CH->kcode = CH->block_fnum>>9; if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1; CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); } return; case 0xc0: /* FB,C */ if( (r&0x0f) > 8) return; CH = &OPL->P_CH[r&0x0f]; { int feedback = (v>>1)&7; CH->FB = feedback ? (8+1) - feedback : 0; CH->CON = v&1; set_algorythm(CH); } return; case 0xe0: /* wave type */ slot = slot_array[r&0x1f]; if(slot == -1) return; CH = &OPL->P_CH[slot/2]; if(OPL->wavesel) { CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT]; } return; } } /* lock/unlock for common table */ static int OPL_LockTable(void) { num_lock++; if(num_lock>1) return 0; /* first time */ cur_chip = NULL; /* allocate total level table (128kb space) */ if( !OPLOpenTable() ) { num_lock--; return -1; } return 0; } static void OPL_UnLockTable(void) { if(num_lock) num_lock--; if(num_lock) return; /* last time */ cur_chip = NULL; OPLCloseTable(); } /*******************************************************************************/ /* YM3812 local section */ /*******************************************************************************/ /* ---------- update one of chip ----------- */ void YM3812UpdateOne(FM_OPL *OPL, sint16 *buffer, int length) { int i; int data; sint16 *buf = buffer; uint32 amsCnt = OPL->amsCnt; uint32 vibCnt = OPL->vibCnt; uint8 rythm = OPL->rythm&0x20; OPL_CH *CH,*R_CH; if( (void *)OPL != cur_chip ){ cur_chip = (void *)OPL; /* channel pointers */ S_CH = OPL->P_CH; E_CH = &S_CH[9]; /* rythm slot */ SLOT7_1 = &S_CH[7].SLOT[SLOT1]; SLOT7_2 = &S_CH[7].SLOT[SLOT2]; SLOT8_1 = &S_CH[8].SLOT[SLOT1]; SLOT8_2 = &S_CH[8].SLOT[SLOT2]; /* LFO state */ amsIncr = OPL->amsIncr; vibIncr = OPL->vibIncr; ams_table = OPL->ams_table; vib_table = OPL->vib_table; } R_CH = rythm ? &S_CH[6] : E_CH; for( i=0; i < length ; i++ ) { /* channel A channel B channel C */ /* LFO */ ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; outd[0] = 0; /* FM part */ for(CH=S_CH ; CH < R_CH ; CH++) OPL_CALC_CH(CH); /* Rythn part */ if(rythm) OPL_CALC_RH(S_CH); /* limit check */ data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); /* store to sound buffer */ buf[i] = data >> OPL_OUTSB; } OPL->amsCnt = amsCnt; OPL->vibCnt = vibCnt; } /* ---------- reset a chip ---------- */ void OPLResetChip(FM_OPL *OPL) { int c,s; int i; /* reset chip */ OPL->mode = 0; /* normal mode */ OPL_STATUS_RESET(OPL,0x7f); /* reset with register write */ OPLWriteReg(OPL,0x01,0); /* wabesel disable */ OPLWriteReg(OPL,0x02,0); /* Timer1 */ OPLWriteReg(OPL,0x03,0); /* Timer2 */ OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); /* reset OPerator paramater */ for( c = 0 ; c < OPL->max_ch ; c++ ) { OPL_CH *CH = &OPL->P_CH[c]; /* OPL->P_CH[c].PAN = OPN_CENTER; */ for(s = 0 ; s < 2 ; s++ ) { /* wave table */ CH->SLOT[s].wavetable = &SIN_TABLE[0]; /* CH->SLOT[s].evm = ENV_MOD_RR; */ CH->SLOT[s].evc = EG_OFF; CH->SLOT[s].eve = EG_OFF+1; CH->SLOT[s].evs = 0; } } } /* ---------- Create a virtual YM3812 ---------- */ /* 'rate' is sampling rate and 'bufsiz' is the size of the */ FM_OPL *OPLCreate(int type, int clock, int rate) { char *ptr; FM_OPL *OPL; int state_size; int max_ch = 9; /* normaly 9 channels */ if( OPL_LockTable() ==-1) return NULL; /* allocate OPL state space */ state_size = sizeof(FM_OPL); state_size += sizeof(OPL_CH)*max_ch; /* allocate memory block */ ptr = (char *)malloc(state_size); if(ptr==NULL) return NULL; /* clear */ memset(ptr,0,state_size); OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL); OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch; /* set channel state pointer */ OPL->type = type; OPL->clock = clock; OPL->rate = rate; OPL->max_ch = max_ch; /* init grobal tables */ OPL_initalize(OPL); /* reset chip */ OPLResetChip(OPL); return OPL; } /* ---------- Destroy one of vietual YM3812 ---------- */ void OPLDestroy(FM_OPL *OPL) { OPL_UnLockTable(); free(OPL); } /* ---------- Option handlers ---------- */ void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) { OPL->TimerHandler = TimerHandler; OPL->TimerParam = channelOffset; } void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) { OPL->IRQHandler = IRQHandler; OPL->IRQParam = param; } void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) { OPL->UpdateHandler = UpdateHandler; OPL->UpdateParam = param; } /* ---------- YM3812 I/O interface ---------- */ int OPLWrite(FM_OPL *OPL,int a,int v) { if( !(a&1) ) { /* address port */ OPL->address = v & 0xff; } else { /* data port */ if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); OPLWriteReg(OPL,OPL->address,v); } return OPL->status>>7; } unsigned char OPLRead(FM_OPL *OPL,int a) { if( !(a&1) ) { /* status port */ return OPL->status & (OPL->statusmask|0x80); } /* data port */ switch(OPL->address) { case 0x05: /* KeyBoard IN */ CERR(("OPL:read unmapped KEYBOARD port\n")); return 0; case 0x19: /* I/O DATA */ CERR(("OPL:read unmapped I/O port\n")); return 0; case 0x1a: /* PCM-DATA */ return 0; } return 0; } int OPLTimerOver(FM_OPL *OPL,int c) { if( c ) { /* Timer B */ OPL_STATUS_SET(OPL,0x20); } else { /* Timer A */ OPL_STATUS_SET(OPL,0x40); /* CSM mode key,TL controll */ if( OPL->mode & 0x80 ) { /* CSM mode total level latch and auto key on */ int ch; if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); for(ch=0;ch<9;ch++) CSMKeyControll( &OPL->P_CH[ch] ); } } /* reload timer */ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); return OPL->status>>7; } #endif //USE_FMOPL_MIDI exult-1.2/audio/midi_drivers/KMIDI.h0000644000175000001440000000237407550423657013004 //-*-Mode: C++;-*- /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_KMIDI_h_ #define _MIDI_driver_KMIDI_h_ #if HAVE_LIBKMIDI #include #include "Flex.h" #include "Table.h" #include "Midi.h" #include class KMIDI : virtual public MidiAbstract { bool repeat_; public: virtual void start_track(XMIDIEventList *, bool repeat); // virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); KMIDI(); virtual ~KMIDI(); }; #endif #endif // Multiple inclusion protector exult-1.2/audio/midi_drivers/fmopldrv.h0000644000175000001440000000600607524010427013760 /* Copyright (C) 2000, 2001, 2002 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef FMOPLDRV_H #define FMOPLDRV_H #ifdef USE_FMOPL_MIDI #include "common_types.h" #include "fmopl.h" struct midi_event; // // The Internal OplDriver. Only slightly modified for exult // class OplDriver { public: /* error codes returned by open. * can be converted to a string with get_error_name() */ enum { MERR_CANNOT_CONNECT = 1, MERR_STREAMING_NOT_AVAILABLE = 2, MERR_DEVICE_NOT_AVAILABLE = 3, MERR_ALREADY_OPEN = 4, }; // Modulation Registers #define INDEX_AVEKM_M 0 #define INDEX_KSLTL_M 2 #define INDEX_AD_M 4 #define INDEX_SR_M 6 #define INDEX_WAVE_M 8 // Carrier Registers #define INDEX_AVEKM_C 1 #define INDEX_KSLTL_C 3 #define INDEX_AD_C 5 #define INDEX_SR_C 7 #define INDEX_WAVE_C 9 #define INDEX_FB_C 10 #define INDEX_PERC 11 #define CHP_CHAN 0 #define CHP_NOTE 1 #define CHP_COUNTER 2 #define CHP_VEL 3 /* open the midi driver. * returns 0 if successful. * otherwise an error code. */ int open(int sample_rate); /* close the midi driver */ void close(); /* output a packed midi command to the midi stream * valid only if mode is MO_SIMPLE */ void OplDriver::send(uint32 b); /* retrieve a string representation of an error code */ static const char *get_error_name(int error_code); // Loads the mt32 bank from /XMIDI.AD void LoadMT32Bank(bool force_xmidi); void generate_samples(sint16 *buf, uint32 len); OplDriver(); ~OplDriver(); private: struct midi_channel { int inum; unsigned char ins[12]; bool xmidi; int xmidi_bank; int vol; int expression; int nshift; int on; int pitchbend; }; struct xmidibank { unsigned char insbank[128][12]; }; enum { ADLIB_MELODIC = 0, ADLIB_RYTHM = 1 }; void midi_write_adlib(unsigned int reg, unsigned char val); void midi_fm_instrument(int voice, unsigned char *inst); int midi_calc_volume(int chan, int vel); void midi_update_volume(int chan); void midi_fm_volume(int voice, int volume); void midi_fm_playnote(int voice, int note, int volume, int pitchbend); void midi_fm_endnote(int voice); unsigned char adlib_data[256]; void LoadXMIDIBank(const char *fn); void LoadU7VBank(const char *fn); int chp[9][4]; unsigned char myinsbank[128][12]; xmidibank *xmidibanks[128]; FM_OPL *_opl; midi_channel ch[16]; }; #endif //USE_FMOPL_MIDI #endif //FMOPLDRV_H exult-1.2/audio/midi_drivers/README0000644000175000001440000000030407427573137012647 All the individual MIDI drivers live here. Notes: repeats - where used in the code - means: -2 continuous 0 single 1+ Play this many more times after the current play-through has completed exult-1.2/audio/midi_drivers/mixer_midiout.cc0000644000175000001440000000441107550423657015155 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif //#ifndef ALPHA_LINUX_CXX //# include //# include //# include //# include //# include //#endif #include #include "fnames.h" using std::cerr; using std::endl; #include "mixer_midiout.h" static Mix_Music *mixermusic; // // Woohoo. This is easy with SDL_mixer! :) // Mixer_MidiOut::Mixer_MidiOut() { //Point to music finish cleanup code Mix_HookMusicFinished(music_complete_callback); } Mixer_MidiOut::~Mixer_MidiOut() { // Stop any current player stop_track(); stop_sfx(); } void Mixer_MidiOut::stop_track(void) { Mix_HaltMusic(); if(mixermusic) { Mix_FreeMusic(mixermusic); mixermusic = NULL; } } //Clean up last track played, freeing memory each time void Mixer_MidiOut::music_complete_callback(void) { if(mixermusic) { Mix_FreeMusic(mixermusic); mixermusic = NULL; } } bool Mixer_MidiOut::is_playing(void) { return Mix_PlayingMusic()!=0; } void Mixer_MidiOut::start_track(XMIDIEventList *event_list,bool repeat) { const char *name = MIDITMPFILE; event_list->Write(name); #if DEBUG cerr << "Starting midi sequence with Mixer_MidiOut" << endl; #endif stop_track(); mixermusic = Mix_LoadMUS(name); Mix_PlayMusic(mixermusic, repeat); Mix_VolumeMusic(MIX_MAX_VOLUME); //Balance volume with other music types } void Mixer_MidiOut::start_sfx(XMIDIEventList *event_list) { //Defunct? } void Mixer_MidiOut::stop_sfx(void) { //Defunct? } const char *Mixer_MidiOut::copyright(void) { return "Internal SDL_mixer midi out"; } exult-1.2/audio/midi_drivers/fmopldrv.cc0000644000175000001440000013305610002255366014122 /* * Copyright (C) 2001 Ludvig Strigeus * Copyright (C) 2001/2002 The ScummVM project * Copyright (C) 2002-2004 The Exult Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Header: /cvsroot/exult/exult/audio/midi_drivers/fmopldrv.cc,v 1.6 2004/01/17 15:55:34 colourles Exp $ */ /* * EmuMIDI support by Lionel Ulmer copied from * AdPlug (http://adplug.sourceforge.net) */ #ifdef HAVE_CONFIG_H # include #endif #ifdef USE_FMOPL_MIDI #include #include "common_types.h" #ifndef PENTAGRAM #include "game.h" #endif #include "Flex.h" #include "xmidi.h" #include "exceptions.h" /* The Bugs could be some strange timing issues with generate_samples(). Haven't looked into the way that scummvm works, but if too many samples are generated, you'll start to get problems with the midi clock. Some notes may not even be heard, and other notes will play for far too long. Haven't looked at the way scummvm handles multiple threads, but it really looks like midiemu_callback_thread(), send(), and generate_samples() are not multiple thread safe. send() and consequently generate_samples() may try to write tothe OPL device while generate_samples() tries to read from it. Something like this wouldn't be noticed in most cases, but it's possible it would cause a problem, especially on a SMP machine. The note on code (0x90) isn't properly detecting notes with velocity 0 as actually being note off's. In some cases, it will attempt to play them. This can cause BIG problems. In Exult I was getting really bad sounding music with notes that would just seem to go on forever. Also the note on code isn't acting properly according to the midi specs when a note is attempted to be played, when the same note, on the same channel is already playing. Midi specs state that the previous note is supposed to be stoped, while the current code instead allocates another voice and plays both notes. Last problem (and I don't know if this is relevant to scummvm) there is no drum kit. Normally Midi Channel 10 (which is really channel 9 in code) is a drum kit. If that channel is attempted to be played like a standard melodic channel, things will sound really really bad. It is usually better just to ignore the channel Pitch wheel, doesn't keep old velocity. Volume Controller only effects new note, doens't effect old. Expression Controller not implemented */ //#define LUCAS_MODE // We fudge with the velocity. If it's 16, it complies to AIL 2.0 Specs #define VEL_FUDGE 4 #include "fmopldrv.h" #include "fmopl.h" #include "utils.h" #include "databuf.h" /* retrieve a string representation of an error code */ const char *OplDriver::get_error_name(int error_code) { static const char *const midi_errors[] = { "No error", "Cannot connect", "Streaming not available", "Device not available", "Driver already open" }; if ((uint32) error_code >= sizeof(midi_errors)) return "Unknown Error"; return midi_errors[error_code]; } /* This is the internal emulated MIDI driver using the included OPL2 sound chip * FM instrument definitions below borrowed from the Allegro library by * Phil Hassey, (www.imitationpickles.org) */ static unsigned char midi_fm_instruments_table[128][11] = { /* This set of GM instrument patches was provided by Jorrit Rouwe... */ {0x21, 0x21, 0x8f, 0x0c, 0xf2, 0xf2, 0x45, 0x76, 0x00, 0x00, 0x08}, /* Acoustic Grand */ {0x31, 0x21, 0x4b, 0x09, 0xf2, 0xf2, 0x54, 0x56, 0x00, 0x00, 0x08}, /* Bright Acoustic */ {0x31, 0x21, 0x49, 0x09, 0xf2, 0xf2, 0x55, 0x76, 0x00, 0x00, 0x08}, /* Electric Grand */ {0xb1, 0x61, 0x0e, 0x09, 0xf2, 0xf3, 0x3b, 0x0b, 0x00, 0x00, 0x06}, /* Honky-Tonk */ {0x01, 0x21, 0x57, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00}, /* Electric Piano 1 */ {0x01, 0x21, 0x93, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00}, /* Electric Piano 2 */ {0x21, 0x36, 0x80, 0x17, 0xa2, 0xf1, 0x01, 0xd5, 0x00, 0x00, 0x08}, /* Harpsichord */ {0x01, 0x01, 0x92, 0x09, 0xc2, 0xc2, 0xa8, 0x58, 0x00, 0x00, 0x0a}, /* Clav */ {0x0c, 0x81, 0x5c, 0x09, 0xf6, 0xf3, 0x54, 0xb5, 0x00, 0x00, 0x00}, /* Celesta */ {0x07, 0x11, 0x97, 0x89, 0xf6, 0xf5, 0x32, 0x11, 0x00, 0x00, 0x02}, /* Glockenspiel */ {0x17, 0x01, 0x21, 0x09, 0x56, 0xf6, 0x04, 0x04, 0x00, 0x00, 0x02}, /* Music Box */ {0x18, 0x81, 0x62, 0x09, 0xf3, 0xf2, 0xe6, 0xf6, 0x00, 0x00, 0x00}, /* Vibraphone */ {0x18, 0x21, 0x23, 0x09, 0xf7, 0xe5, 0x55, 0xd8, 0x00, 0x00, 0x00}, /* Marimba */ {0x15, 0x01, 0x91, 0x09, 0xf6, 0xf6, 0xa6, 0xe6, 0x00, 0x00, 0x04}, /* Xylophone */ {0x45, 0x81, 0x59, 0x89, 0xd3, 0xa3, 0x82, 0xe3, 0x00, 0x00, 0x0c}, /* Tubular Bells */ {0x03, 0x81, 0x49, 0x89, 0x74, 0xb3, 0x55, 0x05, 0x01, 0x00, 0x04}, /* Dulcimer */ {0x71, 0x31, 0x92, 0x09, 0xf6, 0xf1, 0x14, 0x07, 0x00, 0x00, 0x02}, /* Drawbar Organ */ {0x72, 0x30, 0x14, 0x09, 0xc7, 0xc7, 0x58, 0x08, 0x00, 0x00, 0x02}, /* Percussive Organ */ {0x70, 0xb1, 0x44, 0x09, 0xaa, 0x8a, 0x18, 0x08, 0x00, 0x00, 0x04}, /* Rock Organ */ {0x23, 0xb1, 0x93, 0x09, 0x97, 0x55, 0x23, 0x14, 0x01, 0x00, 0x04}, /* Church Organ */ {0x61, 0xb1, 0x13, 0x89, 0x97, 0x55, 0x04, 0x04, 0x01, 0x00, 0x00}, /* Reed Organ */ {0x24, 0xb1, 0x48, 0x09, 0x98, 0x46, 0x2a, 0x1a, 0x01, 0x00, 0x0c}, /* Accoridan */ {0x61, 0x21, 0x13, 0x09, 0x91, 0x61, 0x06, 0x07, 0x01, 0x00, 0x0a}, /* Harmonica */ {0x21, 0xa1, 0x13, 0x92, 0x71, 0x61, 0x06, 0x07, 0x00, 0x00, 0x06}, /* Tango Accordian */ {0x02, 0x41, 0x9c, 0x89, 0xf3, 0xf3, 0x94, 0xc8, 0x01, 0x00, 0x0c}, /* Acoustic Guitar(nylon) */ {0x03, 0x11, 0x54, 0x09, 0xf3, 0xf1, 0x9a, 0xe7, 0x01, 0x00, 0x0c}, /* Acoustic Guitar(steel) */ {0x23, 0x21, 0x5f, 0x09, 0xf1, 0xf2, 0x3a, 0xf8, 0x00, 0x00, 0x00}, /* Electric Guitar(jazz) */ {0x03, 0x21, 0x87, 0x89, 0xf6, 0xf3, 0x22, 0xf8, 0x01, 0x00, 0x06}, /* Electric Guitar(clean) */ {0x03, 0x21, 0x47, 0x09, 0xf9, 0xf6, 0x54, 0x3a, 0x00, 0x00, 0x00}, /* Electric Guitar(muted) */ {0x23, 0x21, 0x4a, 0x0e, 0x91, 0x84, 0x41, 0x19, 0x01, 0x00, 0x08}, /* Overdriven Guitar */ {0x23, 0x21, 0x4a, 0x09, 0x95, 0x94, 0x19, 0x19, 0x01, 0x00, 0x08}, /* Distortion Guitar */ {0x09, 0x84, 0xa1, 0x89, 0x20, 0xd1, 0x4f, 0xf8, 0x00, 0x00, 0x08}, /* Guitar Harmonics */ {0x21, 0xa2, 0x1e, 0x09, 0x94, 0xc3, 0x06, 0xa6, 0x00, 0x00, 0x02}, /* Acoustic Bass */ {0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a}, /* Electric Bass(finger) */ {0x31, 0x31, 0x8d, 0x09, 0xf1, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a}, /* Electric Bass(pick) */ {0x31, 0x32, 0x5b, 0x09, 0x51, 0x71, 0x28, 0x48, 0x00, 0x00, 0x0c}, /* Fretless Bass */ {0x01, 0x21, 0x8b, 0x49, 0xa1, 0xf2, 0x9a, 0xdf, 0x00, 0x00, 0x08}, /* Slap Bass 1 */ {0x21, 0x21, 0x8b, 0x11, 0xa2, 0xa1, 0x16, 0xdf, 0x00, 0x00, 0x08}, /* Slap Bass 2 */ {0x31, 0x31, 0x8b, 0x09, 0xf4, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a}, /* Synth Bass 1 */ {0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a}, /* Synth Bass 2 */ {0x31, 0x21, 0x15, 0x09, 0xdd, 0x56, 0x13, 0x26, 0x01, 0x00, 0x08}, /* Violin */ {0x31, 0x21, 0x16, 0x09, 0xdd, 0x66, 0x13, 0x06, 0x01, 0x00, 0x08}, /* Viola */ {0x71, 0x31, 0x49, 0x09, 0xd1, 0x61, 0x1c, 0x0c, 0x01, 0x00, 0x08}, /* Cello */ {0x21, 0x23, 0x4d, 0x89, 0x71, 0x72, 0x12, 0x06, 0x01, 0x00, 0x02}, /* Contrabass */ {0xf1, 0xe1, 0x40, 0x09, 0xf1, 0x6f, 0x21, 0x16, 0x01, 0x00, 0x02}, /* Tremolo Strings */ {0x02, 0x01, 0x1a, 0x89, 0xf5, 0x85, 0x75, 0x35, 0x01, 0x00, 0x00}, /* Pizzicato Strings */ {0x02, 0x01, 0x1d, 0x89, 0xf5, 0xf3, 0x75, 0xf4, 0x01, 0x00, 0x00}, /* Orchestral Strings */ {0x10, 0x11, 0x41, 0x09, 0xf5, 0xf2, 0x05, 0xc3, 0x01, 0x00, 0x02}, /* Timpani */ {0x21, 0xa2, 0x9b, 0x0a, 0xb1, 0x72, 0x25, 0x08, 0x01, 0x00, 0x0e}, /* String Ensemble 1 */ {0xa1, 0x21, 0x98, 0x09, 0x7f, 0x3f, 0x03, 0x07, 0x01, 0x01, 0x00}, /* String Ensemble 2 */ {0xa1, 0x61, 0x93, 0x09, 0xc1, 0x4f, 0x12, 0x05, 0x00, 0x00, 0x0a}, /* SynthStrings 1 */ {0x21, 0x61, 0x18, 0x09, 0xc1, 0x4f, 0x22, 0x05, 0x00, 0x00, 0x0c}, /* SynthStrings 2 */ {0x31, 0x72, 0x5b, 0x8c, 0xf4, 0x8a, 0x15, 0x05, 0x00, 0x00, 0x00}, /* Choir Aahs */ {0xa1, 0x61, 0x90, 0x09, 0x74, 0x71, 0x39, 0x67, 0x00, 0x00, 0x00}, /* Voice Oohs */ {0x71, 0x72, 0x57, 0x09, 0x54, 0x7a, 0x05, 0x05, 0x00, 0x00, 0x0c}, /* Synth Voice */ {0x90, 0x41, 0x00, 0x09, 0x54, 0xa5, 0x63, 0x45, 0x00, 0x00, 0x08}, /* Orchestra Hit */ {0x21, 0x21, 0x92, 0x0a, 0x85, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c}, /* Trumpet */ {0x21, 0x21, 0x94, 0x0e, 0x75, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c}, /* Trombone */ {0x21, 0x61, 0x94, 0x09, 0x76, 0x82, 0x15, 0x37, 0x00, 0x00, 0x0c}, /* Tuba */ {0x31, 0x21, 0x43, 0x09, 0x9e, 0x62, 0x17, 0x2c, 0x01, 0x01, 0x02}, /* Muted Trumpet */ {0x21, 0x21, 0x9b, 0x09, 0x61, 0x7f, 0x6a, 0x0a, 0x00, 0x00, 0x02}, /* French Horn */ {0x61, 0x22, 0x8a, 0x0f, 0x75, 0x74, 0x1f, 0x0f, 0x00, 0x00, 0x08}, /* Brass Section */ {0xa1, 0x21, 0x86, 0x8c, 0x72, 0x71, 0x55, 0x18, 0x01, 0x00, 0x00}, /* SynthBrass 1 */ {0x21, 0x21, 0x4d, 0x09, 0x54, 0xa6, 0x3c, 0x1c, 0x00, 0x00, 0x08}, /* SynthBrass 2 */ {0x31, 0x61, 0x8f, 0x09, 0x93, 0x72, 0x02, 0x0b, 0x01, 0x00, 0x08}, /* Soprano Sax */ {0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x03, 0x09, 0x01, 0x00, 0x08}, /* Alto Sax */ {0x31, 0x61, 0x91, 0x09, 0x93, 0x82, 0x03, 0x09, 0x01, 0x00, 0x0a}, /* Tenor Sax */ {0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x0f, 0x0f, 0x01, 0x00, 0x0a}, /* Baritone Sax */ {0x21, 0x21, 0x4b, 0x09, 0xaa, 0x8f, 0x16, 0x0a, 0x01, 0x00, 0x08}, /* Oboe */ {0x31, 0x21, 0x90, 0x09, 0x7e, 0x8b, 0x17, 0x0c, 0x01, 0x01, 0x06}, /* English Horn */ {0x31, 0x32, 0x81, 0x09, 0x75, 0x61, 0x19, 0x19, 0x01, 0x00, 0x00}, /* Bassoon */ {0x32, 0x21, 0x90, 0x09, 0x9b, 0x72, 0x21, 0x17, 0x00, 0x00, 0x04}, /* Clarinet */ {0xe1, 0xe1, 0x1f, 0x09, 0x85, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00}, /* Piccolo */ {0xe1, 0xe1, 0x46, 0x09, 0x88, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00}, /* Flute */ {0xa1, 0x21, 0x9c, 0x09, 0x75, 0x75, 0x1f, 0x0a, 0x00, 0x00, 0x02}, /* Recorder */ {0x31, 0x21, 0x8b, 0x09, 0x84, 0x65, 0x58, 0x1a, 0x00, 0x00, 0x00}, /* Pan Flute */ {0xe1, 0xa1, 0x4c, 0x09, 0x66, 0x65, 0x56, 0x26, 0x00, 0x00, 0x00}, /* Blown Bottle */ {0x62, 0xa1, 0xcb, 0x09, 0x76, 0x55, 0x46, 0x36, 0x00, 0x00, 0x00}, /* Skakuhachi */ {0x62, 0xa1, 0xa2, 0x09, 0x57, 0x56, 0x07, 0x07, 0x00, 0x00, 0x0b}, /* Whistle */ {0x62, 0xa1, 0x9c, 0x09, 0x77, 0x76, 0x07, 0x07, 0x00, 0x00, 0x0b}, /* Ocarina */ {0x22, 0x21, 0x59, 0x09, 0xff, 0xff, 0x03, 0x0f, 0x02, 0x00, 0x00}, /* Lead 1 (square) */ {0x21, 0x21, 0x0e, 0x09, 0xff, 0xff, 0x0f, 0x0f, 0x01, 0x01, 0x00}, /* Lead 2 (sawtooth) */ {0x22, 0x21, 0x46, 0x89, 0x86, 0x64, 0x55, 0x18, 0x00, 0x00, 0x00}, /* Lead 3 (calliope) */ {0x21, 0xa1, 0x45, 0x09, 0x66, 0x96, 0x12, 0x0a, 0x00, 0x00, 0x00}, /* Lead 4 (chiff) */ {0x21, 0x22, 0x8b, 0x09, 0x92, 0x91, 0x2a, 0x2a, 0x01, 0x00, 0x00}, /* Lead 5 (charang) */ {0xa2, 0x61, 0x9e, 0x49, 0xdf, 0x6f, 0x05, 0x07, 0x00, 0x00, 0x02}, /* Lead 6 (voice) */ {0x20, 0x60, 0x1a, 0x09, 0xef, 0x8f, 0x01, 0x06, 0x00, 0x02, 0x00}, /* Lead 7 (fifths) */ {0x21, 0x21, 0x8f, 0x86, 0xf1, 0xf4, 0x29, 0x09, 0x00, 0x00, 0x0a}, /* Lead 8 (bass+lead) */ {0x77, 0xa1, 0xa5, 0x09, 0x53, 0xa0, 0x94, 0x05, 0x00, 0x00, 0x02}, /* Pad 1 (new age) */ {0x61, 0xb1, 0x1f, 0x89, 0xa8, 0x25, 0x11, 0x03, 0x00, 0x00, 0x0a}, /* Pad 2 (warm) */ {0x61, 0x61, 0x17, 0x09, 0x91, 0x55, 0x34, 0x16, 0x00, 0x00, 0x0c}, /* Pad 3 (polysynth) */ {0x71, 0x72, 0x5d, 0x09, 0x54, 0x6a, 0x01, 0x03, 0x00, 0x00, 0x00}, /* Pad 4 (choir) */ {0x21, 0xa2, 0x97, 0x09, 0x21, 0x42, 0x43, 0x35, 0x00, 0x00, 0x08}, /* Pad 5 (bowed) */ {0xa1, 0x21, 0x1c, 0x09, 0xa1, 0x31, 0x77, 0x47, 0x01, 0x01, 0x00}, /* Pad 6 (metallic) */ {0x21, 0x61, 0x89, 0x0c, 0x11, 0x42, 0x33, 0x25, 0x00, 0x00, 0x0a}, /* Pad 7 (halo) */ {0xa1, 0x21, 0x15, 0x09, 0x11, 0xcf, 0x47, 0x07, 0x01, 0x00, 0x00}, /* Pad 8 (sweep) */ {0x3a, 0x51, 0xce, 0x09, 0xf8, 0x86, 0xf6, 0x02, 0x00, 0x00, 0x02}, /* FX 1 (rain) */ {0x21, 0x21, 0x15, 0x09, 0x21, 0x41, 0x23, 0x13, 0x01, 0x00, 0x00}, /* FX 2 (soundtrack) */ {0x06, 0x01, 0x5b, 0x09, 0x74, 0xa5, 0x95, 0x72, 0x00, 0x00, 0x00}, /* FX 3 (crystal) */ {0x22, 0x61, 0x92, 0x8c, 0xb1, 0xf2, 0x81, 0x26, 0x00, 0x00, 0x0c}, /* FX 4 (atmosphere) */ {0x41, 0x42, 0x4d, 0x09, 0xf1, 0xf2, 0x51, 0xf5, 0x01, 0x00, 0x00}, /* FX 5 (brightness) */ {0x61, 0xa3, 0x94, 0x89, 0x11, 0x11, 0x51, 0x13, 0x01, 0x00, 0x06}, /* FX 6 (goblins) */ {0x61, 0xa1, 0x8c, 0x89, 0x11, 0x1d, 0x31, 0x03, 0x00, 0x00, 0x06}, /* FX 7 (echoes) */ {0xa4, 0x61, 0x4c, 0x09, 0xf3, 0x81, 0x73, 0x23, 0x01, 0x00, 0x04}, /* FX 8 (sci-fi) */ {0x02, 0x07, 0x85, 0x0c, 0xd2, 0xf2, 0x53, 0xf6, 0x00, 0x01, 0x00}, /* Sitar */ {0x11, 0x13, 0x0c, 0x89, 0xa3, 0xa2, 0x11, 0xe5, 0x01, 0x00, 0x00}, /* Banjo */ {0x11, 0x11, 0x06, 0x09, 0xf6, 0xf2, 0x41, 0xe6, 0x01, 0x02, 0x04}, /* Shamisen */ {0x93, 0x91, 0x91, 0x09, 0xd4, 0xeb, 0x32, 0x11, 0x00, 0x01, 0x08}, /* Koto */ {0x04, 0x01, 0x4f, 0x09, 0xfa, 0xc2, 0x56, 0x05, 0x00, 0x00, 0x0c}, /* Kalimba */ {0x21, 0x22, 0x49, 0x09, 0x7c, 0x6f, 0x20, 0x0c, 0x00, 0x01, 0x06}, /* Bagpipe */ {0x31, 0x21, 0x85, 0x09, 0xdd, 0x56, 0x33, 0x16, 0x01, 0x00, 0x0a}, /* Fiddle */ {0x20, 0x21, 0x04, 0x8a, 0xda, 0x8f, 0x05, 0x0b, 0x02, 0x00, 0x06}, /* Shanai */ {0x05, 0x03, 0x6a, 0x89, 0xf1, 0xc3, 0xe5, 0xe5, 0x00, 0x00, 0x06}, /* Tinkle Bell */ {0x07, 0x02, 0x15, 0x09, 0xec, 0xf8, 0x26, 0x16, 0x00, 0x00, 0x0a}, /* Agogo */ {0x05, 0x01, 0x9d, 0x09, 0x67, 0xdf, 0x35, 0x05, 0x00, 0x00, 0x08}, /* Steel Drums */ {0x18, 0x12, 0x96, 0x09, 0xfa, 0xf8, 0x28, 0xe5, 0x00, 0x00, 0x0a}, /* Woodblock */ {0x10, 0x00, 0x86, 0x0c, 0xa8, 0xfa, 0x07, 0x03, 0x00, 0x00, 0x06}, /* Taiko Drum */ {0x11, 0x10, 0x41, 0x0c, 0xf8, 0xf3, 0x47, 0x03, 0x02, 0x00, 0x04}, /* Melodic Tom */ {0x01, 0x10, 0x8e, 0x09, 0xf1, 0xf3, 0x06, 0x02, 0x02, 0x00, 0x0e}, /* Synth Drum */ {0x0e, 0xc0, 0x00, 0x09, 0x1f, 0x1f, 0x00, 0xff, 0x00, 0x03, 0x0e}, /* Reverse Cymbal */ {0x06, 0x03, 0x80, 0x91, 0xf8, 0x56, 0x24, 0x84, 0x00, 0x02, 0x0e}, /* Guitar Fret Noise */ {0x0e, 0xd0, 0x00, 0x0e, 0xf8, 0x34, 0x00, 0x04, 0x00, 0x03, 0x0e}, /* Breath Noise */ {0x0e, 0xc0, 0x00, 0x09, 0xf6, 0x1f, 0x00, 0x02, 0x00, 0x03, 0x0e}, /* Seashore */ {0xd5, 0xda, 0x95, 0x49, 0x37, 0x56, 0xa3, 0x37, 0x00, 0x00, 0x00}, /* Bird Tweet */ {0x35, 0x14, 0x5c, 0x11, 0xb2, 0xf4, 0x61, 0x15, 0x02, 0x00, 0x0a}, /* Telephone ring */ {0x0e, 0xd0, 0x00, 0x09, 0xf6, 0x4f, 0x00, 0xf5, 0x00, 0x03, 0x0e}, /* Helicopter */ {0x26, 0xe4, 0x00, 0x09, 0xff, 0x12, 0x01, 0x16, 0x00, 0x01, 0x0e}, /* Applause */ {0x00, 0x00, 0x00, 0x09, 0xf3, 0xf6, 0xf0, 0xc9, 0x00, 0x02, 0x0e} /* Gunshot */ }; /* logarithmic relationship between midi and FM volumes */ static int my_midi_fm_vol_table[128] = { 0, 11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100, 101, 101, 102, 103, 103, 104, 104, 105, 106, 106, 107, 107, 108, 109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127 }; /* lucas move volume table */ static int lucas_fm_vol_table[128]; static unsigned char adlib_opadd[] = { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12 }; // // Constructor // OplDriver::OplDriver() { int i, j; for (i = 0; i < 128; i++) { for (j = 0; j < 11; j++) myinsbank[i][j] = midi_fm_instruments_table[i][j]; myinsbank[i][INDEX_PERC] = 0x80; // Setup square root table here lucas_fm_vol_table[i] = (int)((double)std::sqrt((double)my_midi_fm_vol_table[i]) * 11); /* TO CHANGE !!! */ // Clear the xmidibanks xmidibanks[i] = 0; } for (i = 0; i < 16; i++) { ch[i].inum = 0; ch[i].xmidi = false; ch[i].xmidi_bank = 0; ch[i].vol = 127; ch[i].expression = 127; ch[i].nshift = -13;//-13; ch[i].on = 1; ch[i].pitchbend = 0x2000; } /* General init */ for (i = 0; i < 9; i++) { chp[i][CHP_CHAN] = -1; chp[i][CHP_COUNTER] = 0; chp[i][CHP_VEL] = 0; } } // // Destructor // OplDriver::~OplDriver() { close(); } // // Open the device // int OplDriver::open(int sample_rate) { _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, sample_rate); return 0; } // // Close the device // void OplDriver::close() { // Destroy the Opl device if (_opl) OPLDestroy(_opl); // Reset the relevant members _opl = 0; // Clear the xmidibanks for (int i = 0; i < 128; i++) { delete xmidibanks[i]; xmidibanks[i] = 0; } } // // Generate the samples // void OplDriver::generate_samples(sint16 *data, uint32 len) { if (!_opl) { memset(data, 0, len * sizeof(*data)); } else { YM3812UpdateOne(_opl, data, len); } } int OplDriver::midi_calc_volume(int channel, int vel) { vel += (VEL_FUDGE-1)*128; int nv = (ch[channel].vol * ch[channel].expression * vel) / (16129*VEL_FUDGE); // int nv = (ch[channel].vol * ch[channel].expression * vel) >> 14; #ifdef LUCAS_MODE //nv *= 2; #endif if (nv > 127) nv = 127; #ifndef LUCAS_MODE nv = my_midi_fm_vol_table[nv]; #else nv = lucas_fm_vol_table[nv]; /* TO CHANGE !!! */ #endif return nv; } // // Send a single packed midi command to the Opl (to be played now) // void OplDriver::send(uint32 b) { unsigned char channel = (char)(b & 0x0F); // Discard everything on channel 9 for now if (channel == 9 && !xmidibanks[127]) return; switch (b & 0xF0) { case 0x80: /*note off */ // Quick hack, but we should never use it. since note offs will never be sent b &= 0xFFFF; case 0x90:{ /*note on */ unsigned char note = (unsigned char)((b >> 8) & 0x7F); unsigned char vel = (unsigned char)((b >> 16) & 0x7F); int i, j; int onl, on, nv; on = -1; // First send a note off, if it's found for (i = 0; i < 9; i++) if ((chp[i][CHP_CHAN] == channel) && (chp[i][CHP_NOTE] == note)) { midi_fm_endnote(i); chp[i][CHP_CHAN] = -1; } if (vel != 0 && ch[channel].on != 0) { // Increment each counter for (i = 0; i < 9; i++) chp[i][CHP_COUNTER]++; // Try to find the last channel that was used, that is currently unused j = 0; onl = 0; for (i = 0; i < 9; i++) if ((chp[i][CHP_CHAN] == -1) && (chp[i][CHP_COUNTER] > onl)) { onl = chp[i][CHP_COUNTER]; on = i; j = 1; } // If we didn't find a free chan, use the oldest chan if (on == -1) { onl = 0; for (i = 0; i < 9; i++) if (chp[i][CHP_COUNTER] > onl) { onl = chp[i][CHP_COUNTER]; on = i; } } // If we didn't find a free note, send a note off to the Adlib for the chan we are using if (j == 0) midi_fm_endnote(on); // Send the instrument adlib if ((ch[channel].inum >= 0) && (ch[channel].inum < 128)) { if (channel == 9 && xmidibanks[127]) midi_fm_instrument(on, xmidibanks[127]->insbank[note]); else midi_fm_instrument(on, ch[channel].ins); } // Calculate the adlib volume nv = midi_calc_volume(channel, vel); // Send note on midi_fm_playnote(on, note + ch[channel].nshift, nv * 2, ch[channel].pitchbend); // Update the shadows chp[on][CHP_CHAN] = channel; chp[on][CHP_NOTE] = note; chp[on][CHP_COUNTER] = 0; chp[on][CHP_VEL] = vel; } } break; case 0xa0:{ /*key after touch */ unsigned char note = (unsigned char)((b >> 8) & 0x7F); unsigned char vel = (unsigned char)((b >> 16) & 0x7F); int nv = midi_calc_volume(channel, vel); for (int i = 0; i < 9; i++) if ((chp[CHP_CHAN][0] == channel) & (chp[i][CHP_NOTE] == note)) { chp[i][CHP_VEL] = vel; midi_fm_volume(i, nv * 2); } } break; case 0xb0:{ /* control change */ int i; unsigned char ctrl = (unsigned char)((b >> 8) & 0x7F); unsigned char vel = (unsigned char)((b >> 16) & 0x7F); /* FIXME: Except for Volume, the Modulation and Sustain code is just a random guess. */ switch (ctrl) { case 0x00: /* Bank Change */ if (vel == 127) { /* XMIDI Mode */ ch[channel].xmidi = true; COUT ("Setting XMIDI Mode on channel " << ((int) channel) << " Bank " << (int) ch[channel].xmidi_bank); } else { /* General Midi */ ch[channel].xmidi = false; COUT ("Setting General Midi Mode on channel " << ((int) channel)); } break; case 0x01: /* Modulation */ for (i = 0; i < 9; i++) if (chp[i][CHP_CHAN] == channel) midi_write_adlib(0x20 + adlib_opadd[i], vel); break; case 0x07: /* Volume */ ch[channel].vol = vel; midi_update_volume(channel); break; case 0x0A: /* Pan */ /* This is not a warning as we do not support OPL3 => no stereo anyway debug(1, "MIDI sub-command 0xB0 (Control Change) case %02X (Pan) not handled in MIDIEMU driver.", ctrl); */ break; case 0x0B: /* Expression */ ch[channel].expression = vel; midi_update_volume(channel); break; case 0x40: /* Sustain on/off */ //for (i = 0; i < 9; i++) // if (chp[i][CHP_CHAN] == channel) // midi_write_adlib(0x80 + adlib_opadd[i], vel); break; case 0x5B: /* Extended depth effect */ //debug(1, // "MIDI sub-command 0xB0 (Control Change) case %02X (Extended Depth) not handled in MIDIEMU driver.", // ctrl); break; case 0x5D: /* Chorus depth */ //debug(1, // "MIDI sub-command 0xB0 (Control Change) case %02X (Chorus Depth) not handled in MIDIEMU driver.", // ctrl); break; // // XMIDI // case XMIDI_CONTROLLER_CHAN_LOCK: CERR("Uh oh. Detected a XMIDI Channel Lock (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_CHAN_LOCK_PROT: CERR("Uh oh. Detected a XMIDI Channel Lock Protect (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_VOICE_PROT: CERR("Uh oh. Detected a XMIDI Voice Protect (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_TIMBRE_PROT: CERR("Uh oh. Detected a XMIDI Timbre Protect (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_BANK_CHANGE: COUT("Detected a XMIDI Bank Change (" << (int) vel << ") on channel " << (int) channel); // Set the bank ch[channel].xmidi_bank = vel; break; case XMIDI_CONTROLLER_IND_CTRL_PREFIX: CERR("Uh oh. Detected a XMIDI Indirect Controller Prefix (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_CLEAR_BB_COUNT: CERR("Uh oh. Detected a XMIDI Clear Beat/Bar Count (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_CALLBACK_TRIG: CERR("Uh oh. Detected a XMIDI Callback Trigger (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; case XMIDI_CONTROLLER_SEQ_BRANCH_INDEX: CERR("Uh oh. Detected a XMIDI Sequence Branch Index (" << (int) vel << ") on channel " << (int) channel << ", but we don't support them"); break; // // END XMIDI // case 0x7B: /* All notes off */ for (i = 0; i < 9; i++) { if (chp[i][CHP_CHAN] == channel) { midi_fm_endnote(i); chp[i][CHP_CHAN] = -1; } } break; default: CERR("MIDI sub-command 0xB0 (Control Change) case 0x" << std::hex << (int) ctrl << std::dec << " not handled in MIDIEMU driver."); break; } } break; case 0xc0:{ /* patch change */ unsigned char instrument = (unsigned char)((b >> 8) & 0x7F); ch[channel].inum = instrument; //std::cout << "Setting instrument: " << ((unsigned int) instrument) << " for chan " << ((unsigned int) channel) << std::endl; unsigned char *ins = 0; int b = -1; // Search for xmidi ins. if (ch[channel].xmidi) for (b = ch[channel].xmidi_bank; b>=0; b--) { xmidibank *bank = xmidibanks[b]; if (!bank) continue; if (bank->insbank[instrument][INDEX_PERC] &= 0x80) { ins = bank->insbank[instrument]; break; } } if (!ins) ins = myinsbank[instrument]; for (int j = 0; j < 12; j++) ch[channel].ins[j] = ins[j]; COUT("Detected a Patch Change (" << (int) instrument << ") on channel " << (int) channel << " xmidibank: " << b); } break; case 0xd0: /* channel touch */ //debug(1, "MIDI command 0xD0 (Channel Touch) not handled in MIDIEMU driver."); break; case 0xe0:{ //break; /* pitch wheel */ int pitchbend = ((b >> 8) & 0x7F) | (((b >> 16) & 0x7F) << 7); ch[channel].pitchbend = pitchbend; for (int i = 0; i < 9; i++) { if (chp[i][CHP_CHAN] == channel) { int nv = midi_calc_volume(channel, chp[i][CHP_VEL]); midi_fm_playnote(i, chp[i][CHP_NOTE] + ch[channel].nshift, nv * 2, pitchbend); } } } break; default: //fprintf(stderr, "Unknown : %08x\n", (int)b); break; } } void OplDriver::midi_write_adlib(unsigned int reg, unsigned char val) { OPLWrite(_opl, 0, reg); OPLWrite(_opl, 1, val); adlib_data[reg] = val; } /* typedef struct { unsigned char mod_avekm; // 0 (20) unsigned char mod_ksl_tl; // 1 (40) unsigned char mod_ad; // 2 (60) unsigned char mod_sr; // 3 (80) unsigned char mod_ws; // 4 (E0) unsigned char fb_c; // 5 unsigned char car_avekm; // 6 amp, sussnd (20) unsigned char car_ksl_tl; // 7 outlev, keyscale (43) unsigned char car_ad; // 8 Attack Delay AR (63) unsigned char car_sr; // 9 SustainLev Release DR (83) unsigned char car_ws; // 10 Waveform (E0) } AD_instrument; case 0x20: am,vib,ksr,eg type,mul */ void OplDriver::midi_fm_instrument(int voice, unsigned char *inst) { #if 0 /* Just gotta make sure this happens because who knows when it'll be reset otherwise.... */ #endif #if 0 && defined(LUCAS_MODE) midi_write_adlib(OPL_REG_KSLTL_C + adlib_opadd[voice], 0x3f); if ((inst[INDEX_FB_C] & 1) == 0) midi_write_adlib(OPL_REG_KSLTL_M + adlib_opadd[voice], inst[INDEX_KSLTL_M]); else midi_write_adlib(OPL_REG_KSLTL_M + adlib_opadd[voice], 0x3f); #elif 0 midi_write_adlib(OPL_REG_KSLTL_M + adlib_opadd[voice], inst[INDEX_KSLTL_M]); if ((inst[INDEX_FB_C] & 1) == 0) midi_write_adlib(OPL_REG_KSLTL_C + adlib_opadd[voice], inst[INDEX_KSLTL_C]); else midi_write_adlib(OPL_REG_KSLTL_C + adlib_opadd[voice], 0); #else #endif midi_write_adlib(OPL_REG_AVEKM_M + adlib_opadd[voice], inst[INDEX_AVEKM_M]); midi_write_adlib(OPL_REG_KSLTL_M + adlib_opadd[voice], inst[INDEX_KSLTL_M]); midi_write_adlib(OPL_REG_AD_M + adlib_opadd[voice], inst[INDEX_AD_M]); midi_write_adlib(OPL_REG_SR_M + adlib_opadd[voice], inst[INDEX_SR_M]); midi_write_adlib(OPL_REG_WAVE_M + adlib_opadd[voice], inst[INDEX_WAVE_M]); if (!(inst[INDEX_PERC] & 0x7f)) { midi_write_adlib(OPL_REG_AVEKM_C + adlib_opadd[voice], inst[INDEX_AVEKM_C]); midi_write_adlib(OPL_REG_KSLTL_C + adlib_opadd[voice], inst[INDEX_KSLTL_C]); midi_write_adlib(OPL_REG_AD_C + adlib_opadd[voice], inst[INDEX_AD_C]); midi_write_adlib(OPL_REG_SR_C + adlib_opadd[voice], inst[INDEX_SR_C]); midi_write_adlib(OPL_REG_WAVE_C + adlib_opadd[voice], inst[INDEX_WAVE_C]); midi_write_adlib(OPL_REG_FB_C + voice, inst[INDEX_FB_C]); midi_write_adlib(0xbd, 0); if (!inst[INDEX_PERC]) { CERR("Tried setting an instruement that wasnt loaded"); } } } void OplDriver::midi_update_volume(int channel) { for (int i = 0; i < 9; i++) if ((chp[i][CHP_CHAN] == channel)) { int nv = midi_calc_volume(channel, chp[i][CHP_VEL]); midi_fm_volume(i, nv * 2); } } void OplDriver::midi_fm_volume(int voice, int volume) { volume >>= 2; if ((adlib_data[0xc0 + voice] & 1) == 1) midi_write_adlib(0x40 + adlib_opadd[voice], (unsigned char)((63 - volume) | (adlib_data[0x40 + adlib_opadd[voice]] & 0xc0))); midi_write_adlib(0x43 + adlib_opadd[voice], (unsigned char)((63 - volume) | (adlib_data[0x43 + adlib_opadd[voice]] & 0xc0))); } static int fnums[] = { 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2ae }; /* These tables 'borrowed' from Timidity tables.c Copyright (C) 1999-2001 Masanao Izumo Copyright (C) 1995 Tuukka Toivonen */ static float ex_bend_fine[256] = { 1.0, 1.0002256593050698, 1.0004513695322617, 1.0006771306930664, 1.0009029427989777, 1.0011288058614922, 1.0013547198921082, 1.0015806849023274, 1.0018067009036538, 1.002032767907594, 1.0022588859256572, 1.0024850549693551, 1.0027112750502025, 1.0029375461797159, 1.0031638683694153, 1.0033902416308227, 1.0036166659754628, 1.0038431414148634, 1.0040696679605541, 1.0042962456240678, 1.0045228744169397, 1.0047495543507072, 1.0049762854369111, 1.0052030676870944, 1.0054299011128027, 1.0056567857255843, 1.00588372153699, 1.006110708558573, 1.0063377468018897, 1.0065648362784985, 1.0067919769999607, 1.0070191689778405, 1.0072464122237039, 1.0074737067491204, 1.0077010525656616, 1.0079284496849015, 1.0081558981184175, 1.008383397877789, 1.008610948974598, 1.0088385514204294, 1.0090662052268706, 1.0092939104055114, 1.0095216669679448, 1.0097494749257656, 1.009977334290572, 1.0102052450739643, 1.0104332072875455, 1.0106612209429215, 1.0108892860517005, 1.0111174026254934, 1.0113455706759138, 1.0115737902145781, 1.0118020612531047, 1.0120303838031153, 1.0122587578762337, 1.012487183484087, 1.0127156606383041, 1.0129441893505169, 1.0131727696323602, 1.0134014014954713, 1.0136300849514894, 1.0138588200120575, 1.0140876066888203, 1.0143164449934257, 1.0145453349375237, 1.0147742765327674, 1.0150032697908125, 1.0152323147233171, 1.015461411341942, 1.0156905596583505, 1.0159197596842091, 1.0161490114311862, 1.0163783149109531, 1.0166076701351838, 1.0168370771155553, 1.0170665358637463, 1.0172960463914391, 1.0175256087103179, 1.0177552228320703, 1.0179848887683858, 1.0182146065309567, 1.0184443761314785, 1.0186741975816487, 1.0189040708931674, 1.0191339960777379, 1.0193639731470658, 1.0195940021128593, 1.0198240829868295, 1.0200542157806898, 1.0202844005061564, 1.0205146371749483, 1.0207449257987866, 1.0209752663893958, 1.0212056589585028, 1.0214361035178368, 1.0216666000791297, 1.0218971486541166, 1.0221277492545349, 1.0223584018921241, 1.0225891065786274, 1.0228198633257899, 1.0230506721453596, 1.023281533049087, 1.0235124460487257, 1.0237434111560313, 1.0239744283827625, 1.0242054977406807, 1.0244366192415495, 1.0246677928971357, 1.0248990187192082, 1.025130296719539, 1.0253616269099028, 1.0255930093020766, 1.0258244439078401, 1.0260559307389761, 1.0262874698072693, 1.0265190611245079, 1.0267507047024822, 1.0269824005529853, 1.027214148687813, 1.0274459491187637, 1.0276778018576387, 1.0279097069162415, 1.0281416643063788, 1.0283736740398595, 1.0286057361284953, 1.0288378505841009, 1.0290700174184932, 1.0293022366434921, 1.0295345082709197, 1.0297668323126017, 1.0299992087803651, 1.030231637686041, 1.0304641190414621, 1.0306966528584645, 1.0309292391488862, 1.0311618779245688, 1.0313945691973556, 1.0316273129790936, 1.0318601092816313, 1.0320929581168212, 1.0323258594965172, 1.0325588134325767, 1.0327918199368598, 1.0330248790212284, 1.0332579906975481, 1.0334911549776868, 1.033724371873515, 1.0339576413969056, 1.0341909635597348, 1.0344243383738811, 1.0346577658512259, 1.034891246003653, 1.0351247788430489, 1.0353583643813031, 1.0355920026303078, 1.0358256936019572, 1.0360594373081489, 1.0362932337607829, 1.0365270829717617, 1.0367609849529913, 1.0369949397163791, 1.0372289472738365, 1.0374630076372766, 1.0376971208186156, 1.0379312868297725, 1.0381655056826686, 1.0383997773892284, 1.0386341019613787, 1.0388684794110492, 1.0391029097501721, 1.0393373929906822, 1.0395719291445176, 1.0398065182236185, 1.0400411602399278, 1.0402758552053915, 1.0405106031319582, 1.0407454040315787, 1.0409802579162071, 1.0412151647977996, 1.0414501246883161, 1.0416851375997183, 1.0419202035439705, 1.0421553225330404, 1.042390494578898, 1.042625719693516, 1.0428609978888699, 1.043096329176938, 1.0433317135697009, 1.0435671510791424, 1.0438026417172486, 1.0440381854960086, 1.0442737824274138, 1.044509432523459, 1.044745135796141, 1.0449808922574599, 1.0452167019194181, 1.0454525647940205, 1.0456884808932754, 1.0459244502291931, 1.0461604728137874, 1.0463965486590741, 1.046632677777072, 1.0468688601798024, 1.0471050958792898, 1.047341384887561, 1.0475777272166455, 1.047814122878576, 1.048050571885387, 1.0482870742491166, 1.0485236299818055, 1.0487602390954964, 1.0489969016022356, 1.0492336175140715, 1.0494703868430555, 1.0497072096012419, 1.0499440858006872, 1.0501810154534512, 1.050417998571596, 1.0506550351671864, 1.0508921252522903, 1.0511292688389782, 1.0513664659393229, 1.0516037165654004, 1.0518410207292894, 1.0520783784430709, 1.0523157897188296, 1.0525532545686513, 1.0527907730046264, 1.0530283450388465, 1.0532659706834067, 1.0535036499504049, 1.0537413828519411, 1.0539791694001188, 1.0542170096070436, 1.0544549034848243, 1.0546928510455722, 1.0549308523014012, 1.0551689072644284, 1.0554070159467728, 1.0556451783605572, 1.0558833945179062, 1.0561216644309479, 1.0563599881118126, 1.0565983655726334, 1.0568367968255465, 1.0570752818826903, 1.0573138207562065, 1.057552413458239, 1.0577910600009348, 1.0580297603964437, 1.058268514656918, 1.0585073227945128, 1.0587461848213857, 1.058985100749698, 1.0592240705916123 }; static float ex_bend_coarse[128] = { 1.0, 1.0594630943592953, 1.122462048309373, 1.189207115002721, 1.2599210498948732, 1.3348398541700344, 1.4142135623730951, 1.4983070768766815, 1.5874010519681994, 1.681792830507429, 1.7817974362806785, 1.8877486253633868, 2.0, 2.1189261887185906, 2.244924096618746, 2.3784142300054421, 2.5198420997897464, 2.6696797083400687, 2.8284271247461903, 2.996614153753363, 3.1748021039363992, 3.363585661014858, 3.5635948725613571, 3.7754972507267741, 4.0, 4.2378523774371812, 4.4898481932374912, 4.7568284600108841, 5.0396841995794928, 5.3393594166801366, 5.6568542494923806, 5.993228307506727, 6.3496042078727974, 6.727171322029716, 7.1271897451227151, 7.5509945014535473, 8.0, 8.4757047548743625, 8.9796963864749824, 9.5136569200217682, 10.079368399158986, 10.678718833360273, 11.313708498984761, 11.986456615013454, 12.699208415745595, 13.454342644059432, 14.25437949024543, 15.101989002907095, 16.0, 16.951409509748721, 17.959392772949972, 19.027313840043536, 20.158736798317967, 21.357437666720553, 22.627416997969522, 23.972913230026901, 25.398416831491197, 26.908685288118864, 28.508758980490853, 30.203978005814196, 32.0, 33.902819019497443, 35.918785545899944, 38.054627680087073, 40.317473596635935, 42.714875333441107, 45.254833995939045, 47.945826460053802, 50.796833662982394, 53.817370576237728, 57.017517960981706, 60.407956011628393, 64.0, 67.805638038994886, 71.837571091799887, 76.109255360174146, 80.63494719327187, 85.429750666882214, 90.509667991878089, 95.891652920107603, 101.59366732596479, 107.63474115247546, 114.03503592196341, 120.81591202325679, 128.0, 135.61127607798977, 143.67514218359977, 152.21851072034829, 161.26989438654374, 170.85950133376443, 181.01933598375618, 191.78330584021521, 203.18733465192958, 215.26948230495091, 228.07007184392683, 241.63182404651357, 256.0, 271.22255215597971, 287.35028436719938, 304.43702144069658, 322.53978877308765, 341.71900266752868, 362.03867196751236, 383.56661168043064, 406.37466930385892, 430.53896460990183, 456.14014368785394, 483.26364809302686, 512.0, 542.44510431195943, 574.70056873439876, 608.87404288139317, 645.0795775461753, 683.43800533505737, 724.07734393502471, 767.13322336086128, 812.74933860771785, 861.07792921980365, 912.28028737570787, 966.52729618605372, 1024.0, 1084.8902086239189, 1149.4011374687975, 1217.7480857627863, 1290.1591550923506, 1366.8760106701147, 1448.1546878700494, 1534.2664467217226 }; void OplDriver::midi_fm_playnote(int voice, int note, int volume, int pitchbend) { int freq = fnums[note % 12]; int oct = note / 12; int c; float pf; pitchbend -= 0x2000; if (pitchbend != 0) { pitchbend *= 2; if (pitchbend >= 0) pf = (float)(ex_bend_fine[(pitchbend >> 5) & 0xFF] * ex_bend_coarse[(pitchbend >> 13) & 0x7F]); else { pitchbend = -pitchbend; pf = (float)(1.0 / (ex_bend_fine[(pitchbend >> 5) & 0xFF] * ex_bend_coarse[(pitchbend >> 13) & 0x7F])); } freq = (int)((float)freq * pf); while (freq >= (fnums[0] * 2)) { freq /= 2; oct += 1; } while (freq < fnums[0]) { freq *= 2; oct -= 1; } } midi_fm_volume(voice, volume); midi_write_adlib(0xa0 + voice, (unsigned char)(freq & 0xff)); c = ((freq & 0x300) >> 8) + (oct << 2) + (1 << 5); midi_write_adlib(0xb0 + voice, (unsigned char)c); } void OplDriver::midi_fm_endnote(int voice) { midi_write_adlib(0xb0 + voice, (unsigned char)(adlib_data[0xb0 + voice] & (255 - 32))); } void OplDriver::LoadMT32Bank(bool force_xmidi) { #ifdef PENTAGRAM LoadXMIDIBank("/music.flx"); #else if (GAME_BG && !force_xmidi) { const char* u7vfn = "/u7voice.flx"; if (!U7exists(u7vfn)) { u7vfn = "/u7voice.flx"; } LoadU7VBank(u7vfn); } else { LoadXMIDIBank("/xmidi.ad"); } #endif } // Loads the mt32 bank from /XMIDI.AD void OplDriver::LoadXMIDIBank(const char *fn) { #ifdef PENTAGRAM Flex *flex; try { flex = new Flex(fn, false); } catch(file_open_exception &) { std::cerr << "Couldn't open " << fn << std::endl; return; } BufferDataSource ds(flex->get_object_nodel(259), flex->get_size(259)); #else FILE *xmidi_ad = U7open (fn, "rb"); if (!xmidi_ad) { std::cerr << "Warning: couldn't open " << get_system_path(fn) << std::endl; return; } FileDataSource ds(xmidi_ad); #endif COUT ("Reading " << fn); bool read[128]; std::memset(read, false, sizeof(read)); // Read all the timbres if (0) for (uint32 i = 0; ds.getPos() < ds.getSize(); i++) { uint32 patch = (uint8) ds.read1(); uint32 bank = (uint8) ds.read1(); // If we read both == 255 then we've read all of them if (patch == 255 || bank == 255) { COUT ("Finished " << patch << ": "); break; } // Get offset and seek to it uint32 offset = ds.read4(); COUT ("Patch " << i << " = " << bank << ":" << patch << " @ " << offset << " " << ds.getPos()); } // Read all the timbres uint32 i; for (i = 0; ds.getPos() < ds.getSize(); i++) { // Seek to the entry ds.seek(i*6); uint32 patch = (uint8) ds.read1(); uint32 bank = (uint8) ds.read1(); // If we read both == 255 then we've read all of them if (patch == 255 || bank == 255) { COUT ("Finished " << patch << ": "); break; } // Get offset and seek to it uint32 offset = ds.read4(); COUT ("Patch " << i << " = " << bank << ":" << patch << " @ " << offset); // Check to see if the bank exists if (!xmidibanks[bank]) { xmidibanks[bank] = new xmidibank; std::memset (xmidibanks[bank], 0, sizeof (xmidibank)); } // Seek to offset ds.seek(offset); // Get len of the entry uint16 len = ds.read2(); // Only accept lens that are 0xC if (len != 0xE) { COUT ("Invalid Patch " << bank << ":" << patch << " len was " << len << " " << std::hex << len << std::dec); //continue; } // Skip 1 byte ds.skip(1); struct { unsigned char mod_avekm; // 0 (20) unsigned char mod_ksl_tl; // 1 (40) unsigned char mod_ad; // 2 (60) unsigned char mod_sr; // 3 (80) unsigned char mod_ws; // 4 (E0) unsigned char fb_c; // 5 unsigned char car_avekm; // 6 amp, sussnd (20) unsigned char car_ksl_tl; // 7 outlev, keyscale (43) unsigned char car_ad; // 8 Attack Delay AR (63) unsigned char car_sr; // 9 SustainLev Release DR (83) unsigned char car_ws; // 10 Waveform (E0) } xmidi_ins; ds.read((char*) (&xmidi_ins), 11); unsigned char* ins = xmidibanks[bank]->insbank[patch]; ins[INDEX_AVEKM_M] = xmidi_ins.mod_avekm; ins[INDEX_KSLTL_M] = xmidi_ins.mod_ksl_tl; ins[INDEX_AD_M] = xmidi_ins.mod_ad; ins[INDEX_SR_M] = xmidi_ins.mod_sr; ins[INDEX_WAVE_M] = xmidi_ins.mod_ws; ins[INDEX_AVEKM_C] = xmidi_ins.car_avekm; ins[INDEX_KSLTL_C] = xmidi_ins.car_ksl_tl; ins[INDEX_AD_C] = xmidi_ins.car_ad; ins[INDEX_SR_C] = xmidi_ins.car_sr; ins[INDEX_WAVE_C] = xmidi_ins.car_ws; ins[INDEX_FB_C] = xmidi_ins.fb_c; ins[INDEX_PERC] = 0x80; // Note that XMIDI uses a different method to U7:TBG } COUT (i << " timbres read"); #ifdef PENTAGRAM delete flex; #else fclose (xmidi_ad); #endif } void OplDriver::LoadU7VBank(const char *fn) { #ifndef PENTAGRAM Flex *f; try { f = new Flex(fn); } catch(file_open_exception &) { std::cerr << "Warning: couldn't open " << get_system_path(fn) << std::endl; return; } COUT ("Reading " << fn); std::size_t size; char *buf = f->retrieve(1, size); BufferDataSource ds(buf, size); delete f; struct u7voice_adlib_ins { unsigned char mod_avekm; // 0: (20) unsigned char mod_ksl_tl; // 1: (40) unsigned char mod_ad; // 2: (60) unsigned char mod_sr; // 3: (80) unsigned char mod_ws; // 4: (E0) unsigned char car_avekm; // 5: amp, sussnd (22) unsigned char car_ksl_tl; // 6: outlev, keyscale (43) unsigned char car_ad; // 7: Attack Delay AR (63) unsigned char car_sr; // 8: SustainLev Release DR (83) unsigned char car_ws; // 9: Waveform (E3) unsigned char fb_c; // 10: Feedback/Connection // NOT IMPLEMENTED from here on! unsigned char perc_voice; // 11 Percussion voice number !! // (0=melodic, 6=bass drum, etc.) unsigned char car_vel_sense; // 12: carrier velocity sensitivity unsigned char mod_vel_sense; // 13: modulator velocity sensitivity unsigned char bend_sense; // 14: pitch bend sensitivity unsigned char wheel_sense; // 15: modulation wheel sensitivity unsigned char lfo_speed; // 16: lfo speed unsigned char lfo_depth; // 17: lfo depth unsigned short pe_start_level; // 18-19: pitch envelope start level unsigned short pe_attack_rate1; // 20-21: pitch envelope attack rate 1 unsigned short pe_attack_level1; // 22-23: pitch envelope attack level 1 unsigned short pe_attack_rate2; // 24-25: pitch envelope attack rate 2 unsigned short pe_attack_level2; // 26-27: pitch envelope attack level 2 unsigned short pe_decay_rate; // 28-29: pitch envelope decay rate unsigned short pe_sustain_level; // 30-31: pitch envelope sustain level unsigned short pe_release_rate; // 32-33: pitch envelope release rate unsigned short pe_end_level; // 34-35: pitch envelope end level unsigned char deturn; // 36: detune unsigned char transpose; // 37: transpose unsigned char next_partial; // 38: next partial number (+1; 0=no more partials) unsigned char key_follow; // 39: key follow unsigned char reserved[7]; // 40-46: reserved unsigned char prog_num; // 47: program change number void read(DataSource &ds) { mod_avekm = ds.read1(); mod_ksl_tl = ds.read1(); mod_ad = ds.read1(); mod_sr = ds.read1(); mod_ws = ds.read1(); car_avekm = ds.read1(); car_ksl_tl = ds.read1(); car_ad = ds.read1(); car_sr = ds.read1(); car_ws = ds.read1(); fb_c = ds.read1(); // NOT IMPLEMENTED from here on! perc_voice = ds.read1(); car_vel_sense = ds.read1(); mod_vel_sense = ds.read1(); bend_sense = ds.read1(); wheel_sense = ds.read1(); lfo_speed = ds.read1(); lfo_depth = ds.read1(); pe_start_level = ds.read2(); pe_attack_rate1 = ds.read2(); pe_attack_level1 = ds.read2(); pe_attack_rate2 = ds.read2(); pe_attack_level2 = ds.read2(); pe_decay_rate = ds.read2(); pe_sustain_level = ds.read2(); pe_release_rate = ds.read2(); pe_end_level = ds.read2(); deturn = ds.read1(); transpose = ds.read1(); next_partial = ds.read1(); key_follow = ds.read1(); ds.read((char *) reserved, 7); prog_num = ds.read1(); } } u7voice_ins; COUT("Size of u7voice_adlib_ins " << sizeof(u7voice_adlib_ins)); int count = ds.read1() & 0xFF; // Read all the timbres int i; for (i = 0; i < count; i++) { // Read the timbre u7voice_ins.read(ds); uint32 patch = u7voice_ins.prog_num; uint32 bank = 0; COUT ("Patch " << i << " = " << bank << ":" << patch); // Check to see if the bank exists if (!xmidibanks[bank]) { xmidibanks[bank] = new xmidibank; std::memset (xmidibanks[bank], 0, sizeof (xmidibank)); } if (patch > 127) { CERR ("Don't know how to handle this"); continue; } unsigned char* ins = xmidibanks[bank]->insbank[patch]; ins[INDEX_AVEKM_M] = u7voice_ins.mod_avekm; ins[INDEX_KSLTL_M] = u7voice_ins.mod_ksl_tl; ins[INDEX_AD_M] = u7voice_ins.mod_ad; ins[INDEX_SR_M] = u7voice_ins.mod_sr; ins[INDEX_WAVE_M] = u7voice_ins.mod_ws; ins[INDEX_AVEKM_C] = u7voice_ins.car_avekm; ins[INDEX_KSLTL_C] = u7voice_ins.car_ksl_tl; ins[INDEX_AD_C] = u7voice_ins.car_ad; ins[INDEX_SR_C] = u7voice_ins.car_sr; ins[INDEX_WAVE_C] = u7voice_ins.car_ws; ins[INDEX_FB_C] = u7voice_ins.fb_c; ins[INDEX_PERC] = u7voice_ins.perc_voice | 0x80; // Note that XMIDI uses a different method to U7:TBG if (u7voice_ins.next_partial || u7voice_ins.key_follow) { COUT("next_partial " << (int) u7voice_ins.next_partial << " key_follow " << (int) u7voice_ins.key_follow); } } COUT (i << " timbres read"); delete [] buf; #endif } #endif // USE_FMOPL_MIDI exult-1.2/audio/midi_drivers/mac_midi.h0000755000175000001440000000322407724430450013677 /* * mac_midi.h - QuickTime based midi player for MacOS. * * Copyright (C) 2001 Max Horn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_macos_midi_h_ #define _MIDI_driver_macos_midi_h_ #if defined(MACOS) || defined(MACOSX) #ifdef MACOS #include #else // Work around a conflict between exult's Palette class // and the Carbon headers typedef struct ComponentInstanceRecord * TunePlayer; #endif #include "Midi.h" #include "exceptions.h" class Mac_QT_midi : virtual public MidiAbstract { public: // Do we accept events, YES! virtual bool accepts_events(void) { return true; } // Event based methods virtual void start_track(XMIDIEventList *, bool repeat); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); Mac_QT_midi(); virtual ~Mac_QT_midi(); private: UNREPLICATABLE_CLASS(Mac_QT_midi); TunePlayer mTunePlayer; uint32 *mTuneSequence; uint32 *mTuneHeader; }; #endif #endif exult-1.2/audio/midi_drivers/Timidity_binary.h0000644000175000001440000000245307550423657015305 //-*-Mode: C++;-*- /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_Timidity_binary_h_ #define _MIDI_driver_Timidity_binary_h_ #include "Midi.h" #if HAVE_TIMIDITY_BIN class Timidity_binary : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *, bool repeat); virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual void stop_sfx(void); virtual bool is_playing(void); virtual const char *copyright(void); static void music_complete_callback(void); // void player(void); // void sfxplayer(void); Timidity_binary(); virtual ~Timidity_binary(); }; #endif #endif exult-1.2/audio/midi_drivers/be_midi.cc0000644000175000001440000000345007550423657013671 /* Copyright (C) 2000 Willem Jan Palenstijn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif //BEOS-specific code #ifdef BEOS #include "be_midi.h" #include "fnames.h" #include #include Be_midi::Be_midi() { FileOpen = false; } void Be_midi::stop_track(void) { if (FileOpen) { midiSynthFile.UnloadFile(); FileOpen = false; } } Be_midi::~Be_midi(void) { stop_track(); } bool Be_midi::is_playing(void) { if (!FileOpen) return false; return !midiSynthFile.IsFinished(); } void Be_midi::start_track(XMIDIEventList *event_list,bool repeat) { const char *name = MIDITMPFILE; event_list->Write(name); #if DEBUG cerr << "Stopping any running track" << endl; #endif stop_track(); #if DEBUG cerr << "Starting midi sequence with Be_midi, repeat = " << (repeat?"true":"false") << endl; #endif //open file get_ref_for_path(name, &midiRef); midiSynthFile.LoadFile(&midiRef); FileOpen = true; //set repeating midiSynthFile.EnableLooping(repeat); //play file midiSynthFile.Start(); } const char *Be_midi::copyright(void) { return "Internal BeOS MIDI player"; } #endif exult-1.2/audio/midi_drivers/fmopl.h0000644000175000001440000001345207524010427013247 /* ScummVM - Scumm Interpreter * Copyright (C) 1999/2000 Tatsuyuki Satoh * Copyright (C) 2001/2002 The ScummVM project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Header: /cvsroot/exult/exult/audio/midi_drivers/fmopl.h,v 1.1 2002/08/06 18:10:31 colourles Exp $ * * LGPL licensed version of MAMEs fmopl (V0.37a modified) by * Tatsuyuki Satoh. Included from LGPL'ed AdPlug. */ #ifndef FMOPL_H #define FMOPL_H #ifdef USE_FMOPL_MIDI #include "common_types.h" typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); typedef void (*OPL_IRQHANDLER)(int param,int irq); typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); #define OPL_TYPE_WAVESEL 0x01 /* waveform select */ /* Saving is necessary for member of the 'R' mark for suspend/resume */ /* ---------- OPL one of slot ---------- */ typedef struct fm_opl_slot { int TL; /* total level :TL << 8 */ int TLL; /* adjusted now TL */ uint8 KSR; /* key scale rate :(shift down bit) */ int *AR; /* attack rate :&AR_TABLE[AR<<2] */ int *DR; /* decay rate :&DR_TABLE[DR<<2] */ int SL; /* sustain level :SL_TABLE[SL] */ int *RR; /* release rate :&DR_TABLE[RR<<2] */ uint8 ksl; /* keyscale level :(shift down bits) */ uint8 ksr; /* key scale rate :kcode>>KSR */ uint32 mul; /* multiple :ML_TABLE[ML] */ uint32 Cnt; /* frequency count */ uint32 Incr; /* frequency step */ /* envelope generator state */ uint8 eg_typ;/* envelope type flag */ uint8 evm; /* envelope phase */ int evc; /* envelope counter */ int eve; /* envelope counter end point */ int evs; /* envelope counter step */ int evsa; /* envelope step for AR :AR[ksr] */ int evsd; /* envelope step for DR :DR[ksr] */ int evsr; /* envelope step for RR :RR[ksr] */ /* LFO */ uint8 ams; /* ams flag */ uint8 vib; /* vibrate flag */ /* wave selector */ int **wavetable; } OPL_SLOT; /* ---------- OPL one of channel ---------- */ typedef struct fm_opl_channel { OPL_SLOT SLOT[2]; uint8 CON; /* connection type */ uint8 FB; /* feed back :(shift down bit)*/ int *connect1; /* slot1 output pointer */ int *connect2; /* slot2 output pointer */ int op1_out[2]; /* slot1 output for selfeedback */ /* phase generator state */ uint32 block_fnum; /* block+fnum */ uint8 kcode; /* key code : KeyScaleCode */ uint32 fc; /* Freq. Increment base */ uint32 ksl_base; /* KeyScaleLevel Base step */ uint8 keyon; /* key on/off flag */ } OPL_CH; /* OPL state */ typedef struct fm_opl_f { uint8 type; /* chip type */ int clock; /* master clock (Hz) */ int rate; /* sampling rate (Hz) */ double freqbase; /* frequency base */ double TimerBase; /* Timer base time (==sampling time) */ uint8 address; /* address register */ uint8 status; /* status flag */ uint8 statusmask; /* status mask */ uint32 mode; /* Reg.08 : CSM , notesel,etc. */ /* Timer */ int T[2]; /* timer counter */ uint8 st[2]; /* timer enable */ /* FM channel slots */ OPL_CH *P_CH; /* pointer of CH */ int max_ch; /* maximum channel */ /* Rythm sention */ uint8 rythm; /* Rythm mode , key flag */ /* time tables */ int AR_TABLE[75]; /* atttack rate tables */ int DR_TABLE[75]; /* decay rate tables */ uint32 FN_TABLE[1024];/* fnumber -> increment counter */ /* LFO */ int *ams_table; int *vib_table; int amsCnt; int amsIncr; int vibCnt; int vibIncr; /* wave selector enable flag */ uint8 wavesel; /* external event callback handler */ OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ int TimerParam; /* TIMER parameter */ OPL_IRQHANDLER IRQHandler; /* IRQ handler */ int IRQParam; /* IRQ parameter */ OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ int UpdateParam; /* stream update parameter */ } FM_OPL; /* ---------- Generic interface section ---------- */ #define OPL_TYPE_YM3526 (0) #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) // Modulation Registers #define OPL_REG_AVEKM_M 0x20 #define OPL_REG_KSLTL_M 0x40 #define OPL_REG_AD_M 0x60 #define OPL_REG_SR_M 0x80 #define OPL_REG_WAVE_M 0xE0 // Carrier Registers #define OPL_REG_AVEKM_C 0x23 #define OPL_REG_KSLTL_C 0x43 #define OPL_REG_AD_C 0x63 #define OPL_REG_SR_C 0x83 #define OPL_REG_WAVE_C 0xE3 #define OPL_REG_FB_C 0xC0 FM_OPL *OPLCreate(int type, int clock, int rate); void OPLDestroy(FM_OPL *OPL); void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset); void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param); void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param); void OPLResetChip(FM_OPL *OPL); int OPLWrite(FM_OPL *OPL,int a,int v); unsigned char OPLRead(FM_OPL *OPL,int a); int OPLTimerOver(FM_OPL *OPL,int c); void OPLWriteReg(FM_OPL *OPL, int r, int v); void YM3812UpdateOne(FM_OPL *OPL, sint16 *buffer, int length); #endif //USE_FMOPL_MIDI #endif //FMOPL_H exult-1.2/audio/midi_drivers/KMIDI.cc0000644000175000001440000000542507550423657013142 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef XWIN #include "KMIDI.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #include "fnames.h" #include "Configuration.h" extern Configuration *config; #if HAVE_LIBKMIDI int kmidi_device_selection(void) { int num_devices=kMidDevices(); if(!num_devices) return -1; cout << "Device\tType\tIdentity" << endl; cout << "-1\tnone\tdisable kmidi" << endl; for(int i=0;i> s; return atoi(s.c_str()); } KMIDI::KMIDI() { cerr << "libkmid initialisation..." << endl; if(KMidSimpleAPI::kMidInit()) { cerr << "failed. Falling back..." << endl; throw 0; } // This is probably not right for anyone but me int devnum; bool changed=false; config->value("config/audio/midi/kmidi/device",devnum,-2); if(devnum==-1) { // kmidi is disabled throw 0; } if(devnum==-2) { devnum=kmidi_device_selection(); changed=true; if(devnum==-1) { // User disabled kmidi devnum=-2; config->set("config/audio/midi/kmidi/device",devnum,true); throw 0; } } kMidSetDevice(devnum); if(changed) { config->set("config/audio/midi/kmidi/device",devnum,true); } } KMIDI::~KMIDI() {} void KMIDI::start_track(XMIDIEventList *event_list,bool repeat) { const char *name = MIDITMPFILE; event_list->Write(name); if(is_playing()) stop_track(); repeat_=repeat; #if DEBUG cerr << "Starting midi sequence with KMIDI: " << name << endl; #endif KMidSimpleAPI::kMidLoad(name); // Something (probably SDL) traps SIGTERM which makes getting // rid of the repeating track a problem. This fixes it: signal(SIGTERM,SIG_DFL); KMidSimpleAPI::kMidPlay((repeat)?255:0); } void KMIDI::stop_track(void) { KMidSimpleAPI::kMidStop(); } bool KMIDI::is_playing(void) { return KMidSimpleAPI::kMidIsPlaying(); } const char *KMIDI::copyright(void) { return KMidSimpleAPI::kMidCopyright(); } #endif // HAVE_LIBKMIDI #endif // XWIN exult-1.2/audio/midi_drivers/Makefile.am0000644000175000001440000000136710026506276014022 INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/../../conf -I$(srcdir)/../.. -I$(srcdir)/.. -I$(srcdir)/../../files -I$(srcdir)/../../imagewin -I$(srcdir)/../../shapes $(SDL_CFLAGS) $(KMID_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -I../../conf -I../../files noinst_LTLIBRARIES = libmididrv.la libmididrv_la_SOURCES = \ KMIDI.cc \ KMIDI.h \ Timidity_binary.cc \ Timidity_binary.h \ forked_player.cc \ forked_player.h \ mixer_midiout.cc \ mixer_midiout.h \ be_midi.cc \ be_midi.h \ mac_midi.cc \ mac_midi.h \ amiga_midi.cc \ amiga_midi.h \ fmopl.cc \ fmopl.h \ fmopl_midi.cc \ fmopl_midi.h \ fmopldrv.cc \ fmopldrv.h \ win_midiout.cc \ win_midiout.h EXTRA_DIST = \ README CLEANFILES = *~ exult-1.2/audio/midi_drivers/Makefile.in0000644000175000001440000002663710061527055014037 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/../../conf -I$(srcdir)/../.. -I$(srcdir)/.. -I$(srcdir)/../../files -I$(srcdir)/../../imagewin -I$(srcdir)/../../shapes $(SDL_CFLAGS) $(KMID_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -I../../conf -I../../files noinst_LTLIBRARIES = libmididrv.la libmididrv_la_SOURCES = \ KMIDI.cc \ KMIDI.h \ Timidity_binary.cc \ Timidity_binary.h \ forked_player.cc \ forked_player.h \ mixer_midiout.cc \ mixer_midiout.h \ be_midi.cc \ be_midi.h \ mac_midi.cc \ mac_midi.h \ amiga_midi.cc \ amiga_midi.h \ fmopl.cc \ fmopl.h \ fmopl_midi.cc \ fmopl_midi.h \ fmopldrv.cc \ fmopldrv.h \ win_midiout.cc \ win_midiout.h EXTRA_DIST = \ README CLEANFILES = *~ subdir = audio/midi_drivers mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libmididrv_la_LDFLAGS = libmididrv_la_LIBADD = am_libmididrv_la_OBJECTS = KMIDI.lo Timidity_binary.lo forked_player.lo \ mixer_midiout.lo be_midi.lo mac_midi.lo amiga_midi.lo fmopl.lo \ fmopl_midi.lo fmopldrv.lo win_midiout.lo libmididrv_la_OBJECTS = $(am_libmididrv_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/KMIDI.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Timidity_binary.Plo \ @AMDEP_TRUE@ $(DEPDIR)/amiga_midi.Plo $(DEPDIR)/be_midi.Plo \ @AMDEP_TRUE@ $(DEPDIR)/fmopl.Plo $(DEPDIR)/fmopl_midi.Plo \ @AMDEP_TRUE@ $(DEPDIR)/fmopldrv.Plo $(DEPDIR)/forked_player.Plo \ @AMDEP_TRUE@ $(DEPDIR)/mac_midi.Plo $(DEPDIR)/mixer_midiout.Plo \ @AMDEP_TRUE@ $(DEPDIR)/win_midiout.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libmididrv_la_SOURCES) DIST_COMMON = README Makefile.am Makefile.in SOURCES = $(libmididrv_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu audio/midi_drivers/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libmididrv.la: $(libmididrv_la_OBJECTS) $(libmididrv_la_DEPENDENCIES) $(CXXLINK) $(libmididrv_la_LDFLAGS) $(libmididrv_la_OBJECTS) $(libmididrv_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/KMIDI.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Timidity_binary.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/amiga_midi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/be_midi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fmopl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fmopl_midi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fmopldrv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/forked_player.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mac_midi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mixer_midiout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/win_midiout.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/audio/midi_drivers/be_midi.h0000644000175000001440000000253207550423657013533 //-*-Mode: C++;-*- /* Copyright (C) 2000 Willem Jan Palenstijn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_be_midi_h_ #define _MIDI_driver_be_midi_h_ #ifdef BEOS #include "Midi.h" #include //name clash; MidiSynthFile.h includes Exult's Midi.h 'accidently' #include class Be_midi : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *,bool repeat); //virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); Be_midi(); virtual ~Be_midi(); private: BMidiSynthFile midiSynthFile; entry_ref midiRef; bool FileOpen; }; #endif #endif exult-1.2/audio/midi_drivers/amiga_midi.cc0000644000175000001440000000560307463225425014357 /* Copyright (C) 2001 Ruediger Hanke This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #if defined(__MORPHOS__) || defined( AMIGA ) #define NO_PPCINLINE_STDARG #include // "Remove" has been defined as a macro in ppcinline/exec.h and it will clash with a // definition in xmidi.h so I better undefine this here. #undef Remove #include "amiga_midi.h" #include "Configuration.h" extern Configuration *config; AmigaMIDI::AmigaMIDI() { int amUnit = 0; FileOpen = false; amMsgPort = NULL; amMidiRequest = NULL; config->value( "config/audio/midi/unit", amUnit, 0 ); /* Open amidi.device */ amMsgPort = CreateMsgPort(); if( amMsgPort ) { amMidiRequest = (struct IOMidiRequest *)CreateIORequest( amMsgPort, sizeof( struct IOMidiRequest ) ); if( amMidiRequest ) { amMidiRequest->amr_Version = 1; if( !OpenDevice( "amidi.device", amUnit, (struct IORequest *)amMidiRequest, 0 ) ) return; DeleteIORequest( amMidiRequest ); amMidiRequest = NULL; } DeleteMsgPort( amMsgPort ); amMsgPort = NULL; } } AmigaMIDI::~AmigaMIDI(void) { stop_track(); if( amMidiRequest ) { CloseDevice( (struct IORequest *)amMidiRequest ); DeleteIORequest( amMidiRequest ); DeleteMsgPort( amMsgPort ); } } void AmigaMIDI::stop_track(void) { if( FileOpen ) { if( amMidiRequest->amr_Std.io_Command == CMD_WRITE ) { AbortIO( (struct IORequest *)amMidiRequest ); WaitIO( (struct IORequest *)amMidiRequest ); } FileOpen = false; } } bool AmigaMIDI::is_playing(void) { bool open; open = FileOpen && amMidiRequest->amr_Std.io_Command == CMD_WRITE && CheckIO( (struct IORequest *)amMidiRequest ) == NULL; return open; } void AmigaMIDI::start_track(XMIDIEventList *event_list,bool repeat) { if( amMidiRequest ) { const static char *name = "T:u7midi"; event_list->Write(name); stop_track(); FileOpen = true; amMidiRequest->amr_Std.io_Command = CMD_WRITE; amMidiRequest->amr_Std.io_Data = (APTR)name; amMidiRequest->amr_Std.io_Length = 0; amMidiRequest->amr_Loop = repeat ? -1 : 0; SendIO( (struct IORequest *)amMidiRequest ); } } const char *AmigaMIDI::copyright(void) { #ifdef __MORPHOS__ return "MorphOS AMIDI MIDI player"; #else return "AmigaOS AMIDI MIDI player"; #endif } #endif exult-1.2/audio/midi_drivers/mac_midi.cc0000755000175000001440000003623707724430450014047 /* * mac_midi.cc - QuickTime based midi player for MacOS. * * Copyright (C) 2001 Max Horn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif //MacOS-specific code #if defined(MACOS) || defined(MACOSX) #include #include #include #include "mac_midi.h" #ifdef MACOSX #include #endif using std::cout; using std::endl; using std::malloc; using std::free; using std::realloc; using std::memset; enum { // number of (32-bit) long words in a note request event kNoteRequestEventLength = ((sizeof(NoteRequest)/sizeof(long)) + 2), // number of (32-bit) long words in a marker event kMarkerEventLength = 1, // number of (32-bit) long words in a general event, minus its data kGeneralEventLength = 2 }; #define BUFFER_INCREMENT 5000 #define REST_IF_NECESSARY() do {\ int timeDiff = eventPos->time - lastEventTime; \ if(timeDiff) \ { \ timeDiff = (int)(timeDiff*tick); \ qtma_StuffRestEvent(*tunePos, timeDiff); \ tunePos++; \ lastEventTime = eventPos->time; \ } \ } while(0) static uint32 *BuildTuneSequence(midi_event *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int &numParts); static uint32 *BuildTuneHeader(int part_poly_max[32], int part_to_inst[32], int numParts); Mac_QT_midi::Mac_QT_midi() : MidiAbstract(), mTunePlayer(0), mTuneSequence(0), mTuneHeader(0) { // FIX ME - check for QuickTime!!! mTunePlayer = OpenDefaultComponent(kTunePlayerComponentType, 0); if( 0 == mTunePlayer ) throw exult_exception("Couldn't get tune place component"); } Mac_QT_midi::~Mac_QT_midi(void) { if(mTunePlayer) { if(mTuneSequence) TuneStop(mTunePlayer, 0); CloseComponent(mTunePlayer); mTunePlayer = 0; } if(mTuneSequence) { free(mTuneSequence); mTuneSequence = 0; } if(mTuneHeader) { DisposePtr((Ptr)mTuneHeader); mTuneHeader = 0; } } void Mac_QT_midi::start_track(XMIDIEventList *elist, bool repeat) { int part_to_inst[32]; int part_poly_max[32]; int numParts = 0; // Max, this is just a work around that should allow things to compile // Note that now the ppqn is always 60, and the tempo is always 500000 mcs // This means each tick is now always 120th of a second int ppqn = 60; midi_event *evntlist = elist->events; UInt32 queueFlags = 0; ComponentResult tpError; memset(part_poly_max,0,sizeof(part_poly_max)); memset(part_to_inst,-1,sizeof(part_to_inst)); // First thing we do - stop any already playing music stop_track(); // Build a tune sequence from the event list mTuneSequence = BuildTuneSequence(evntlist, ppqn, part_poly_max, part_to_inst, numParts); if(!mTuneSequence) goto bail; // Now build a tune header from the data we collect above, create // all parts as needed and assign them the correct instrument. mTuneHeader = BuildTuneHeader(part_poly_max, part_to_inst, numParts); if(!mTuneHeader) goto bail; // Set up the queue flags queueFlags = kTuneStartNow; if(repeat) queueFlags |= kTuneLoopUntil; // Set the time scale (units per second), we want milliseconds tpError = TuneSetTimeScale(mTunePlayer, 1000); assert (tpError == noErr); // Set the header, to tell what instruments are used tpError = TuneSetHeader(mTunePlayer, (UInt32 *)mTuneHeader); assert (tpError == noErr); // Have it allocate whatever resources are needed tpError = TunePreroll(mTunePlayer); assert (tpError == noErr); // We want to play at normal volume tpError = TuneSetVolume(mTunePlayer, 0x00010000); assert (tpError == noErr); // Finally, start playing the full song tpError = TuneQueue(mTunePlayer, (UInt32 *)mTuneSequence, 0x00010000, 0, 0xFFFFFFFF, queueFlags, NULL, 0); assert (tpError == noErr); return; bail: // This disposes of the allocated tune header/sequence stop_track(); } void Mac_QT_midi::stop_track(void) { if(0 == mTuneSequence) return; // For some resons, using a non-zero stopflag doesn't stop the music at all:/ // TuneStop(mTunePlayer, kTuneStopFade | kTuneStopInstant | kTuneStopReleaseChannels); // Stop music TuneStop(mTunePlayer, 0); // Deallocate all instruments TuneUnroll(mTunePlayer); // Finally, free the data storage free(mTuneSequence); mTuneSequence = 0; if(mTuneHeader) { DisposePtr((Ptr)mTuneHeader); mTuneHeader = 0; } } bool Mac_QT_midi::is_playing(void) { TuneStatus ts; TuneGetStatus(mTunePlayer,&ts); return ts.queueTime != 0; } const char *Mac_QT_midi::copyright(void) { return "Internal QuickTime MIDI player"; } uint32 *BuildTuneSequence(midi_event *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int &numParts) { int part_poly[32]; int channel_to_part[16]; int channel_pan[16]; int channel_vol[16]; int channel_pitch_bend[16]; int lastEventTime = 0; int tempo = 500000; double Ippqn = 1.0 / (1000*ppqn); double tick = tempo * Ippqn; midi_event *eventPos = evntlist; uint32 *tunePos, *endPos; uint32 *tuneSequence; size_t tuneSize; #ifdef DEBUG int numEventsHandled = 0; #endif // allocate space for the tune header tuneSize = 5000; tuneSequence = (uint32 *)malloc(tuneSize * sizeof(uint32)); if (tuneSequence == NULL) return NULL; // Set starting position in our tune memory tunePos = tuneSequence; endPos = tuneSequence + tuneSize; // Initialise the arrays memset(part_poly,0,sizeof(part_poly)); memset(channel_to_part,-1,sizeof(channel_to_part)); memset(channel_pan,-1,sizeof(channel_pan)); memset(channel_vol,-1,sizeof(channel_vol)); memset(channel_pitch_bend,-1,sizeof(channel_pitch_bend)); /* * Now the major work - iterate over all GM events, * and turn them into QuickTime Music format. * At the same time, calculate the max. polyphony for each part, * and also the part->instrument mapping. */ while(eventPos) { int status = (eventPos->status&0xF0)>>4; int channel = eventPos->status&0x0F; int part = channel_to_part[channel]; int velocity, pitch; int value, controller; int bend; int newInst; // Check if we are running low on space... if((tunePos+16) > endPos) { // Resize our data storage. uint32 *oldTuneSequence = tuneSequence; tuneSize += BUFFER_INCREMENT; tuneSequence = (uint32 *)realloc(tuneSequence, tuneSize * sizeof(uint32)); if(oldTuneSequence != tuneSequence) tunePos += tuneSequence - oldTuneSequence; endPos = tuneSequence + tuneSize; } #if defined(DEBUG) && 0 numEventsHandled++; cout << std::setw(4) << numEventsHandled << ". "; cout << "Time: " << std::setw(5) << eventPos->time << " "; cout << std::hex << std::uppercase; cout << "Status 0x" << status << " Channel: 0x" << channel << " "; cout << "Data 0x" << std::setw(4) <<*(unsigned short *)(eventPos->data) << " "; cout << std::dec; cout << "Length " << eventPos->len << endl; #endif switch (status) { case MIDI_STATUS_NOTE_OFF: assert(part>=0 && part<=31); // Keep track of the polyphony of the current part part_poly[part]--; break; case MIDI_STATUS_NOTE_ON: if (part < 0) { // If no part is specified yet, we default to the first instrument, which // is piano (or the first drum kit if we are on the drum channel) int newInst; if (channel == 9) newInst = kFirstDrumkit + 1; // the first drum kit is the "no drum" kit! else newInst = kFirstGMInstrument; part = channel_to_part[channel] = numParts; part_to_inst[numParts++] = newInst; } // TODO - add support for more than 32 parts using eXtended QTMA events assert(part<=31); // Decode pitch & velocity pitch = eventPos->data[0]; velocity = eventPos->data[1]; if (velocity == 0) { // was a NOTE OFF in disguise, so we decrement the polyphony part_poly[part]--; } else { // Keep track of the polyphony of the current part int foo = ++part_poly[part]; if (part_poly_max[part] < foo) part_poly_max[part] = foo; // Now scan forward to find the matching NOTE OFF event midi_event *noteOffPos; for(noteOffPos = eventPos; noteOffPos; noteOffPos = noteOffPos->next) { if ((noteOffPos->status&0xF0)>>4 == MIDI_STATUS_NOTE_OFF && channel == (eventPos->status&0x0F) && pitch == noteOffPos->data[0]) break; // NOTE ON with velocity == 0 is the same as a NOTE OFF if ((noteOffPos->status&0xF0)>>4 == MIDI_STATUS_NOTE_ON && channel == (eventPos->status&0x0F) && pitch == noteOffPos->data[0] && 0 == noteOffPos->data[1]) break; } // Did we find a note off? Should always be the case, but who knows... if (noteOffPos) { // We found a NOTE OFF, now calculate the note duration int duration = (int)((noteOffPos->time - eventPos->time)*tick); REST_IF_NECESSARY(); // Now we need to check if we get along with a normal Note Even, or if we need an extended one... if (duration < 2048 && pitch>=32 && pitch<=95 && velocity>=0 && velocity<=127) { qtma_StuffNoteEvent(*tunePos, part, pitch, velocity, duration); tunePos++; } else { qtma_StuffXNoteEvent(*tunePos, *(tunePos+1), part, pitch, velocity, duration); tunePos+=2; } #if defined(DEBUG) && 0 cout << std::setw(4) << numEventsHandled << ". "; cout << "NOTE ON duration " << std::setw(4) << duration << " "; cout << "Channel " << std::setw(2) << channel << " "; cout << "Part " << std::setw(2) << part << " "; cout << "Pitch " << std::setw(2) << pitch << " "; cout << "Velocity " << std::setw(2) << velocity << endl; #endif } } break; case MIDI_STATUS_AFTERTOUCH: COUT("MIDI_STATUS_AFTERTOUCH"); break; case MIDI_STATUS_CONTROLLER: controller = eventPos->data[0]; value = eventPos->data[1]; switch(controller) { case 0: // bank change - igore for now break; case kControllerVolume: if(channel_vol[channel] != value<<8) { channel_vol[channel] = value<<8; if(part>=0 && part<=31) { REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerVolume, channel_vol[channel]); tunePos++; } } break; case kControllerPan: if(channel_pan[channel] != ((value << 1) + 256)) { channel_pan[channel] = ((value << 1) + 256); if(part>=0 && part<=31) { REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerPan, channel_pan[channel]); tunePos++; } } break; default: COUT("CONTROLLER not handled: "<< controller); break; } break; case MIDI_STATUS_PROG_CHANGE: // Instrument changed newInst = eventPos->data[0]; // Channel 9 (the 10th channel) is different, it indicates a drum kit if (channel == 9) newInst += kFirstDrumkit; else newInst += kFirstGMInstrument; // Only if the instrument for this channel *really* changed, add a new part. if(newInst != part_to_inst[part]) { // TODO maybe make use of kGeneralEventPartChange here, // to help QT reuse note channels? part = channel_to_part[channel] = numParts; part_to_inst[numParts++] = newInst; if(channel_vol[channel] >= 0) { REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerVolume, channel_vol[channel]); tunePos++; } if(channel_pan[channel] >= 0) { REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerPan, channel_pan[channel]); tunePos++; } if(channel_pitch_bend[channel] >= 0) { REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerPitchBend, channel_pitch_bend[channel]); tunePos++; } } break; case MIDI_STATUS_PRESSURE: COUT("MIDI_STATUS_PRESSURE"); break; case MIDI_STATUS_PITCH_WHEEL: // In the midi spec, 0x2000 = center, 0x0000 = - 2 semitones, 0x3FFF = +2 semitones // but for QTMA, we specify it as a 8.8 fixed point of semitones // TODO: detect "pitch bend range changes" bend = eventPos->data[0] & 0x7f | (eventPos->data[1] & 0x7f) << 7; // "Center" the bend bend -= 0x2000; // Move it to our format: bend <<= 4; // If it turns out the pitch bend didn't change, stop here if(channel_pitch_bend[channel] == bend) break; channel_pitch_bend[channel] = bend; if(part>=0 && part<=31) { // Stuff a control event REST_IF_NECESSARY(); qtma_StuffControlEvent(*tunePos, part, kControllerPitchBend, bend); tunePos++; } break; case MIDI_STATUS_SYSEX: if (eventPos->status == 0xFF && eventPos->data[0] == 0x51) // Tempo change { tempo = (eventPos->buffer[0] << 16) + (eventPos->buffer[1] << 8) + eventPos->buffer[2]; tick = tempo * Ippqn; } break; } // on to the next event eventPos = eventPos->next; } // Finally, place an end marker *tunePos = kEndMarkerValue; return tuneSequence; } uint32 *BuildTuneHeader(int part_poly_max[32], int part_to_inst[32], int numParts) { uint32 *myHeader; uint32 *myPos1, *myPos2; // pointers to the head and tail long words of a music event NoteRequest *myNoteRequest; NoteAllocator myNoteAllocator; // for the NAStuffToneDescription call ComponentResult myErr = noErr; myHeader = NULL; myNoteAllocator = NULL; /* * Open up the Note Allocator */ myNoteAllocator = OpenDefaultComponent(kNoteAllocatorComponentType,0); if (myNoteAllocator == NULL) goto bail; /* * Allocate space for the tune header */ myHeader = (uint32 *) NewPtrClear((numParts * kNoteRequestEventLength + kMarkerEventLength) * sizeof(uint32)); if (myHeader == NULL) goto bail; myPos1 = myHeader; /* * Loop over all parts */ for(int part = 0; part < numParts; ++part) { /* * Stuff request for the instrument with the given polyphony */ myPos2 = myPos1 + (kNoteRequestEventLength - 1); // last longword of general event qtma_StuffGeneralEvent(*myPos1, *myPos2, part, kGeneralEventNoteRequest, kNoteRequestEventLength); myNoteRequest = (NoteRequest *)(myPos1 + 1); myNoteRequest->info.flags = 0; myNoteRequest->info.polyphony = part_poly_max[part]; myNoteRequest->info.typicalPolyphony = 0x00010000; myErr = NAStuffToneDescription(myNoteAllocator,part_to_inst[part],&myNoteRequest->tone); if (myErr != noErr) goto bail; // move pointer to beginning of next event myPos1 += kNoteRequestEventLength; } *myPos1 = kEndMarkerValue; /* end of sequence marker */ bail: if(myNoteAllocator) CloseComponent(myNoteAllocator); // if we encountered an error, dispose of the storage we allocated and return NULL if (myErr != noErr) { DisposePtr((Ptr)myHeader); myHeader = NULL; } return myHeader; } #endif exult-1.2/audio/midi_drivers/forked_player.h0000644000175000001440000000246407550423657014775 //-*-Mode: C++;-*- /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_forked_player_h_ #define _MIDI_driver_forked_player_h_ #include #include #include "Flex.h" #include "Table.h" #include "Midi.h" #if HAVE_LIBKMIDI #include #endif class forked_player : virtual public MidiAbstract { bool repeat_; public: virtual void start_track(XMIDIEventList *, bool repeat); // virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); forked_player(); virtual ~forked_player(); private: pid_t forked_job; }; #endif exult-1.2/audio/midi_drivers/fmopl_midi.h0000644000175000001440000001043610054030551014240 /* Copyright (C) 2000, 2001, 2002 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef FMOPL_MIDI_H #define FMOPL_MIDI_H #ifdef USE_FMOPL_MIDI // 22050/OPL_NUM_SAMPLES_PER_PASS = (120*OPL_TICK_MULTIPLIER)/OPL_TIME_PER_PASS #define OPL_TIME_PER_PASS 4 #define OPL_NUM_SAMPLES_PER_PASS 49 //#define OPL_TIME_PER_PASS 8 //#define OPL_NUM_SAMPLES_PER_PASS 98 //#define OPL_TIME_PER_PASS 32 //#define OPL_NUM_SAMPLES_PER_PASS 392 #define OPL_TICK_MULTIPLIER 15 #include "Midi.h" #include "exceptions.h" #include "SDL_thread.h" #include "SDL.h" class OplDriver; class RingBuffer16; class FMOpl_Midi : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *, bool repeat); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); virtual void load_patches(bool force_xmidi); virtual bool is_fm_synth(); virtual bool use_gs127(); // PSMDEX - Pentagram Streaming Midi Driver Extensions virtual int max_streams(); virtual void start_stream(int str_num, XMIDIEventList *, bool repeat, bool activate, int vol); virtual void activate_stream(int str_num); virtual void stop_stream(int str_num); virtual void set_volume(int str_num, int level); virtual bool is_playing(int str_num); virtual int get_active(); FMOpl_Midi(); virtual ~FMOpl_Midi(); private: UNREPLICATABLE_CLASS(FMOpl_Midi); struct mid_data { XMIDIEventList *list; bool repeat; }; static const unsigned short centre_value; static const unsigned char fine_value; static const unsigned char coarse_value; static const unsigned short combined_value; int is_available; OplDriver *opl; RingBuffer16 *buffer; // For Dual Opl2 Mode bool dual; int global_volume; uint8 volumes[16]; uint8 balances[16]; OplDriver *opl_right; RingBuffer16 *buffer_right; // Communications int &LockComs(); void UnlockComs(); void ClearComs(); bool playing; int comMessage_priv; XMIDIEventList *new_list; SDL_mutex *mutex; SDL_mutex *comMutex; // Methods static void mixer_hook_static(void *udata, Uint8 *stream, int len); void mixer_hook(Uint8 *stream, int len); void init_device(); void deinit_device(); void reset_channel (int i); // Sample Clock unsigned long total_sample_ticks; unsigned long start; inline void wmoClockIncTime(unsigned long c) { total_sample_ticks += c; } inline unsigned long wmoGetRealTime () { return total_sample_ticks*OPL_TIME_PER_PASS; } inline void wmoInitClock () { start = wmoGetRealTime(); } inline void wmoAddOffset (unsigned long offset) { start += offset; } inline void wmoSubOffset (unsigned long offset) { start -= offset; } inline unsigned long wmoGetTime () { return wmoGetRealTime() - start; } inline unsigned long wmoGetStart () { return start; } inline void send(uint32 b); inline void send_vol_or_balance(uint32 chan); void PlayNotes(); void HandlePlay(); void HandleStop(); uint32 GenerateSamples(uint32 count_required, uint32 sample_rate); void GetSamples(uint32 samples); // This stuff is only actually used by the play thread. it should NOT be touched // by anything else int repeat; uint32 aim; sint32 diff; uint32 last_tick; XMIDIEventList *evntlist; midi_event *event; NoteStack notes_on; uint32 generate_rem; // // Xmidi Looping // // The for loop event midi_event *loop_event[XMIDI_MAX_FOR_LOOP_COUNT]; // The amount of times we have left that we can loop int loop_count[XMIDI_MAX_FOR_LOOP_COUNT]; // The level of the loop we are currently in int loop_num; }; #endif //USE_FMOPL_MIDI #endif //FMOPL_MIDI_H exult-1.2/audio/midi_drivers/win_midiout.h0000644000175000001440000000626310054030551014453 /* Copyright (C) 2000, 2001, 2002 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef WIN_MIDIOUT_H #define WIN_MIDIOUT_H #if defined(WIN32) && !defined(UNDER_CE) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif // These will prevent inclusion of mmsystem sections #define MMNODRV // Installable driver support #define MMNOSOUND // Sound support #define MMNOWAVE // Waveform support #define MMNOAUX // Auxiliary audio support #define MMNOMIXER // Mixer support #define MMNOTIMER // Timer support #define MMNOJOY // Joystick support #define MMNOMCI // MCI support #define MMNOMMIO // Multimedia file I/O support #include #include #include "../Midi.h" #include "exceptions.h" class Windows_MidiOut : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *, bool repeat); virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual void stop_sfx(void); virtual bool is_playing(void); virtual const char *copyright(void); Windows_MidiOut(); virtual ~Windows_MidiOut(); private: UNREPLICATABLE_CLASS(Windows_MidiOut); struct mid_data { XMIDIEventList *list; bool repeat; }; static const unsigned short centre_value; static const unsigned char fine_value; static const unsigned char coarse_value; static const unsigned short combined_value; signed int dev_num; HMIDIOUT midi_port; HANDLE *thread_handle; DWORD thread_id; // Thread communicatoins LONG is_available; LONG playing; LONG s_playing; LONG thread_com; LONG sfx_com; mid_data *thread_data; mid_data *sfx_data; mid_data data; mid_data sdata; // Methods static DWORD __stdcall thread_start(void *data); void init_device(); DWORD thread_main(); void thread_play (); void reset_channel (int i); // Microsecond Clock unsigned long start; unsigned long sfx_start; inline void wmoInitClock () { start = GetTickCount()*6; } inline void wmoAddOffset (unsigned long offset) { start += offset; } inline unsigned long wmoGetTime () { return GetTickCount()*6 - start; } inline unsigned long wmoGetStart () { return start; } inline unsigned long wmoGetRealTime () { return GetTickCount()*6; } inline void wmoInitSFXClock () { sfx_start = GetTickCount()*6; } inline void wmoAddSFXOffset (unsigned long offset) { sfx_start += offset; } inline unsigned long wmoGetSFXTime () { return GetTickCount()*6 - sfx_start; } inline unsigned long wmoGetSFXStart () { return sfx_start; } }; #endif //WIN32 #endif //WIN_MIDIOUT_H exult-1.2/audio/midi_drivers/fmopl_midi.cc0000644000175000001440000004766110054030551014410 /* Copyright (C) 2000, 2001, 2002 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef USE_FMOPL_MIDI #include #include "Audio.h" #include "fmopl_midi.h" #include "fmopldrv.h" #include "xmidi.h" #include "utils.h" #include "Configuration.h" #include "SDL_mixer.h" extern Configuration *config; #define FMOPL_MESSAGE_NO_MESSAGE 0 #define FMOPL_MESSAGE_PLAY 1 #define FMOPL_MESSAGE_PLAY_REPEAT 2 #define FMOPL_MESSAGE_STOP 3 #define FMOPL_MESSAGE_INIT 4 const unsigned short FMOpl_Midi::centre_value = 0x2000; const unsigned char FMOpl_Midi::fine_value = centre_value & 127; const unsigned char FMOpl_Midi::coarse_value = centre_value >> 7; const unsigned short FMOpl_Midi::combined_value = (coarse_value << 8) | fine_value; //#define DO_SMP_TEST #ifdef DO_SMP_TEST #define giveinfo() std::cerr << __FILE__ << ":" << __LINE__ << std::endl; std::cerr.flush(); #else #define giveinfo() #endif using std::string; using std::cout; using std::cerr; using std::endl; class RingBuffer16 { uint32 write_pos; uint32 read_pos; sint16 *buf; uint32 size; SDL_mutex *mutex; public: void LockWrite(uint32 total, sint16 *&buf1, uint32 &size1, sint16 *&buf2, uint32 &size2); void LockRead(uint32 total, sint16 *&buf1, uint32 &size1, sint16 *&buf2, uint32 &size2); void Unlock(); RingBuffer16(uint32 s); ~RingBuffer16(); }; RingBuffer16::RingBuffer16(uint32 s) : write_pos(0), read_pos(0), size(s) { buf = new sint16[size]; std::memset(buf, 0, sizeof(sint16)*size); mutex = SDL_CreateMutex(); } RingBuffer16::~RingBuffer16() { SDL_DestroyMutex(mutex); delete [] buf; } void RingBuffer16::Unlock() { // Unlock it SDL_mutexV(mutex); } void RingBuffer16::LockRead(uint32 total, sint16 *&buf1, uint32 &size1, sint16 *&buf2, uint32 &size2) { // Lock it SDL_mutexP(mutex); // Too many samples if (size < total) { size1 = 0; buf1 = 0; size2 = 0; buf2 = 0; return; } // It will run over the end of the ring buffer. Need to return end and start if (read_pos + total >= size) { // Buffer 1 buf1 = buf + read_pos; size1 = size - read_pos; // Increment read_pos read_pos += total; read_pos -= size; // Buffer 2 buf2 = buf; size2 = read_pos; return; } // Handle it normally buf1 = buf + read_pos; size1 = total; buf2 = 0; size2 = 0; read_pos += total; } void RingBuffer16::LockWrite(uint32 total, sint16 *&buf1, uint32 &size1, sint16 *&buf2, uint32 &size2) { // Lock it SDL_mutexP(mutex); // Too many samples if (size < total) { size1 = 0; buf1 = 0; size2 = 0; buf2 = 0; return; } // It will run over the end of the ring buffer. Need to return end and start if (write_pos + total >= size) { // Buffer 1 buf1 = buf + write_pos; size1 = size - write_pos; // Increment read_pos write_pos += total; write_pos -= size; // Buffer 2 buf2 = buf; size2 = write_pos; return; } // Handle it normally buf1 = buf + write_pos; size1 = total; buf2 = 0; size2 = 0; write_pos += total; } FMOpl_Midi::FMOpl_Midi() { giveinfo(); playing = false; is_available = false; giveinfo(); init_device(); giveinfo(); } FMOpl_Midi::~FMOpl_Midi() { giveinfo(); if (!is_available) return; deinit_device(); } void FMOpl_Midi::deinit_device() { // Un Hook SDL is_available = false; Mix_HookMusic (NULL, NULL); #ifdef PENTAGRAM Mix_CloseAudio(); #endif // Delay a fraction SDL_Delay(10); // Lock it SDL_mutexP(mutex); // Free everything if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; // Free new list if it exists if (new_list) new_list->DecerementCounter(); new_list = NULL; comMessage_priv = FMOPL_MESSAGE_NO_MESSAGE; // Reset the reasonable defaults repeat = false; aim = 0; diff = 0; last_tick = 0; evntlist = NULL; event = NULL; notes_on.clear(); loop_num = -1; std::memset(volumes, 64, sizeof(volumes)); std::memset(balances, 64, sizeof(balances)); generate_rem = 0; total_sample_ticks = 0; // Left delete opl; opl = 0; delete buffer; buffer = 0; // Right delete opl_right; opl_right = 0; delete buffer_right; buffer_right = 0; // Unlock it SDL_mutexV(mutex); // Kill it SDL_DestroyMutex(mutex); SDL_DestroyMutex(comMutex); mutex = NULL; comMutex = NULL; } void FMOpl_Midi::init_device() { string s; Audio *audio = Audio::get_ptr(); // Dual Opl mode if (audio->is_stereo()) { config->value("config/audio/midi/dual_opl",s,"yes"); if (s == "yes") dual = true; else { s = "no"; dual = false; } std::cout << "Dual OPL mode: " << s << endl; // Make sure it's in the config config->set("config/audio/midi/dual_opl",s,true); } else { dual = false; } // Now setup all our settings playing = false; generate_rem = 0; is_available = true; comMessage_priv = FMOPL_MESSAGE_NO_MESSAGE; new_list = NULL; // Create Left buffer = new RingBuffer16(44096); opl = new OplDriver; opl->open(audio->get_sample_rate()); // Create right, if required if (dual) { buffer_right = new RingBuffer16(44096); opl_right = new OplDriver; opl_right->open(audio->get_sample_rate()); } else { opl_right = 0; buffer_right = 0; } // Setup some reasonable defaults repeat = false; aim = 0; diff = 0; last_tick = 0; evntlist = NULL; event = NULL; notes_on.clear(); loop_num = -1; std::memset(volumes, 64, sizeof(volumes)); std::memset(balances, 64, sizeof(balances)); generate_rem = 0; total_sample_ticks = 0; global_volume = 255; // Create the Mutexes mutex = SDL_CreateMutex(); comMutex = SDL_CreateMutex(); // Hook the process #ifdef PENTAGRAM Mix_OpenAudio(audio->get_sample_rate(), AUDIO_S16SYS, 2, 4096); #endif Mix_HookMusic (mixer_hook_static, (void*) this); } inline void FMOpl_Midi::send_vol_or_balance(uint32 chan) { // Single OPL mode only if (!dual) return; int left = volumes[chan]; int right = volumes[chan]; // is left if (balances[chan] < 64) { right *= balances[chan]; right >>= 6; // right /= 64; } // is right else if (balances[chan] > 64) { left *= 127 - balances[chan]; left >>= 6; // left /= 64; } opl->send(chan | (MIDI_STATUS_CONTROLLER << 4)|(7 << 8) | (left<<16)); opl_right->send(chan | (MIDI_STATUS_CONTROLLER << 4)|(7 << 8) | (right<<16)); } inline void FMOpl_Midi::send(uint32 b) { // Volume if (dual && (b&0xFFF0) == ((MIDI_STATUS_CONTROLLER << 4)|(7 << 8))) { int chan = b&0xF; volumes[chan] = (b >> 16) & 0x7F; send_vol_or_balance(chan); } // Balance else if (dual && (b&0xFFF0) == ((MIDI_STATUS_CONTROLLER << 4)|(10 << 8))) { int chan = b&0xF; balances[chan] = (b >> 16) & 0x7F; send_vol_or_balance(chan); } else { opl->send(b); if (opl_right) opl_right->send(b); } } uint32 FMOpl_Midi::GenerateSamples(uint32 count_required, uint32 sample_rate) { uint32 amount_generated = 0; uint32 inc = 1; uint32 gen = OPL_NUM_SAMPLES_PER_PASS; if (sample_rate == 44100) gen *= 2; else if (sample_rate == 11025) inc *= 2; else if (sample_rate != 22050) { // Approximate it! inc = 6; gen = (OPL_TIME_PER_PASS*sample_rate)/(120*OPL_TICK_MULTIPLIER*inc); } while (amount_generated < count_required) { HandleStop(); PlayNotes(); HandlePlay(); GetSamples(gen); amount_generated += gen; wmoClockIncTime(inc); } return amount_generated - count_required; } void FMOpl_Midi::PlayNotes() { // Handle note off's here while (midi_event *note = notes_on.PopTime(wmoGetRealTime())) send(note->status | (note->data[0] << 8)); while (event) { aim = (event->time-last_tick)*OPL_TICK_MULTIPLIER; //printf ("aim %i time %i\n", aim, wmoGetTime ()); diff = aim - wmoGetTime (); if (diff > 0) break; last_tick = event->time; wmoAddOffset(aim); // XMIDI For Loop if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_FOR_LOOP) { if (loop_num < XMIDI_MAX_FOR_LOOP_COUNT) loop_num++; loop_count[loop_num] = event->data[1]; loop_event[loop_num] = event; } // XMIDI Next/Break else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_NEXT_BREAK) { if (loop_num != -1) { if (event->data[1] < 64) { loop_num--; } } event = NULL; } // XMIDI Callback Trigger else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_CALLBACK_TRIG) { // TODO } // Not SysEx else if (event->status < 0xF0) { int type = event->status >> 4; if ((type != MIDI_STATUS_NOTE_ON || event->data[1]) && type != MIDI_STATUS_NOTE_OFF) { if (type == MIDI_STATUS_NOTE_ON) { notes_on.Remove(event); notes_on.Push (event, event->duration * OPL_TICK_MULTIPLIER + wmoGetStart()); } send(event->status | (event->data[0] << 8) | (event->data[1] << 16)); } } if (event) event = event->next; // Lock com system int &comMessage = LockComs(); if (!event || comMessage != FMOPL_MESSAGE_NO_MESSAGE) { bool clean = !repeat || (comMessage != FMOPL_MESSAGE_NO_MESSAGE) || last_tick == 0; if (clean) { playing = false; if (comMessage == FMOPL_MESSAGE_STOP) comMessage = FMOPL_MESSAGE_NO_MESSAGE; // Handle note off's here while (midi_event *note = notes_on.Pop()) send(note->status | (note->data[0] << 8)); // Clean up for (int i = 0; i < 16; i++) reset_channel (i); //midiOutReset (midi_port); if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; event = NULL; loop_num = -1; wmoInitClock (); } last_tick = 0; if (evntlist) { if (loop_num == -1) event = evntlist->events; else { event = loop_event[loop_num]->next; last_tick = loop_event[loop_num]->time; if (loop_count[loop_num]) if (!--loop_count[loop_num]) loop_num--; } } } // UnLock com system UnlockComs(); } } void FMOpl_Midi::HandlePlay() { // Lock com system int &comMessage = LockComs(); // Got issued a music play command // set up the music playing routine if (comMessage == FMOPL_MESSAGE_PLAY || comMessage == FMOPL_MESSAGE_PLAY_REPEAT) { // Handle note off's here while (midi_event *note = notes_on.Pop()) send(note->status | (note->data[0] << 8)); // Manual Reset since I don't trust midiOutReset() giveinfo(); for (int i = 0; i < 16; i++) reset_channel (i); if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; event = NULL; playing = false; giveinfo(); evntlist = new_list; repeat = (comMessage == FMOPL_MESSAGE_PLAY_REPEAT); giveinfo(); new_list = NULL; giveinfo(); comMessage = FMOPL_MESSAGE_NO_MESSAGE; giveinfo(); if (evntlist) event = evntlist->events; else event = 0; giveinfo(); last_tick = 0; giveinfo(); wmoInitClock (); // Reset XMIDI Looping loop_num = -1; giveinfo(); playing = true; } // Unlock com system UnlockComs(); } void FMOpl_Midi::HandleStop() { // Lock com system int &comMessage = LockComs(); if (comMessage == FMOPL_MESSAGE_STOP) { giveinfo(); playing = false; comMessage = FMOPL_MESSAGE_NO_MESSAGE; // Handle note off's here while (midi_event *note = notes_on.Pop()) send(note->status | (note->data[0] << 8)); giveinfo(); // Clean up for (int i = 0; i < 16; i++) reset_channel (i); //midiOutReset (midi_port); giveinfo(); if (evntlist) evntlist->DecerementCounter(); giveinfo(); evntlist = NULL; event = NULL; giveinfo(); // If stop was requested, we are ready to receive another song loop_num = -1; wmoInitClock (); last_tick = 0; } // Unlock com system UnlockComs(); } void FMOpl_Midi::reset_channel (int i) { // Bank Select (General Midi) send(i | (MIDI_STATUS_CONTROLLER << 4) | (0 << 8) | (127 << 16)); // Modulation Wheel send(i | (MIDI_STATUS_CONTROLLER << 4) | (1 << 8) | (coarse_value << 16)); // Volume send(i | (MIDI_STATUS_CONTROLLER << 4) | (7 << 8) | (coarse_value << 16)); // Balance send(i | (MIDI_STATUS_CONTROLLER << 4) | (10 << 8) | (coarse_value << 16)); // Expression send(i | (MIDI_STATUS_CONTROLLER << 4) | (11 << 8) | (127 << 16)); // XMIDI Bank Select send(i | (MIDI_STATUS_CONTROLLER << 4) | (XMIDI_CONTROLLER_BANK_CHANGE << 8) | (0 << 16)); // All notes off send(i | (MIDI_STATUS_CONTROLLER << 4) | (123 << 8)); // Instrument send(i | (MIDI_STATUS_PROG_CHANGE << 4) | (0 << 8)); // Pitch Wheel send(i | (MIDI_STATUS_PITCH_WHEEL << 4) | (combined_value << 8)); } // Lock the coms int &FMOpl_Midi::LockComs() { SDL_mutexP(comMutex); return comMessage_priv; } // Unlock the coms void FMOpl_Midi::UnlockComs() { SDL_mutexV(comMutex); } // Clead coms void FMOpl_Midi::ClearComs() { comMessage_priv = FMOPL_MESSAGE_NO_MESSAGE; // Free everything if (new_list) new_list->DecerementCounter(); new_list = NULL; } void FMOpl_Midi::start_track (XMIDIEventList *xmidi, bool repeat) { giveinfo(); if (!is_available) init_device(); giveinfo(); if (!is_available) return; giveinfo(); // Lock and clear the com system int &comMessage = LockComs(); ClearComs(); // Increment the list counter giveinfo(); xmidi->IncerementCounter(); new_list = xmidi; // Set the com message if (repeat) comMessage = FMOPL_MESSAGE_PLAY_REPEAT; else comMessage = FMOPL_MESSAGE_PLAY; // Unlock the coms UnlockComs(); } void FMOpl_Midi::stop_track(void) { giveinfo(); if (!is_available) return; giveinfo(); // Lock and clear the com system int &comMessage = LockComs(); ClearComs(); // If we are playing, we need to issue a stop com if (playing) comMessage = FMOPL_MESSAGE_STOP; // Unlock the coms UnlockComs(); } bool FMOpl_Midi::is_playing(void) { giveinfo(); int &comMessage = LockComs(); // If a stop command has been issued, we'll return and say that we have actually stopped // even though, there may still be some output. bool ret = playing && comMessage != FMOPL_MESSAGE_STOP; UnlockComs(); return ret; } const char *FMOpl_Midi::copyright(void) { giveinfo(); return "Internal Emulated FM Opl Midi Synth."; } void FMOpl_Midi::mixer_hook_static(void *udata, Uint8 *stream, int len) { ((FMOpl_Midi *)udata)->mixer_hook(stream, len); } void FMOpl_Midi::mixer_hook(Uint8 *stream, int len) { // Lock the mutex SDL_mutexP(mutex); // Looks like we are shutting down if (!is_available) return; Audio *audio = Audio::get_ptr(); // Generate the music if (audio->is_stereo()) generate_rem = GenerateSamples(len/4-generate_rem, audio->get_sample_rate()); else generate_rem = GenerateSamples(len/2-generate_rem, audio->get_sample_rate()); // Copy the buffers into SDL_Mixer's buffer sint16* stream16 = (sint16*) stream; sint16* b1 = 0; sint16* b2 = 0; uint32 size1 = 0; uint32 size2 = 0; int i = 0; // Lock it (Left or Mono) if (audio->is_stereo()) buffer->LockRead(len/4, b1, size1, b2, size2); else buffer->LockRead(len/2, b1, size1, b2, size2); sint16* b1_r = b1; sint16* b2_r = b2; uint32 size1_r = size1; uint32 size2_r = size2; // Right, if in dual mode if (dual) buffer_right->LockRead(len/4, b1_r, size1_r, b2_r, size2_r); // Copy the samples if (global_volume >= 255) { if (audio->is_stereo()) { for (i = 0; i < size1; ++i) { stream16[i<<1] = b1[i]; stream16[(i<<1)+1] = b1_r[i]; } for (i = 0; i < size2; ++i) { stream16[(i+size1)<<1] = b2[i]; stream16[((i+size1)<<1)+1] = b2_r[i]; } } else { for (i = 0; i < size1; ++i) { stream16[i] = b1[i]; } for (i = 0; i < size2; ++i) { stream16[i+size1] = b2[i]; } } } else if (global_volume && dual) { for (i = 0; i < size1; ++i) { stream16[i<<1] = (b1[i]*global_volume)/255; stream16[(i<<1)+1] = (b1_r[i]*global_volume)/255; } for (i = 0; i < size2; ++i) { stream16[(i+size1)<<1] = (b2[i]*global_volume)/255; stream16[((i+size1)<<1)+1] = (b2_r[i]*global_volume)/255; } } else if (global_volume) { if (audio->is_stereo()) { for (i = 0; i < size1; ++i) { stream16[(i<<1)+1] = stream16[i<<1] = (b1[i]*global_volume)/255; } for (i = 0; i < size2; ++i) { stream16[((i+size1)<<1)+1] = stream16[(i+size1)<<1] = (b2[i]*global_volume)/255; } } else { for (i = 0; i < size1; ++i) { stream16[i] = (b1[i]*global_volume)/255; } for (i = 0; i < size2; ++i) { stream16[i+size1] = (b2[i]*global_volume)/255; } } } // Unlock right first if (dual) buffer_right->Unlock(); // Unlock it buffer->Unlock(); // Unlock the mutex SDL_mutexV(mutex); } void FMOpl_Midi::GetSamples(uint32 samples) { // Got samples if (samples) { // Do the lock and generate the samples sint16* b1 = 0; sint16* b2 = 0; uint32 size1 = 0; uint32 size2 = 0; // Lock left buffer->LockWrite(samples, b1, size1, b2, size2); // printf ("Generating %i samples\n", samples); if (size1 && b1) opl->generate_samples(b1, size1); if (size2 && b2) opl->generate_samples(b2, size2); if (dual) { // Lock it (right) buffer_right->LockWrite(samples, b1, size1, b2, size2); if (size1 && b1) opl_right->generate_samples(b1, size1); if (size2 && b2) opl_right->generate_samples(b2, size2); // Unlock (right) buffer_right->Unlock(); } // Unlock left buffer->Unlock(); } } void FMOpl_Midi::load_patches(bool force_xmidi) { // Lock the mutex SDL_mutexP(mutex); if (opl) opl->LoadMT32Bank(force_xmidi); if (opl_right) opl_right->LoadMT32Bank(force_xmidi); // Unlock the mutex SDL_mutexV(mutex); } bool FMOpl_Midi::is_fm_synth() { return true; } bool FMOpl_Midi::use_gs127() { return true; } // // PSMDEX - Pentagram Streaming Midi Driver Extensions // int FMOpl_Midi::max_streams() { return 1; } void FMOpl_Midi::start_stream(int str_num, XMIDIEventList *eventlist, bool repeat, bool activate, int vol) { stop_track(); set_volume(0, vol); start_track(eventlist, repeat); } void FMOpl_Midi::activate_stream(int str_num) { } void FMOpl_Midi::stop_stream(int str_num) { stop_track(); } void FMOpl_Midi::set_volume(int str_num, int level) { if (!is_available) return; // Lock the mutex SDL_mutexP(mutex); // Set the volume global_volume = level; // Unlock the mutex SDL_mutexV(mutex); } bool FMOpl_Midi::is_playing(int str_num) { return is_playing(); } int FMOpl_Midi::get_active() { return 0; } /* what we need to do play notes and generate 5512 samples delay till we are past the amount of time it should have taken to generate those samples repeat what we will do for now play notes and generate 5513 samples (250ms) delay till we are 250ms ahead play notes and generate 5512 samples (250ms) delay till we are 250ms ahead repeat at audio->get_sample_rate() KHz there are 735 samples for every 4 ticks. at audio->get_sample_rate() KHz there are 147 samples for every 4/5 ticks at audio->get_sample_rate() KHz there are 98 samples for every 8/15 ticks at audio->get_sample_rate() KHz there are 49 samples for every 4/15 ticks The wmo clock 'should' be based on the 98 samples number. For every 98 samples, we increment the clock 15 units. Working out the midi tick is unit/8. The unit from the midi tick is tick*8 I could base it on the 49 samples number too. For every 49 samples we increment the clock 15 units aslso. The midi tick being then is unit/4. The unit from the midi tick is tick*4 The generate samples function: uint32 generate_sample (uint32 count_required) { uint32 amount_generated = 0; while (amount_generated < count_required) { while_event_loop(); get_opls_to_generate_samples(NUM_SAMPLES_PER_PASS); amount_generated += NUM_SAMPLES_PER_PASS; wmoClockIncTime(TIME_PER_PASS); } return amount_generated; } */ #endif //USE_FMOPL_MIDI exult-1.2/audio/midi_drivers/amiga_midi.h0000644000175000001440000000240507463225425014216 /* Copyright (C) 2001 Ruediger Hanke This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_amiga_midi_h_ #define _MIDI_driver_amiga_midi_h_ #if defined( AMIGA ) || defined( __MORPHOS__ ) #include "Midi.h" #include #include class AmigaMIDI : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *,bool repeat); virtual void stop_track(void); virtual bool is_playing(void); virtual const char *copyright(void); AmigaMIDI(); virtual ~AmigaMIDI(); private: bool FileOpen; struct MsgPort *amMsgPort; struct IOMidiRequest *amMidiRequest; }; #endif #endif exult-1.2/audio/midi_drivers/Timidity_binary.cc0000644000175000001440000000454007550423657015442 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef XWIN #ifndef ALPHA_LINUX_CXX # include # include # include # include # include # include #endif #include "fnames.h" using std::cerr; using std::endl; #if HAVE_TIMIDITY_BIN #include "Timidity_binary.h" static Mix_Music *mixermusic; // // Woohoo. This is easy with SDL_mixer! :) // Timidity_binary::Timidity_binary() { //Point to music finish cleanup code Mix_HookMusicFinished(music_complete_callback); } Timidity_binary::~Timidity_binary() { // Stop any current player stop_track(); stop_sfx(); } void Timidity_binary::stop_track(void) { Mix_HaltMusic(); if(mixermusic) { Mix_FreeMusic(mixermusic); mixermusic = NULL; } } //Clean up last track played, freeing memory each time void Timidity_binary::music_complete_callback(void) { if(mixermusic) { Mix_FreeMusic(mixermusic); mixermusic = NULL; } } bool Timidity_binary::is_playing(void) { return Mix_PlayingMusic()!=0; } void Timidity_binary::start_track(XMIDIEventList *event_list,bool repeat) { const char *name = MIDITMPFILE; event_list->Write(name); #if DEBUG cerr << "Starting midi sequence with Timidity_binary" << endl; #endif stop_track(); mixermusic = Mix_LoadMUS(name); Mix_PlayMusic(mixermusic, repeat); Mix_VolumeMusic(MIX_MAX_VOLUME - 50); //Balance volume with other music types } void Timidity_binary::start_sfx(XMIDIEventList *event_list) { } void Timidity_binary::stop_sfx(void) { } const char *Timidity_binary::copyright(void) { return "Internal SDL_mixer timidity synthesiser"; } #endif // HAVE_TIMIDITY_BIN #endif // XWIN exult-1.2/audio/midi_drivers/mixer_midiout.h0000644000175000001440000000236407550423657015024 //-*-Mode: C++;-*- /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MIDI_driver_Mixer_MidiOut_h_ #define _MIDI_driver_Mixer_MidiOut_h_ #include "Midi.h" class Mixer_MidiOut : virtual public MidiAbstract { public: virtual void start_track(XMIDIEventList *, bool repeat); virtual void start_sfx(XMIDIEventList *); virtual void stop_track(void); virtual void stop_sfx(void); virtual bool is_playing(void); virtual const char *copyright(void); static void music_complete_callback(void); Mixer_MidiOut(); virtual ~Mixer_MidiOut(); }; #endif //_MIDI_driver_Mixer_MidiOut_h_ exult-1.2/audio/midi_drivers/win_midiout.cc0000644000175000001440000004232010054030551014603 /* Copyright (C) 2000, 2001, 2002 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif //Windows-specific code #if defined(WIN32) && !defined(UNDER_CE) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif // These will prevent inclusion of mmsystem sections #define MMNODRV // Installable driver support #define MMNOSOUND // Sound support #define MMNOWAVE // Waveform support #define MMNOAUX // Auxiliary audio support #define MMNOMIXER // Mixer support #define MMNOTIMER // Timer support #define MMNOJOY // Joystick support #define MMNOMCI // MCI support #define MMNOMMIO // Multimedia file I/O support #include #include #include #include #include "win_midiout.h" #include "../xmidi.h" #include "../../files/utils.h" #include "../../conf/Configuration.h" extern Configuration *config; #define W32MO_THREAD_COM_READY 0 #define W32MO_THREAD_COM_PLAY 1 #define W32MO_THREAD_COM_STOP 2 #define W32MO_THREAD_COM_INIT 3 #define W32MO_THREAD_COM_INIT_FAILED 4 #define W32MO_THREAD_COM_EXIT -1 const unsigned short Windows_MidiOut::centre_value = 0x2000; const unsigned char Windows_MidiOut::fine_value = centre_value & 127; const unsigned char Windows_MidiOut::coarse_value = centre_value >> 7; const unsigned short Windows_MidiOut::combined_value = (coarse_value << 8) | fine_value; //#define DO_SMP_TEST #ifdef DO_SMP_TEST #define giveinfo() std::cerr << __FILE__ << ":" << __LINE__ << std::endl; std::cerr.flush(); #else #define giveinfo() #endif using std::string; using std::cout; using std::cerr; using std::endl; Windows_MidiOut::Windows_MidiOut() : dev_num(-1) { giveinfo(); InterlockedExchange (&playing, false); InterlockedExchange (&s_playing, false); InterlockedExchange (&is_available, false); giveinfo(); init_device(); giveinfo(); } Windows_MidiOut::~Windows_MidiOut() { giveinfo(); if (!is_available) return; giveinfo(); while (thread_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_EXIT); giveinfo(); int count = 0; giveinfo(); while (count < 100) { giveinfo(); DWORD code; GetExitCodeThread (thread_handle, &code); giveinfo(); // Wait 1 MS before trying again if (code == STILL_ACTIVE) Sleep (1); else break; giveinfo(); count++; } // We waited a second and it still didn't terminate giveinfo(); if (count == 100 && is_available) TerminateThread (thread_handle, 1); giveinfo(); InterlockedExchange (&is_available, false); giveinfo(); } void Windows_MidiOut::init_device() { string s; // Opened, lets open the thread giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT); // Get Win32 Midi Device num config->value("config/audio/midi/win32_device", dev_num, -1); giveinfo(); thread_handle = (HANDLE*) CreateThread (NULL, 0, thread_start, this, 0, &thread_id); giveinfo(); while (thread_com == W32MO_THREAD_COM_INIT) Sleep (1); // Set Win32 Midi Device num config->set("config/audio/midi/win32_device", dev_num, true); giveinfo(); if (thread_com == W32MO_THREAD_COM_INIT_FAILED) cerr << "Failure to initialize midi playing thread" << endl; giveinfo(); } DWORD __stdcall Windows_MidiOut::thread_start(void *data) { giveinfo(); Windows_MidiOut *ptr=static_cast(data); giveinfo(); return ptr->thread_main(); } DWORD Windows_MidiOut::thread_main() { int i; thread_data = NULL; giveinfo(); InterlockedExchange (&playing, false); InterlockedExchange (&s_playing, false); giveinfo(); // List all the midi devices. MIDIOUTCAPS caps; signed long dev_count = (signed long) midiOutGetNumDevs(); std::cout << dev_count << " Midi Devices Detected" << endl; std::cout << "Listing midi devices:" << endl; for (i = -1; i < dev_count; i++) { midiOutGetDevCaps ((UINT) i, &caps, sizeof(caps)); std::cout << i << ": " << caps.szPname << endl; } if (dev_num < -1 || dev_num >= dev_count) { std::cerr << "Warning Midi device in config is out of range." << endl; dev_num = -1; } midiOutGetDevCaps ((UINT) dev_num, &caps, sizeof(caps)); std::cout << "Using device " << dev_num << ": "<< caps.szPname << endl; UINT mmsys_err = midiOutOpen (&midi_port, dev_num, 0, 0, 0); giveinfo(); if (mmsys_err != MMSYSERR_NOERROR) { TCHAR buf[512]; giveinfo(); mciGetErrorString(mmsys_err, buf, 512); #ifdef UNICODE std::wcerr << TEXT("Unable to open device: ") << buf << endl; #else cerr << "Unable to open device: " << buf << endl; #endif giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT_FAILED); giveinfo(); return 1; } giveinfo(); InterlockedExchange (&is_available, true); // SetThreadPriority (thread_handle, THREAD_PRIORITY_HIGHEST); giveinfo(); SetThreadPriority (thread_handle, THREAD_PRIORITY_TIME_CRITICAL); giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY); InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY); giveinfo(); thread_play(); giveinfo(); giveinfo(); midiOutClose (midi_port); giveinfo(); InterlockedExchange (&is_available, false); giveinfo(); return 0; } void Windows_MidiOut::thread_play () { int repeat = false; uint32 aim = 0; sint32 diff = 0; uint32 last_tick = 0; XMIDIEventList *evntlist = NULL; midi_event *event = NULL; NoteStack notes_on; midi_event *note = NULL; // // Xmidi Looping // // The for loop event midi_event *loop_event[XMIDI_MAX_FOR_LOOP_COUNT]; // The amount of times we have left that we can loop int loop_count[XMIDI_MAX_FOR_LOOP_COUNT]; // The level of the loop we are currently in int loop_num = -1; giveinfo(); int s_track = 0; uint32 s_aim = 0; sint32 s_diff = 0; uint32 s_last_tick = 0; NoteStack s_notes_on; XMIDIEventList *s_evntlist = NULL; midi_event *s_event = NULL; giveinfo(); // Play while there isn't a message waiting while (1) { if (thread_com == W32MO_THREAD_COM_EXIT && !playing && !s_playing) break; if (thread_com == W32MO_THREAD_COM_STOP) { giveinfo(); InterlockedExchange (&playing, FALSE); InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY); // Handle note off's here while (note = notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); giveinfo(); // Clean up for (int i = 0; i < 16; i++) reset_channel (i); midiOutReset (midi_port); giveinfo(); if (evntlist) evntlist->DecerementCounter(); giveinfo(); evntlist = NULL; event = NULL; giveinfo(); // If stop was requested, we are ready to receive another song loop_num = -1; wmoInitClock (); last_tick = 0; } // Handle note off's here while (note = notes_on.PopTime(wmoGetRealTime())) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); while (note = s_notes_on.PopTime(wmoGetRealTime())) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); while (event && thread_com != W32MO_THREAD_COM_STOP) { aim = (event->time-last_tick)*50; diff = aim - wmoGetTime (); if (diff > 0) break; last_tick = event->time; wmoAddOffset(aim); // XMIDI For Loop if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_FOR_LOOP) { if (loop_num < XMIDI_MAX_FOR_LOOP_COUNT) loop_num++; loop_count[loop_num] = event->data[1]; loop_event[loop_num] = event; } // XMIDI Next/Break else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_NEXT_BREAK) { if (loop_num != -1) { if (event->data[1] < 64) { loop_num--; } } event = NULL; } // Not SysEx else if (event->status < 0xF0) { int type = event->status >> 4; if ((type != MIDI_STATUS_NOTE_ON || event->data[1]) && type != MIDI_STATUS_NOTE_OFF) { if (type == MIDI_STATUS_NOTE_ON) { notes_on.Remove(event); notes_on.Push (event, event->duration * 50 + wmoGetStart()); } midiOutShortMsg (midi_port, event->status + (event->data[0] << 8) + (event->data[1] << 16)); } } if (event) event = event->next; if (!event || thread_com != W32MO_THREAD_COM_READY) { bool clean = !repeat || (thread_com != W32MO_THREAD_COM_READY) || last_tick == 0; if (clean) { InterlockedExchange (&playing, FALSE); if (thread_com == W32MO_THREAD_COM_STOP) InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY); // Handle note off's here while (note = notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); // Clean up for (int i = 0; i < 16; i++) reset_channel (i); midiOutReset (midi_port); if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; event = NULL; loop_num = -1; wmoInitClock (); } last_tick = 0; if (evntlist) { if (loop_num == -1) event = evntlist->events; else { event = loop_event[loop_num]->next; last_tick = loop_event[loop_num]->time; if (loop_count[loop_num]) if (!--loop_count[loop_num]) loop_num--; } } } } // Got issued a music play command // set up the music playing routine if (thread_com == W32MO_THREAD_COM_PLAY) { // Handle note off's here while (note = notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); // Manual Reset since I don't trust midiOutReset() giveinfo(); for (int i = 0; i < 16; i++) reset_channel (i); midiOutReset (midi_port); if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; event = NULL; InterlockedExchange (&playing, FALSE); // Make sure that the data exists giveinfo(); while (!thread_data) Sleep(1); giveinfo(); evntlist = thread_data->list; repeat = thread_data->repeat; giveinfo(); InterlockedExchange ((LONG*) &thread_data, (LONG) NULL); giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY); giveinfo(); if (evntlist) event = evntlist->events; else event = 0; giveinfo(); last_tick = 0; giveinfo(); wmoInitClock (); // Reset XMIDI Looping loop_num = -1; giveinfo(); InterlockedExchange (&playing, true); } if (s_event) { s_aim = (s_event->time-s_last_tick)*50; s_diff = s_aim - wmoGetSFXTime (); } else s_diff = 1; if (s_diff <= 0) { s_last_tick = s_event->time; wmoAddSFXOffset(s_aim); // Not SysEx if ((s_event->status >> 4) != MIDI_STATUS_SYSEX) { int type = s_event->status >> 4; if ((type != MIDI_STATUS_NOTE_ON || s_event->data[1]) && type != MIDI_STATUS_NOTE_OFF) { if (type == MIDI_STATUS_NOTE_ON) { s_notes_on.Remove(s_event); s_notes_on.Push (s_event, s_event->duration * 50 + wmoGetSFXStart()); } midiOutShortMsg (midi_port, s_event->status + (s_event->data[0] << 8) + (s_event->data[1] << 16)); } s_track |= 1 << (s_event->status & 0xF); } s_event = s_event->next; } if (s_evntlist && (!s_event || thread_com == W32MO_THREAD_COM_EXIT || sfx_com != W32MO_THREAD_COM_READY)) { // Play all the remaining note offs while (note = s_notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); // Also reset the played tracks for (int i = 0; i < 16; i++) if ((s_track >> i)&1) reset_channel (i); s_evntlist->DecerementCounter(); s_evntlist = NULL; s_event = NULL; InterlockedExchange (&s_playing, false); if (sfx_com != W32MO_THREAD_COM_PLAY) InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY); } // Got issued a sound effect play command // set up the sound effect playing routine if (!s_evntlist && sfx_com == W32MO_THREAD_COM_PLAY) { giveinfo(); cout << "Play sfx command" << endl; // Play all the remaining note offs while (note = s_notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); // Make sure that the data exists while (!sfx_data) Sleep(1); giveinfo(); s_evntlist = sfx_data->list; giveinfo(); InterlockedExchange ((LONG*) &sfx_data, (LONG) NULL); InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY); giveinfo(); if (s_evntlist) s_event = s_evntlist->events; else s_event = 0; giveinfo(); s_last_tick = 0; giveinfo(); wmoInitSFXClock (); giveinfo(); InterlockedExchange (&s_playing, true); giveinfo(); // Reset thet track counter s_track = 0; } if (event) { aim = (event->time-last_tick)*50; diff = aim - wmoGetTime (); } else diff = 6; if (s_event) { s_aim = (s_event->time-s_last_tick)*50; s_diff = s_aim - wmoGetSFXTime (); } else s_diff = 6; //std::cout << sfx_com << endl; if (diff > 5 && s_diff > 5) Sleep (1); } // Handle note off's here while (note = notes_on.Pop()) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); // Play all the remaining note offs while (note = s_notes_on.PopTime(wmoGetRealTime())) midiOutShortMsg (midi_port, note->status + (note->data[0] << 8)); if (evntlist) evntlist->DecerementCounter(); evntlist = NULL; if (s_evntlist) s_evntlist->DecerementCounter(); s_evntlist = NULL; for (int i = 0; i < 16; i++) reset_channel (i); midiOutReset (midi_port); } void Windows_MidiOut::reset_channel (int i) { // Pitch Wheel midiOutShortMsg (midi_port, i | (MIDI_STATUS_PITCH_WHEEL << 4) | (combined_value << 8)); // All controllers off midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (121 << 8)); // All notes off midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (123 << 8)); // Bank Select midiOutShortMsg (midi_port, i | (MIDI_STATUS_PROG_CHANGE << 4) | (0 << 8)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (0 << 8)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (32 << 8)); // Modulation Wheel midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (1 << 8) | (coarse_value << 16)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (33 << 8) | (fine_value << 16)); // Volume midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (7 << 8) | (coarse_value << 16)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (39 << 8) | (fine_value << 16)); // Pan midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (8 << 8) | (coarse_value << 16)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (40 << 8) | (fine_value << 16)); // Balance midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (10 << 8) | (coarse_value << 16)); midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (42 << 8) | (fine_value << 16)); // Effects (Reverb) midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (91 << 8)); // Chorus midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (93 << 8)); } void Windows_MidiOut::start_track (XMIDIEventList *xmidi, bool repeat) { giveinfo(); if (!is_available) init_device(); giveinfo(); if (!is_available) return; giveinfo(); while (thread_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); xmidi->IncerementCounter(); data.list = xmidi; data.repeat = repeat; // xmidi->Write("winmidi_out.mid"); giveinfo(); InterlockedExchange ((LONG*) &thread_data, (LONG) &data); giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_PLAY); giveinfo(); } void Windows_MidiOut::start_sfx(XMIDIEventList *xmidi) { giveinfo(); if (!is_available) init_device(); giveinfo(); if (!is_available) return; giveinfo(); while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); xmidi->IncerementCounter(); sdata.list = xmidi; sdata.repeat; giveinfo(); InterlockedExchange ((LONG*) &sfx_data, (LONG) &sdata); giveinfo(); InterlockedExchange (&sfx_com, W32MO_THREAD_COM_PLAY); giveinfo(); } void Windows_MidiOut::stop_track(void) { giveinfo(); if (!is_available) return; giveinfo(); if (!playing) return; giveinfo(); while (thread_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); InterlockedExchange (&thread_com, W32MO_THREAD_COM_STOP); giveinfo(); while (thread_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); } void Windows_MidiOut::stop_sfx(void) { giveinfo(); if (!is_available) return; giveinfo(); if (!s_playing) return; giveinfo(); while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1); giveinfo(); InterlockedExchange (&sfx_com, W32MO_THREAD_COM_STOP); giveinfo(); } bool Windows_MidiOut::is_playing(void) { giveinfo(); return playing!=0; } const char *Windows_MidiOut::copyright(void) { giveinfo(); return "Internal Win32 Midiout Midi Player for Exult and Pentagram."; } #endif exult-1.2/audio/midi_drivers/forked_player.cc0000644000175000001440000000446107724430450015122 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef XWIN #ifndef ALPHA_LINUX_CXX # include #endif #include #include "Configuration.h" #include "exult.h" #include "fnames.h" #include "forked_player.h" #include using std::cerr; using std::endl; // NB: This function doesn't return unless execlp fails! static void playFJmidifile(const char *name) { execlp("playmidi","-v","-v","-e",name,0); } forked_player::forked_player() : forked_job(-1) {} void forked_player::stop_track(void) { if(forked_job!=-1) kill(forked_job,SIGKILL); forked_job=-1; } forked_player::~forked_player(void) { stop_track(); } bool forked_player::is_playing(void) { if(forked_job==-1) return false; if(kill(forked_job,0)) { forked_job=-1; return false; } return true; } void forked_player::start_track(XMIDIEventList *event_list,bool repeat) { static char *name = 0; if (name == 0) { name = new char[19]; strcpy(name, "/tmp/u7midi_XXXXXX"); close(mkstemp(name)); // TODO: delete this file on exit } event_list->Write(name); repeat_=repeat; #if DEBUG cerr << "Starting midi sequence with forked_player" << endl; #endif if(forked_job!=-1) { #if DEBUG cerr << "Stopping any running track" << endl; #endif stop_track(); } forked_job=fork(); if(!forked_job) { playFJmidifile(name); // this doesn't return if it started correctly cerr << "Starting forked player failed" << endl; exit(-1); } } const char *forked_player::copyright(void) { return "Internal cheapass forked midi player"; } #endif // XWIN exult-1.2/audio/Audio.cc0000644000175000001440000006664310054030532010652 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef PENTAGRAM // Exult only at this stage. #include #include //#include "SDL_mapping.h" #include "Audio.h" #include "Configuration.h" #include "Flex.h" #include "conv.h" #include "exult.h" #include "fnames.h" #include "game.h" #include "utils.h" #if !defined(ALPHA_LINUX_CXX) #ifndef UNDER_CE # include #endif # include # include # include # include #endif #ifndef UNDER_CE #include #include #endif #if defined(MACOS) # include #elif !defined(UNDER_CE) # include # include #endif //#include #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::exit; using std::memcpy; using std::memset; using std::string; using std::strncmp; using std::vector; #endif // These MIGHT be macros! #ifndef min using std::min; #endif #ifndef max using std::max; #endif #define TRAILING_VOC_SLOP 32 #define LEADING_VOC_SLOP 32 struct Chunk { size_t length; uint8 *data; Chunk(size_t l, uint8 *d) : length(l),data(d) {} }; static size_t calc_sample_buffer(uint16 _samplerate); static uint8 *chunks_to_block(vector &chunks); static sint16 *resample_new(uint8 *sourcedata, size_t sourcelen, size_t &destlen, int current_rate, int wanted_rate); static sint16 *resample_new_mono(uint8 *sourcedata, size_t sourcelen, size_t &destlen, int current_rate, int wanted_rate); static void resample(uint8 *sourcedata, uint8 **destdata, size_t sourcelen, size_t *destlen, int current_rate, int wanted_rate); static void decode_ADPCM_4(uint8* inBuf, int bufSize, // Size of inbuf uint8* outBuf, // Size is 2x bufsize int& reference, // ADPCM reference value int& scale); Audio *Audio::self = 0; int *Audio::bg2si_sfxs = 0; //----- Utilities ---------------------------------------------------- /* * Class that performs cubic interpolation on integer data. * It is expected that the data is equidistant, i.e. all have the same * horizontal distance. This is obviously the case for sampled audio. */ class CubicInterpolator { protected: int x0, x1, x2, x3; int a, b, c, d; public: CubicInterpolator(int a0, int a1, int a2, int a3) : x0(a0), x1(a1), x2(a2), x3(a3) { updateCoefficients(); } CubicInterpolator(int a1, int a2, int a3) : x0(2*a1-a2), x1(a1), x2(a2), x3(a3) { // We use a simple linear interpolation for x0 updateCoefficients(); } inline void feedData() { x0 = x1; x1 = x2; x2 = x3; x3 = 2*x2-x1; // Simple linear interpolation updateCoefficients(); } inline void feedData(int xNew) { x0 = x1; x1 = x2; x2 = x3; x3 = xNew; updateCoefficients(); } /* t must be a 16.16 fixed point number between 0 and 1 */ inline int interpolate(uint32 fp_pos) { int result = 0; int t = fp_pos >> 8; result = (a*t + b) >> 8; result = (result * t + c) >> 8; result = (result * t + d) >> 8; result = (result/3 + 1) >> 1; return result; } protected: inline void updateCoefficients() { a = ((-x0*2)+(x1*5)-(x2*4)+x3); b = ((x0+x2-(2*x1))*6) << 8; c = ((-4*x0)+x1+(x2*4)-x3) << 8; d = (x1*6) << 8; } }; //----- SFX ---------------------------------------------------------- /* * For caching sound effects: */ class SFX_cached { int num; // Sound-effects #. uint8 *buf; // The data. It's passed in to us, // and then we own it. uint32 len; SFX_cached *next; // Next in chain. public: friend class Audio; SFX_cached(int sn, uint8 *b, uint32 l, SFX_cached *oldhead) : num(sn), /*buf(b), */ len(l), next(oldhead) { buf = new uint8[l]; memcpy(buf, b, l); } ~SFX_cached() { delete [] buf; } }; //---- Audio --------------------------------------------------------- void Audio::Init(void) { // Crate the Audio singleton object if (!self) { self = new Audio(); #ifdef UNDER_CE self->Init(SAMPLERATE/2,1); #else self->Init(SAMPLERATE,2); #endif } } void Audio::Destroy(void) { delete self; self = 0; } Audio *Audio::get_ptr(void) { // The following assert here might be too harsh, maybe we should leave // it to the caller to handle non-inited audio-system? assert(self != NULL); return self; } Audio::Audio() : truthful_(false),speech_enabled(true), music_enabled(true), effects_enabled(true), SDL_open(false),/*mixer(0),*/midi(0), sfxs(0), sfx_file(0), initialized(false) { assert(self == NULL); string s; config->value("config/audio/enabled",s,"yes"); audio_enabled = (s!="no"); config->set("config/audio/enabled", audio_enabled?"yes":"no",true); config->value("config/audio/speech/enabled",s,"yes"); speech_enabled = (s!="no"); config->value("config/audio/midi/enabled",s,"---"); music_enabled = (s!="no"); config->value("config/audio/effects/enabled",s,"---"); effects_enabled = (s!="no"); config->value("config/audio/midi/looping",s,"yes"); allow_music_looping = (s!="no"); midi = 0; } void Audio::Init(int _samplerate,int _channels) { if (!audio_enabled) return; // Initialise the speech vectors uint32 _buffering_unit=calc_sample_buffer(_samplerate); build_speech_vector(); delete midi; midi=0; // Avoid closing SDL audio. This seems to trigger a segfault if(SDL_open) SDL_QuitSubSystem(SDL_INIT_AUDIO); // Init the SDL audio system SDL_InitSubSystem(SDL_INIT_AUDIO); /* Open the audio device, forcing the desired format */ if ( Mix_OpenAudio(_samplerate, AUDIO_S16SYS, _channels, _buffering_unit) < 0 ) { cerr << "Couldn't open audio: " << Mix_GetError() << endl; audio_enabled = false; // Prevent crashes. return; } int art_freq; Uint16 art_format; int art_channels; Mix_QuerySpec(&art_freq,&art_format,&art_channels); actual.freq = art_freq; actual.format = art_format; actual.channels = art_channels; #ifdef DEBUG cout << "Audio requested frequency " << _samplerate << ", channels " << _channels << endl; cout << "Audio actual frequency " << actual.freq << ", channels " << (int) actual.channels << endl; #endif //SDL_mixer will always go here when it has played a sound, we want to free up //the memory used as we don't re-play the sound. Mix_ChannelFinished(channel_complete_callback); // Disable playing initially. Mix_Pause(-1); SDL_open=true; midi=new MyMidiPlayer(); COUT("Audio initialisation OK"); initialized = true; } //Free up memory used by the just played WAV. We only ever play a sound //once and discard it. void Audio::channel_complete_callback(int chan) { Mix_Chunk *done_chunk = Mix_GetChunk(chan); Uint8 *chunkbuf=NULL; //We need to free these chunks as they were allocated by us and not SDL_Mixer //This happens when Mix_QuickLoadRAW is used. if(done_chunk->allocated == 0) chunkbuf = done_chunk->abuf; Mix_FreeChunk(done_chunk); //Must be freed after the Mix_FreeChunk if(chunkbuf) delete[] chunkbuf; } bool Audio::can_sfx(const std::string &game) const { string s; string d = "config/disk/game/" + game + "/waves"; config->value(d.c_str(), s, "---"); if (s != "---" && U7exists(s.c_str())) return true; // Also just check in the actual data dir d = "/" + s; if (U7exists(d.c_str())) return true; #ifdef ENABLE_MIDISFX if (U7exists("/midisfx.flx")) return true; #endif return false; } void Audio::Init_sfx() { if (sfx_file) delete sfx_file; if (Game::get_game_type() == SERPENT_ISLE) bg2si_sfxs = bgconv; else bg2si_sfxs = 0; // Collection of .wav's? string s; string d = "config/disk/game/" + Game::get_gametitle() + "/waves"; config->value(d.c_str(), s, "---"); if (s != "---") { if (!U7exists(s.c_str())) { d = "/" + s; if (!U7exists(d.c_str())) { cerr << "Digital SFX's file specified: " << s << "... but file not found" << endl; return; } } else d = s; sfx_file = new Flex(d); } } Audio::~Audio() { if (!initialized) { self = 0; SDL_open = false; return; } CERR("~Audio: about to stop_music()"); stop_music(); CERR("~Audio: about to quit subsystem"); SDL_QuitSubSystem(SDL_INIT_AUDIO); // SDL 1.1 lets us diddle with // subsystems CERR("~Audio: closed audio"); if(midi) { delete midi; midi = 0; } while (sfxs) // Cached sound effects. { SFX_cached *todel = sfxs; sfxs = todel->next; delete todel; } delete sfx_file; CERR("~Audio: deleted midi"); // Avoid closing SDL audio. This seems to trigger a segfault // SDL::CloseAudio(); SDL_open = false; self = 0; } uint8 *Audio::convert_VOC(uint8 *old_data,uint32 &visible_len) { vector chunks; size_t data_offset=0x1a; bool last_chunk=false; uint16 sample_rate; size_t l = 0; size_t chunk_length; int compression = 0; int adpcm_reference = -1; int adpcm_scale = 0; while(!last_chunk) { switch(old_data[data_offset]&0xff) { case 0: COUT("Terminator"); last_chunk = true; continue; case 1: COUT("Sound data"); l = (old_data[3+data_offset]&0xff)<<16; l |= (old_data[2+data_offset]&0xff)<<8; l |= (old_data[1+data_offset]&0xff); COUT("Chunk length appears to be " << l); sample_rate=1000000/(256-(old_data[4+data_offset]&0xff)); #ifdef FUDGE_SAMPLE_RATES if (sample_rate == 11111) sample_rate = 11025; else if (sample_rate == 22222) sample_rate = 22050; #endif COUT("Original sample_rate is " << sample_rate << ", hw rate is " << actual.freq); COUT("Sample rate ("<< sample_rate<<") = _real_rate"); compression = old_data[5+data_offset]&0xff; COUT("compression type " << compression); if (compression) { adpcm_reference = -1; adpcm_scale = 0; } COUT("Channels " << (old_data[6+data_offset]&0xff)); chunk_length=l+4; //workaround here to exit this loop, it fixes start speech which was //causing this function to go exit too early. last_chunk=true; break; case 2: COUT("Sound continues"); l=(old_data[3+data_offset]&0xff)<<16; l|=(old_data[2+data_offset]&0xff)<<8; l|=(old_data[1+data_offset]&0xff); COUT("Chunk length appears to be " << l); chunk_length = l+4; break; case 3: COUT("Silence"); chunk_length=0; break; case 5: // A null terminated string COUT("Text string chunk"); chunk_length=0; break; default: cerr << "Unknown VOC chunk " << (*(old_data+data_offset)&0xff) << endl; throw exult_exception("Unknown VOC chunk"); } if(chunk_length==0) break; l -= (TRAILING_VOC_SLOP+LEADING_VOC_SLOP); // uint8 *dec_data = old_data+LEADING_VOC_SLOP; size_t dec_len = l; // Decompress data if (compression == 1) { // Allocate temp buffer if (adpcm_reference == -1) dec_len = (dec_len-1)*2; else dec_len *= 2; dec_data = new uint8[dec_len]; decode_ADPCM_4(old_data+LEADING_VOC_SLOP, l, dec_data, adpcm_reference, adpcm_scale); } else if (compression != 0) { CERR("Can't handle VOC compression type"); } // Our input is 8 bit mono unsigned; but want to output 16 bit stereo signed. // In addition, the rates don't match, we have to upsample. #if 1 // New code: Do it all in one step with cubic interpolation sint16 *stereo_data; if (is_stereo()) stereo_data = resample_new(dec_data, dec_len, l, sample_rate, actual.freq); else stereo_data = resample_new_mono(dec_data, dec_len, l, sample_rate, actual.freq); #else // Old code: resample using pseudo-breshenham, then in a second step convert // to 16 bit stereo. // Resample to the current rate uint8 *new_data; size_t new_len; resample(dec_data, &new_data, dec_len, &new_len, sample_rate, actual.freq); l = new_len; COUT("Have " << l << " bytes of resampled data"); // And convert to 16 bit stereo sint16 *stereo_data = new sint16[l*2]; for(size_t i = 0, j = 0; i < l; i++) { stereo_data[j++] = (new_data[i] - 128)<<8; stereo_data[j++] = (new_data[i] - 128)<<8; } l <<= 2; // because it's 16bit delete [] new_data; #endif // Delete temp buffer if (compression == 1) { delete [] dec_data; } chunks.push_back(Chunk(l,(uint8 *)stereo_data)); data_offset += chunk_length; } COUT("Turn chunks to block"); visible_len = l; return chunks_to_block(chunks); } static sint16 *resample_new(uint8 *src, size_t sourcelen, size_t &size, int rate, int wanted_rate) { int fp_pos = 0; int fp_speed = (1 << 16) * rate / wanted_rate; size = sourcelen; // adjust the magnitudes of size and rate to prevent division error while (size & 0xFFFF0000) size >>= 1, rate = (rate >> 1) + 1; // Compute the output size (times 4 since it is 16 stereo) size = (size * wanted_rate / rate) << 2; sint16 *stereo_data = new sint16 [size]; sint16 *data = stereo_data; uint8 *src_end = src + sourcelen; int result; // Compute the initial data feed for the interpolator. We don't simply // shift by 8, but rather duplicate the byte, this way we cover the full // range. Probably doesn't make a big difference, listening wise :-) int a = *(src+0); a = (a|(a << 8))-32768; int b = *(src+1); b = (a|(b << 8))-32768; int c = *(src+2); c = (a|(c << 8))-32768; // We divide the data by 2, to prevent overshots. Imagine this sample pattern: // 0, 65535, 65535, 0. Now you want to compute a value between the two 65535. // Obviously, it will be *bigger* than 65535 (it can get to about 80,000). // It is possibly to clamp it, but that leads to a distored wave form. Compare // this to turning up the volume of your stereo to much, it will start to sound // bad at a certain level (depending on the power of your stereo, your speakers // etc, this can be quite loud, though ;-). Hence we reduce the original range. // A factor of roughly 1/1.2 = 0.8333 is sufficient. Since we want to avoid // floating point, we approximate that by 27/32 #define RANGE_REDUX(x) (((x) * 27) >> 5) // #define RANGE_REDUX(x) ((x) >> 1) // #define RANGE_REDUX(x) ((x) / 1.2) CubicInterpolator interp(RANGE_REDUX(a), RANGE_REDUX(b), RANGE_REDUX(c)); do { do { // Convert to signed data result = interp.interpolate(fp_pos); // Enforce range in case of an "overshot". Shouldn't happen since we // scale down already, but safe is safe. if (result < -32768) result = -32768; else if (result > 32767) result = 32767; *data++ = result; *data++ = result; fp_pos += fp_speed; } while (!(fp_pos & 0xFFFF0000)); src++; fp_pos &= 0x0000FFFF; if (src+2 < src_end) { c = *(src+2); c = (c|(c << 8))-32768; interp.feedData(RANGE_REDUX(c)); } else interp.feedData(); } while (src < src_end); return stereo_data; } static sint16 *resample_new_mono(uint8 *src, size_t sourcelen, size_t &size, int rate, int wanted_rate) { int fp_pos = 0; int fp_speed = (1 << 16) * rate / wanted_rate; size = sourcelen; // adjust the magnitudes of size and rate to prevent division error while (size & 0xFFFF0000) size >>= 1, rate = (rate >> 1) + 1; // Compute the output size (times 2 since it is 16 stereo) size = (size * wanted_rate / rate) << 1; sint16 *stereo_data = new sint16 [size]; sint16 *data = stereo_data; uint8 *src_end = src + sourcelen; int result; // Compute the initial data feed for the interpolator. We don't simply // shift by 8, but rather duplicate the byte, this way we cover the full // range. Probably doesn't make a big difference, listening wise :-) int a = *(src+0); a = (a|(a << 8))-32768; int b = *(src+1); b = (a|(b << 8))-32768; int c = *(src+2); c = (a|(c << 8))-32768; // We divide the data by 2, to prevent overshots. Imagine this sample pattern: // 0, 65535, 65535, 0. Now you want to compute a value between the two 65535. // Obviously, it will be *bigger* than 65535 (it can get to about 80,000). // It is possibly to clamp it, but that leads to a distored wave form. Compare // this to turning up the volume of your stereo to much, it will start to sound // bad at a certain level (depending on the power of your stereo, your speakers // etc, this can be quite loud, though ;-). Hence we reduce the original range. // A factor of roughly 1/1.2 = 0.8333 is sufficient. Since we want to avoid // floating point, we approximate that by 27/32 #define RANGE_REDUX(x) (((x) * 27) >> 5) // #define RANGE_REDUX(x) ((x) >> 1) // #define RANGE_REDUX(x) ((x) / 1.2) CubicInterpolator interp(RANGE_REDUX(a), RANGE_REDUX(b), RANGE_REDUX(c)); do { do { // Convert to signed data result = interp.interpolate(fp_pos); // Enforce range in case of an "overshot". Shouldn't happen since we // scale down already, but safe is safe. if (result < -32768) result = -32768; else if (result > 32767) result = 32767; *data++ = result; fp_pos += fp_speed; } while (!(fp_pos & 0xFFFF0000)); src++; fp_pos &= 0x0000FFFF; if (src+2 < src_end) { c = *(src+2); c = (c|(c << 8))-32768; interp.feedData(RANGE_REDUX(c)); } else interp.feedData(); } while (src < src_end); return stereo_data; } void Audio::play(uint8 *sound_data,uint32 len,bool wait) { Mix_Chunk *wavechunk; if (!audio_enabled || !speech_enabled) return; bool own_audio_data=false; if(!strncmp((const char *)sound_data,"Creative Voice File",19)) { sound_data=convert_VOC(sound_data,len); own_audio_data=true; } //Play voice sample using RAW sample we created above. ConvertVOC() produced a stereo, 22KHz, 16bit //sample. Currently SDL does not resample very well so we do it in ConvertVOC() wavechunk = Mix_QuickLoad_RAW(sound_data, len); int channel; channel = Mix_PlayChannel(-1, wavechunk, 0); Mix_SetPosition(channel, 0, 0); Mix_Volume(channel, MIX_MAX_VOLUME - 40); //Voice is loud compared to other SFX,music //so adjust to match volumes } void Audio::cancel_streams(void) { if (!audio_enabled) return; Mix_HaltChannel(-1); } void Audio::pause_audio(void) { if (!audio_enabled) return; Mix_Pause(-1); Mix_PauseMusic(); } void Audio::resume_audio(void) { if (!audio_enabled) return; Mix_Resume(-1); Mix_ResumeMusic(); } void Audio::playfile(const char *fname,bool wait) { if (!audio_enabled) return; FILE *fp; size_t len; uint8 *buf; fp = U7open(fname,"r"); // DARKE FIXME if(!fp) { perror(fname); return; } fseek(fp,0L,SEEK_END); len=ftell(fp); fseek(fp,0L,SEEK_SET); if(len<=0) { perror("seek"); fclose(fp); return; } buf=new uint8[len]; fread(buf,len,1,fp); fclose(fp); play(buf,len,wait); delete [] buf; } bool Audio::playing(void) { return false; } void Audio::start_music(int num, bool continuous, int bank) { if(audio_enabled && music_enabled && midi != 0) midi->start_music(num,continuous && allow_music_looping,bank); } void Audio::start_music(const char *fname, int num, bool continuous) { if(audio_enabled && music_enabled && midi != 0) midi->start_music(fname,num,continuous && allow_music_looping); } void Audio::start_music(XMIDIEventList *mid_file,bool continuous) { if(audio_enabled && music_enabled && midi != 0) midi->start_track(mid_file,continuous && allow_music_looping); } void Audio::start_music_combat (Combat_song song, bool continuous, int bank) { if(!audio_enabled || !music_enabled || midi == 0) return; int num = -1; if (Game::get_game_type()!=SERPENT_ISLE) switch (song) { case CSBattle_Over: num = 9; break; case CSAttacked1: num = 11; break; case CSAttacked2: num = 12; break; case CSVictory: num = 15; break; case CSRun_Away: num = 16; break; case CSDanger: num = 10; break; case CSHidden_Danger: num = 18; break; default: CERR("Error: Unable to Find combat track for song " << song << "."); break; } else switch (song) { case CSBattle_Over: num = 0; break; case CSAttacked1: num = 2; break; case CSAttacked2: num = 3; break; case CSVictory: num = 6; break; case CSRun_Away: num = 7; break; case CSDanger: num = 1; break; case CSHidden_Danger: num = 9; break; default: CERR("Error: Unable to Find combat track for song " << song << "."); break; } midi->start_music(num,continuous && allow_music_looping,bank); } void Audio::stop_music() { if (!audio_enabled) return; if(midi) midi->stop_music(); } bool Audio::start_speech(int num,bool wait) { if (!audio_enabled || !speech_enabled) return false; char *buf=0; size_t len; const char *filename; if (Game::get_game_type() == SERPENT_ISLE) filename = SISPEECH; else filename = U7SPEECH; U7object sample(filename,num); try { buf = sample.retrieve(len); } catch( const std::exception & err ) { return false; } play(reinterpret_cast(buf),len,wait); delete [] buf; return true; } void Audio::build_speech_vector(void) { } /* * This returns a 'unique' ID, but only for .wav SFX's (for now). */ int Audio::play_sound_effect (int num, int volume, int dir, int repeat) { if (!audio_enabled || !effects_enabled) return -1; // Where sort of sfx are we using???? if (sfx_file != 0) // Digital .wav's? return play_wave_sfx(num, volume, dir, repeat); #ifdef ENABLE_MIDISFX else if (midi != 0) midi->start_sound_effect(num); #endif return -1; } /* * Play a .wav format sound effect, * return the channel number playing on or -1 if not playing, (0 is a valid channel in SDL_Mixer!) */ int Audio::play_wave_sfx ( int num, int volume, // 0-128. int dir, // 0-15, from North, clockwise. int repeat // Keep playing. ) { if (!effects_enabled || !sfx_file /*|| !mixer*/) return -1; // no .wav sfx available CERR("Playing SFX: " << num); #if 0 if (Game::get_game_type() == BLACK_GATE) num = bgconv[num]; CERR("; after bgconv: " << num); #endif if (num < 0 || num >= sfx_file->number_of_objects()) { cerr << "SFX " << num << " is out of range" << endl; return -1; } const int max_cached = 6; // Max. we'll cache. SFX_cached *each = sfxs, *prev = 0; int cnt = 0; size_t wavlen; // Read .wav file. SDL_RWops *rwsrc; bool foundcache=false; unsigned char *wavbuf; // First see if we have it already in our cache while (each && each->num != num && each->next) { cnt++; prev = each; each = each->next; } if (each && each->num == num) // Found it? { // Move to head of chain. if (prev) { prev->next = each->next; each->next = sfxs; sfxs = each; } // Return the cached data foundcache = true; wavbuf = new uint8[each->len]; memcpy(wavbuf, each->buf, each->len); wavlen = each->len; } if (cnt == max_cached && !foundcache) // Hit our limit? Remove last. { prev->next = 0; delete each; } // Retrieve the .wav data from the SFX file if(!foundcache) { wavbuf = (unsigned char *) sfx_file->retrieve(num, wavlen); rwsrc = SDL_RWFromMem(wavbuf, wavlen); wave = Mix_LoadWAV_RW(rwsrc, 1); if (!wave) { cerr << "SFX " << num << " is an invalid wave. "; } else { sfxs = new SFX_cached(num, wave->abuf, wave->alen, sfxs); } delete [] wavbuf; } else { wave = Mix_QuickLoad_RAW(wavbuf, wavlen); //Wavbuf will be deleted by the channel_complete_callback function } if (!wave) { cerr << "Couldn't play sfx '" << num << "'" << endl; return -1; } int sfxchannel; sfxchannel = Mix_PlayChannel(-1, wave, repeat); Mix_Volume(sfxchannel, volume); Mix_SetPosition(sfxchannel, (dir * 22), 0); return sfxchannel; } /* * Halt sound effects. */ void Audio::stop_sound_effects() { if (sfx_file != 0) // .Wav's? Mix_HaltChannel(-1); #ifdef ENABLE_MIDISFX else if (midi) midi->stop_sound_effects(); #endif } void Audio::set_audio_enabled(bool ena) { if (ena && audio_enabled && initialized) { } else if (!ena && audio_enabled && initialized) { stop_sound_effects(); stop_music(); audio_enabled = false; } else if (ena && !audio_enabled && initialized) { audio_enabled = true; } else if (!ena && !audio_enabled && initialized) { } else if (ena && !audio_enabled && !initialized) { audio_enabled = true; Init(SAMPLERATE,2); } else if (!ena && !audio_enabled && !initialized) { } } static size_t calc_sample_buffer(uint16 _samplerate) { uint32 _buffering_unit=1; while(_buffering_unit<_samplerate/10U) _buffering_unit<<=1; // _buffering_unit=128; return _buffering_unit; } static uint8 *chunks_to_block(vector &chunks) { uint8 *unified_block; size_t aggregate_length=0; size_t working_offset=0; for(std::vector::iterator it=chunks.begin(); it!=chunks.end(); ++it) { aggregate_length+=it->length; } unified_block=new uint8[aggregate_length]; { for(std::vector::iterator it=chunks.begin(); it!=chunks.end(); ++it) { memcpy(unified_block+working_offset,it->data,it->length); working_offset+=it->length; delete [] it->data; it->data=0; it->length=0; } } return unified_block; } static void resample(uint8 *sourcedata, uint8 **destdata, size_t sourcelen, size_t *destlen, int current_rate, int wanted_rate) { // I have no idea what I'm doing here - Dancer // This is really Breshenham's line-drawing algorithm in // a false nose, and clutching a crude smoothing loop. float ratio= (static_cast(wanted_rate))/(static_cast(current_rate)); *destlen = static_cast ((sourcelen*ratio)+1); if(!*destlen||current_rate==wanted_rate) { // Least work *destlen=sourcelen; *destdata=new uint8[sourcelen]; memcpy(*destdata,sourcedata,sourcelen); return; } *destdata=new uint8[*destlen]; size_t last=0; for(size_t i=0;i> 4, reference, scale); outBuf[i * 2 + 1] = decode_ADPCM_4_sample(inBuf[i] >> 0, reference, scale); } } #endif // PENTAGRAM exult-1.2/audio/Midi.cc0000644000175000001440000003710410054030550010461 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX #ifndef UNDER_CE # include #endif # include #endif #include #include "fnames.h" #include "exult.h" #include "game.h" #include "Audio.h" #include "../files/U7file.h" #include "../files/utils.h" #include "Midi.h" #include "xmidi.h" #include "conv.h" #include "convmusic.h" #include "../conf/Configuration.h" extern Configuration *config; #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::string; using std::strcpy; #endif static Mix_Music *oggmusic; void MyMidiPlayer::start_track(int num,bool repeat,int bank) { if (!midi_device && !init_device()) return; #ifdef DEBUG cout << "Audio subsystem request: Music track # " << num << endl; #endif // -1 and 255 are stop tracks if (num == -1 || num == 255) { stop_music(); return; } current_track = num; repeating = repeat; if (output_driver_type == MIDI_DRIVER_OGG) { char filename[255] ; string s; //Free previous music, may not have been properly stopped if(oggmusic) { Mix_FreeMusic(oggmusic); oggmusic = NULL; } if(Game::get_game_type()==SERPENT_ISLE) { if(bank == 2 && num == 28) //Convert title track number only in SI num = 70; s = midi_bank[bank]; to_uppercase(s); if((num == 30 || num == 32) && s.find("MAINSHP") != std::string::npos) { //Convert credit/quote tracks if(num == 30) s = "endcr01.ogg"; else s = "endcr02.ogg"; } else { s = bgconvmusic[num]; s = s + ".ogg"; } s = get_system_path("/" + s); strcpy(filename, s.c_str()); } else { char outputstr[255]; s = midi_bank[bank]; to_uppercase(s); if((num == 4 || num == 5) && s.find("INTRORDM") != std::string::npos) { //Convert credit/quotes tracks if(num == 4) s = "endcr01.ogg"; else s = "endcr02.ogg"; } else s = "%02dbg.ogg"; s = get_system_path("/" + s); strcpy(outputstr, s.c_str()); sprintf(filename, outputstr, num); } if(num == 99) //Play the Exult theme tune { s = get_system_path("/exult.ogg"); strcpy(filename, s.c_str()); } if(repeat) repeat = 2; //Convert repeats to repeat 2 times only oggmusic = Mix_LoadMUS(filename); if (!oggmusic) { cout << "Error playing " << filename << ": " << Mix_GetError() << std::endl; } Mix_PlayMusic(oggmusic, repeat); Mix_VolumeMusic(MIX_MAX_VOLUME); #ifdef DEBUG cout << "OGG audio: Music track " << filename << endl; #endif return; //We don't want to continue with Midi conversions!! } // Bank 0 is mainmus, but it's for mt32. If our hardware is an fm synth, // use the fmsynth music, which is bank 3 if (bank == 0 && midi_device->is_fm_synth()) bank = 3; // Bank 1 is BG menu/intro. We need Bank 4 else if (bank == 1 && midi_device->is_fm_synth()) bank = 4; // Bank 2 is SI menu/intro. We need to offset -1 else if (bank == 2 && midi_device->is_fm_synth()) num--; U7object track(midi_bank[bank].c_str(),num); char *buffer; size_t size; DataSource *mid_data; try { buffer = track.retrieve(size); } catch( const std::exception & /*err*/ ) { return; } // Read the data into the XMIDI class mid_data = new BufferDataSource(buffer, size); // Play with the conversion type for the FMSynth or MT32EMU drivers int conv = music_conversion; if (midi_device->use_gs127()) //if (midi_device->is_fmsynth()) conv = XMIDI_CONVERT_MT32_TO_GS127; //else if (midi_device->is_mt32()) //conv = XMIDI_CONVERT_NOCONVERSION; XMIDI midfile(mid_data, conv); delete mid_data; delete [] buffer; // Now give the xmidi object to the midi device XMIDIEventList *eventlist = midfile.GetEventList(0); if (eventlist) midi_device->start_track(eventlist, repeat); } void MyMidiPlayer::start_track(const char *fname,int num,bool repeat) { if (!fname || (!midi_device && !init_device())) return; current_track = -1; repeating = repeat; #ifdef DEBUG cout << "Audio subsystem request: Music track # " << num << " in file "<< fname << endl; #endif // -1 and 255 are stop tracks if (num == -1 || num == 255) { midi_device->stop_track(); return; } //Only called from the endgame sequences if (output_driver_type == MIDI_DRIVER_OGG) { char filename[255] ; //Free previous music, may not have been properly stopped if(oggmusic) { Mix_FreeMusic(oggmusic); oggmusic = NULL; } string s = fname; to_uppercase(s); if(s.find("ENDSCORE") != std::string::npos && Game::get_game_type()!=SERPENT_ISLE) { sprintf(filename, "end%02dbg.ogg", num); } else if(s.find("R_SINTRO") != std::string::npos && Game::get_game_type()==SERPENT_ISLE) strcpy(filename, "si01.ogg"); //SI introduction sequence else if(s.find("R_SEND") != std::string::npos && Game::get_game_type()==SERPENT_ISLE) strcpy(filename, "si13.ogg"); //SI end sequence else return; string s2 = filename; s2 = get_system_path("/" + s2); strcpy(filename, s2.c_str()); oggmusic = Mix_LoadMUS(filename); Mix_PlayMusic(oggmusic, repeat); Mix_VolumeMusic(MIX_MAX_VOLUME); return; //We don't want to continue with Midi conversions!! } FILE *mid_file; DataSource *mid_data; // Read the data into the XMIDI class mid_file = U7open(fname, "rb"); //DARKE FIXME mid_data = new FileDataSource(mid_file); // Play with the conversion type for the FMSynth or MT32EMU drivers int conv = music_conversion; if (midi_device->use_gs127()) //if (midi_device->is_fmsynth()) conv = XMIDI_CONVERT_MT32_TO_GS127; //else if (midi_device->is_mt32()) //conv = XMIDI_CONVERT_NOCONVERSION; XMIDI midfile(mid_data, conv); delete mid_data; fclose(mid_file); // Now give the xmidi object to the midi device XMIDIEventList *eventlist = midfile.GetEventList(num); if (eventlist) midi_device->start_track(eventlist, repeat); } void MyMidiPlayer::start_track(XMIDIEventList *midfile, bool repeat) { #ifdef DEBUG cout << "Audio subsystem request: Custom Music track" << endl; #endif if (!midi_device && !init_device()) return; // Now give the xmidi object to the midi device midi_device->start_track(midfile, repeat); } void MyMidiPlayer::start_music(int num,bool repeat,int bank) { if(!midi_device && !init_device()) return; if(current_track==num&&midi_device->is_playing()) return; // Already playing it if(num == 0 && bank == 0 && Game::get_game_type() == BLACK_GATE) return; //Gets around Usecode bug where track 0 is played at Intro Earthquake start_track(num,repeat,bank); } void MyMidiPlayer::start_music(const char *fname,int num,bool repeat) { if(!fname || (!midi_device && !init_device())) return; start_track(fname,num,repeat); } void MyMidiPlayer::stop_music() { if(!midi_device && !init_device()) return; current_track = -1; repeating = false; midi_device->stop_track(); } bool MyMidiPlayer::add_midi_bank(const char *bankname) { string bank(bankname); midi_bank.push_back(bank); return true; } #if HAVE_TIMIDITY_BIN #include "midi_drivers/Timidity_binary.h" #endif #if HAVE_LIBKMIDI #include "midi_drivers/KMIDI.h" #endif #if !defined(MACOS) && !defined(WIN32) #include "midi_drivers/forked_player.h" #endif #ifdef USE_FMOPL_MIDI #include "midi_drivers/fmopl_midi.h" #endif #ifdef WIN32 #include "midi_drivers/win_midiout.h" #endif #ifdef BEOS #include "midi_drivers/be_midi.h" #endif #if defined(MACOS) || defined(MACOSX) #include "midi_drivers/mac_midi.h" #endif #if defined( __MORPHOS__ ) || defined( AMIGA ) #include "midi_drivers/amiga_midi.h" #endif #define TRY_MIDI_DRIVER(CLASS_NAME) do { \ if(no_device) { \ try { \ midi_device=new CLASS_NAME(); \ no_device=false; \ cout << "Music player: " << midi_device->copyright() << endl; \ } catch(...) { \ no_device=true; \ } \ } \ } while(0) void MyMidiPlayer::set_music_conversion(int conv) { music_conversion = conv; switch(music_conversion) { case XMIDI_CONVERT_MT32_TO_GS: config->set("config/audio/midi/convert","gs",true); break; case XMIDI_CONVERT_NOCONVERSION: config->set("config/audio/midi/convert","none",true); break; case XMIDI_CONVERT_MT32_TO_GS127: config->set("config/audio/midi/convert","gs127",true); break; default: config->set("config/audio/midi/convert","gm",true); break; } } void MyMidiPlayer::set_effects_conversion(int conv) { effects_conversion = conv; switch(effects_conversion) { case XMIDI_CONVERT_NOCONVERSION: config->set("config/audio/effects/convert","none",true); break; default: config->set("config/audio/effects/convert","gs",true); break; } } void MyMidiPlayer::set_output_driver_type(int type) { // Don't kill the device if we don't need to if (type != output_driver_type) { stop_music(); delete midi_device; midi_device = 0; initialized = false; } output_driver_type = type; switch(output_driver_type) { case MIDI_DRIVER_OGG: config->set("config/audio/midi/driver","digital",true); break; #ifdef USE_FMOPL_MIDI case MIDI_DRIVER_FMSYNTH: config->set("config/audio/midi/driver","fmsynth",true); break; #endif #ifdef USE_MT32EMU_MIDI case MIDI_DRIVER_MT32EMU: config->set("config/audio/midi/driver","mt32emu",true); break; #endif default: config->set("config/audio/midi/driver","normal",true); break; }; } bool MyMidiPlayer::init_device(void) { // already initialized? Do this first if (initialized) return (midi_device != 0); bool no_device=true; // instrument_patches=AccessTableFile(XMIDI_MT); string s; bool sfx = Audio::get_ptr()->are_effects_enabled(); if (!sfx) s = "no"; else s = "yes"; config->set("config/audio/effects/enabled",s,true); bool music = Audio::get_ptr()->is_music_enabled(); if (!music) s = "no"; else s = "yes"; // Global Midi Enable/Disable config->set("config/audio/midi/enabled",s,true); // String for default value for driver type std::string driver_default = "normal"; // Music conversion config->value("config/audio/midi/convert",s,"gm"); if (s == "gs") music_conversion = XMIDI_CONVERT_MT32_TO_GS; else if (s == "none") music_conversion = XMIDI_CONVERT_NOCONVERSION; else if (s == "gs127") music_conversion = XMIDI_CONVERT_MT32_TO_GS127; else if (s == "gs127drum") { music_conversion = XMIDI_CONVERT_MT32_TO_GS; config->set("config/audio/midi/convert","gs",true); } else { music_conversion = XMIDI_CONVERT_MT32_TO_GM; config->set("config/audio/midi/convert","gm",true); driver_default = s; } // Effects conversion config->value("config/audio/effects/convert",s,"gs"); if (s == "none") effects_conversion = XMIDI_CONVERT_NOCONVERSION; else if (s == "gs127") effects_conversion = XMIDI_CONVERT_NOCONVERSION; else { effects_conversion = XMIDI_CONVERT_GS127_TO_GS; config->set("config/audio/effects/convert","gs",true); } // Midi driver type. config->value("config/audio/midi/driver",s,driver_default.c_str()); if (s == "digital") { output_driver_type = MIDI_DRIVER_OGG; config->set("config/audio/effects/driver","digital",true); } #ifdef USE_FMOPL_MIDI else if (s == "fmsynth") { output_driver_type = MIDI_DRIVER_FMSYNTH; config->set("config/audio/effects/driver","fmsynth",true); } #endif #ifdef USE_MT32EMU_MIDI else if (s == "mt32emu") { output_driver_type = MIDI_DRIVER_MT32EMU; } #endif else { output_driver_type = MIDI_DRIVER_NORMAL; config->set("config/audio/effects/driver","normal",true); } // no need for a MIDI device (for now) if (!sfx && !music) { midi_device = 0; return false; } // OGG is handled differently to the other MIDI devices, due to it // not actually being a midi device. There are hacks all over the place // for it. The OGG_MIDI driver does do some 'stuff', such as init if (output_driver_type == MIDI_DRIVER_OGG) TRY_MIDI_DRIVER(OGG_MIDI); #ifdef USE_FMOPL_MIDI else if (output_driver_type == MIDI_DRIVER_FMSYNTH) TRY_MIDI_DRIVER(FMOpl_Midi); #endif #if defined(WIN32) && !defined(UNDER_CE) TRY_MIDI_DRIVER(Windows_MidiOut); #endif #ifdef BEOS TRY_MIDI_DRIVER(Be_midi); #endif #if defined(HAVE_TIMIDITY_BIN) && (defined(XWIN) || defined(WIN32)) TRY_MIDI_DRIVER(Timidity_binary); #endif #if HAVE_LIBKMIDI TRY_MIDI_DRIVER(KMIDI); #endif #if (defined(XWIN) && !defined(OPENBSD) && !defined(__zaurus__)) TRY_MIDI_DRIVER(forked_player); #endif #if defined(MACOS) || defined(MACOSX) TRY_MIDI_DRIVER(Mac_QT_midi); #endif #if defined(__MORPHOS__) || defined(AMIGA) TRY_MIDI_DRIVER(AmigaMIDI); #endif #ifdef USE_FMOPL_MIDI TRY_MIDI_DRIVER(FMOpl_Midi); #endif initialized = true; if(no_device) { midi_device=0; cerr << "Unable to create a MIDI device. No music will be played." << endl; return false; } load_patches(false); return true; } MyMidiPlayer::MyMidiPlayer() : current_track(-1),repeating(false), midi_device(0), initialized(false), music_conversion(XMIDI_CONVERT_MT32_TO_GM), effects_conversion(XMIDI_CONVERT_GS127_TO_GS), output_driver_type(MIDI_DRIVER_NORMAL) { add_midi_bank(MAINMUS); add_midi_bank(INTROMUS); add_midi_bank("/mainshp.flx"); add_midi_bank(MAINMUS_AD); add_midi_bank(INTROMUS_AD); init_device(); } MyMidiPlayer::~MyMidiPlayer() { if(midi_device)//&&midi_device->is_playing()) //midi_device->stop_track(); delete midi_device; } void MyMidiPlayer::start_sound_effect(int num) { #ifdef DEBUG cout << "Audio subsystem request: sound effect # " << num << endl; #endif int real_num = num; if (Game::get_game_type() == BLACK_GATE) real_num = bgconv[num]; cout << "Real num " << real_num << endl; U7object track("/midisfx.flx",real_num); if (!midi_device && !init_device()) return; char *buffer; size_t size; DataSource *mid_data; try { buffer = track.retrieve(size); } catch( const std::exception & /*err*/ ) { return; } // Read the data into the XMIDI class mid_data = new BufferDataSource(buffer, size); // It's already GM, so dont convert XMIDI midfile(mid_data, effects_conversion); delete mid_data; delete [] buffer; // Now give the xmidi object to the midi device XMIDIEventList *eventlist = midfile.GetEventList(0); if (eventlist) midi_device->start_sfx(eventlist); } void MyMidiPlayer::stop_sound_effects() { if (midi_device) midi_device->stop_sfx(); } OGG_MIDI::OGG_MIDI() { oggmusic = NULL; Mix_HookMusicFinished(music_complete_callback); Mix_VolumeMusic(MIX_MAX_VOLUME); } OGG_MIDI::~OGG_MIDI() { Mix_HaltMusic(); if(oggmusic) { Mix_FreeMusic(oggmusic); oggmusic = NULL; } } //Clean up last track played, freeing memory each time void OGG_MIDI::music_complete_callback(void) { if(oggmusic) { Mix_FreeMusic(oggmusic); oggmusic = NULL; } } void OGG_MIDI::start_track(XMIDIEventList *, bool repeat) { } void OGG_MIDI::stop_track(void) { Mix_HaltMusic(); if(oggmusic) { Mix_FreeMusic(oggmusic); oggmusic = NULL; } } bool OGG_MIDI::is_playing(void) { return Mix_PlayingMusic()!=0; } const char * OGG_MIDI::copyright(void) { return "Internal OGG digital music player"; } exult-1.2/audio/xmidi.cc0000644000175000001440000011423110054030550010706 /* * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ // Nope, not any more we don't #if 1 #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include # include #endif #include #include "../files/utils.h" #include "xmidi.h" #include "../conf/Configuration.h" extern Configuration *config; #ifndef UNDER_CE using std::atof; using std::atoi; using std::cerr; using std::endl; using std::memcmp; using std::memcpy; using std::memset; using std::size_t; using std::string; #endif #include "gamma.h" // Here's a bit of joy: WIN32 isn't SMP safe if we use operator new and delete. // On the other hand, nothing else is thread-safe if we use malloc()/free(). // So, we wrap the implementations and use malloc()/calloc()/free() for WIN32, and // the C++ thread-safe allocator for other platforms. template inline T* Malloc(size_t num=1) { #ifdef WIN32 return static_cast(std::malloc(num)); #else return static_cast(::operator new(num)); #endif } template inline T* Calloc(size_t num=1,size_t sz=0) { if(!sz) sz=sizeof(T); #ifdef WIN32 return static_cast(std::calloc(num,sz)); #else size_t total=sz*num; T *tmp=Malloc(total); std::memset(tmp,0,total); return tmp; #endif } inline void Free(void *ptr) { #ifdef WIN32 std::free(ptr); #else ::operator delete(ptr); #endif } // This is used to correct incorrect patch, vol and pan changes in midi files // The bias is just a value to used to work out if a vol and pan belong with a // patch change. This is to ensure that the default state of a midi file is with // the tracks centred, unless the first patch change says otherwise. #define PATCH_VOL_PAN_BIAS 5 // This is a default set of patches to convert from MT32 to GM // The index is the MT32 Patch nubmer and the value is the GM Patch // This is only suitable for music that doesn'tdo timbre changes // XMIDIs that contain Timbre changes will not convert properly const char XMIDI::mt32asgm[128] = { 0, // 0 Piano 1 1, // 1 Piano 2 2, // 2 Piano 3 (synth) 4, // 3 EPiano 1 4, // 4 EPiano 2 5, // 5 EPiano 3 5, // 6 EPiano 4 3, // 7 Honkytonk 16, // 8 Organ 1 17, // 9 Organ 2 18, // 10 Organ 3 16, // 11 Organ 4 19, // 12 Pipe Organ 1 19, // 13 Pipe Organ 2 19, // 14 Pipe Organ 3 21, // 15 Accordion 6, // 16 Harpsichord 1 6, // 17 Harpsichord 2 6, // 18 Harpsichord 3 7, // 19 Clavinet 1 7, // 20 Clavinet 2 7, // 21 Clavinet 3 8, // 22 Celesta 1 8, // 23 Celesta 2 62, // 24 Synthbrass 1 (62) 63, // 25 Synthbrass 2 (63) 62, // 26 Synthbrass 3 Bank 8 63, // 27 Synthbrass 4 Bank 8 38, // 28 Synthbass 1 39, // 29 Synthbass 2 38, // 30 Synthbass 3 Bank 8 39, // 31 Synthbass 4 Bank 8 88, // 32 Fantasy 90, // 33 Harmonic Pan - No equiv closest is polysynth(90) :( 52, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)??? 92, // 35 Glass 97, // 36 Soundtrack 99, // 37 Atmosphere 14, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is! 54, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111) 98, // 40 EchoBell, no real equiv, sounds like Crystal(98) 96, // 41 IceRain 68, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68) 95, // 43 EchoPans, no equiv, setting to SweepPad 81, // 44 DoctorSolo Bank 8 87, // 45 SchoolDaze, no real equiv 112, // 46 Bell Singer 80, // 47 SquareWave 48, // 48 Strings 1 48, // 49 Strings 2 - should be 49 44, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50 45, // 51 Pizzicato Strings 40, // 52 Violin 1 40, // 53 Violin 2 ? Viola 42, // 54 Cello 1 42, // 55 Cello 2 43, // 56 Contrabass 46, // 57 Harp 1 46, // 58 Harp 2 24, // 59 Guitar 1 (Nylon) 25, // 60 Guitar 2 (Steel) 26, // 61 Elec Guitar 1 27, // 62 Elec Guitar 2 104, // 63 Sitar 32, // 64 Acou Bass 1 32, // 65 Acou Bass 2 33, // 66 Elec Bass 1 34, // 67 Elec Bass 2 36, // 68 Slap Bass 1 37, // 69 Slap Bass 2 35, // 70 Fretless Bass 1 35, // 71 Fretless Bass 2 73, // 72 Flute 1 73, // 73 Flute 2 72, // 74 Piccolo 1 72, // 75 Piccolo 2 74, // 76 Recorder 75, // 77 Pan Pipes 64, // 78 Sax 1 65, // 79 Sax 2 66, // 80 Sax 3 67, // 81 Sax 4 71, // 82 Clarinet 1 71, // 83 Clarinet 2 68, // 84 Oboe 69, // 85 English Horn (Cor Anglais) 70, // 86 Bassoon 22, // 87 Harmonica 56, // 88 Trumpet 1 56, // 89 Trumpet 2 57, // 90 Trombone 1 57, // 91 Trombone 2 60, // 92 French Horn 1 60, // 93 French Horn 2 58, // 94 Tuba 61, // 95 Brass Section 1 61, // 96 Brass Section 2 11, // 97 Vibes 1 11, // 98 Vibes 2 99, // 99 Syn Mallet Bank 1 112, // 100 WindBell no real equiv Set to TinkleBell(112) 9, // 101 Glockenspiel 14, // 102 Tubular Bells 13, // 103 Xylophone 12, // 104 Marimba 107, // 105 Koto 111, // 106 Sho?? set to Shanai(111) 77, // 107 Shakauhachi 78, // 108 Whistle 1 78, // 109 Whistle 2 76, // 110 Bottle Blow 76, // 111 Breathpipe no real equiv set to bottle blow(76) 47, // 112 Timpani 117, // 113 Melodic Tom 116, // 114 Deap Snare no equiv, set to Taiko(116) 118, // 115 Electric Perc 1 118, // 116 Electric Perc 2 116, // 117 Taiko 115, // 118 Taiko Rim, no real equiv, set to Woodblock(115) 119, // 119 Cymbal, no real equiv, set to reverse cymbal(119) 115, // 120 Castanets, no real equiv, in GM set to Woodblock(115) 112, // 121 Triangle, no real equiv, set to TinkleBell(112) 55, // 122 Orchestral Hit 124, // 123 Telephone 123, // 124 BirdTweet 94, // 125 Big Notes Pad no equiv, set to halo pad (94) 98, // 126 Water Bell set to Crystal Pad(98) 121 // 127 Jungle Tune set to Breath Noise }; // Same as above, except include patch changes // so GS instruments can be used const char XMIDI::mt32asgs[256] = { 0, 0, // 0 Piano 1 1, 0, // 1 Piano 2 2, 0, // 2 Piano 3 (synth) 4, 0, // 3 EPiano 1 4, 0, // 4 EPiano 2 5, 0, // 5 EPiano 3 5, 0, // 6 EPiano 4 3, 0, // 7 Honkytonk 16, 0, // 8 Organ 1 17, 0, // 9 Organ 2 18, 0, // 10 Organ 3 16, 0, // 11 Organ 4 19, 0, // 12 Pipe Organ 1 19, 0, // 13 Pipe Organ 2 19, 0, // 14 Pipe Organ 3 21, 0, // 15 Accordion 6, 0, // 16 Harpsichord 1 6, 0, // 17 Harpsichord 2 6, 0, // 18 Harpsichord 3 7, 0, // 19 Clavinet 1 7, 0, // 20 Clavinet 2 7, 0, // 21 Clavinet 3 8, 0, // 22 Celesta 1 8, 0, // 23 Celesta 2 62, 0, // 24 Synthbrass 1 (62) 63, 0, // 25 Synthbrass 2 (63) 62, 0, // 26 Synthbrass 3 Bank 8 63, 0, // 27 Synthbrass 4 Bank 8 38, 0, // 28 Synthbass 1 39, 0, // 29 Synthbass 2 38, 0, // 30 Synthbass 3 Bank 8 39, 0, // 31 Synthbass 4 Bank 8 88, 0, // 32 Fantasy 90, 0, // 33 Harmonic Pan - No equiv closest is polysynth(90) :( 52, 0, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)??? 92, 0, // 35 Glass 97, 0, // 36 Soundtrack 99, 0, // 37 Atmosphere 14, 0, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is! 54, 0, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111) 98, 0, // 40 EchoBell, no real equiv, sounds like Crystal(98) 96, 0, // 41 IceRain 68, 0, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68) 95, 0, // 43 EchoPans, no equiv, setting to SweepPad 81, 0, // 44 DoctorSolo Bank 8 87, 0, // 45 SchoolDaze, no real equiv 112, 0, // 46 Bell Singer 80, 0, // 47 SquareWave 48, 0, // 48 Strings 1 48, 0, // 49 Strings 2 - should be 49 44, 0, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50 45, 0, // 51 Pizzicato Strings 40, 0, // 52 Violin 1 40, 0, // 53 Violin 2 ? Viola 42, 0, // 54 Cello 1 42, 0, // 55 Cello 2 43, 0, // 56 Contrabass 46, 0, // 57 Harp 1 46, 0, // 58 Harp 2 24, 0, // 59 Guitar 1 (Nylon) 25, 0, // 60 Guitar 2 (Steel) 26, 0, // 61 Elec Guitar 1 27, 0, // 62 Elec Guitar 2 104, 0, // 63 Sitar 32, 0, // 64 Acou Bass 1 32, 0, // 65 Acou Bass 2 33, 0, // 66 Elec Bass 1 34, 0, // 67 Elec Bass 2 36, 0, // 68 Slap Bass 1 37, 0, // 69 Slap Bass 2 35, 0, // 70 Fretless Bass 1 35, 0, // 71 Fretless Bass 2 73, 0, // 72 Flute 1 73, 0, // 73 Flute 2 72, 0, // 74 Piccolo 1 72, 0, // 75 Piccolo 2 74, 0, // 76 Recorder 75, 0, // 77 Pan Pipes 64, 0, // 78 Sax 1 65, 0, // 79 Sax 2 66, 0, // 80 Sax 3 67, 0, // 81 Sax 4 71, 0, // 82 Clarinet 1 71, 0, // 83 Clarinet 2 68, 0, // 84 Oboe 69, 0, // 85 English Horn (Cor Anglais) 70, 0, // 86 Bassoon 22, 0, // 87 Harmonica 56, 0, // 88 Trumpet 1 56, 0, // 89 Trumpet 2 57, 0, // 90 Trombone 1 57, 0, // 91 Trombone 2 60, 0, // 92 French Horn 1 60, 0, // 93 French Horn 2 58, 0, // 94 Tuba 61, 0, // 95 Brass Section 1 61, 0, // 96 Brass Section 2 11, 0, // 97 Vibes 1 11, 0, // 98 Vibes 2 99, 0, // 99 Syn Mallet Bank 1 112, 0, // 100 WindBell no real equiv Set to TinkleBell(112) 9, 0, // 101 Glockenspiel 14, 0, // 102 Tubular Bells 13, 0, // 103 Xylophone 12, 0, // 104 Marimba 107, 0, // 105 Koto 111, 0, // 106 Sho?? set to Shanai(111) 77, 0, // 107 Shakauhachi 78, 0, // 108 Whistle 1 78, 0, // 109 Whistle 2 76, 0, // 110 Bottle Blow 76, 0, // 111 Breathpipe no real equiv set to bottle blow(76) 47, 0, // 112 Timpani 117, 0, // 113 Melodic Tom 116, 0, // 114 Deap Snare no equiv, set to Taiko(116) 118, 0, // 115 Electric Perc 1 118, 0, // 116 Electric Perc 2 116, 0, // 117 Taiko 115, 0, // 118 Taiko Rim, no real equiv, set to Woodblock(115) 119, 0, // 119 Cymbal, no real equiv, set to reverse cymbal(119) 115, 0, // 120 Castanets, no real equiv, in GM set to Woodblock(115) 112, 0, // 121 Triangle, no real equiv, set to TinkleBell(112) 55, 0, // 122 Orchestral Hit 124, 0, // 123 Telephone 123, 0, // 124 BirdTweet 94, 0, // 125 Big Notes Pad no equiv, set to halo pad (94) 98, 0, // 126 Water Bell set to Crystal Pad(98) 121, 0 // 127 Jungle Tune set to Breath Noise }; GammaTable XMIDI::VolumeCurve(128); // Constructor XMIDI::XMIDI(DataSource *source, int pconvert) : events(NULL), convert_type(pconvert), do_reverb(false), do_chorus(false) { std::memset(bank127,0,sizeof(bank127)); ExtractTracks (source); } XMIDI::~XMIDI() { if (events) { for (int i=0; i < num_tracks; i++) { events[i]->DecerementCounter(); events[i] = NULL; } //delete [] events; Free(events); } } XMIDIEventList *XMIDI::GetEventList (uint32 track) { if (!events) { cerr << "No midi data in loaded." << std::endl; return 0; } if (track >= num_tracks) { cerr << "Can't retrieve MIDI data, track out of range" << endl; return 0; } return events[track]; } // Sets current to the new event and updates list void XMIDI::CreateNewEvent (int time) { if (!list) { list = current = Calloc(); //new midi_event; if (time > 0) current->time = time; return; } if (time < 0 || list->time > time) { midi_event *event = Calloc(); //new midi_event; event->next = list; list = current = event; return; } if (!current || current->time > time) current = list; while (current->next) { if (current->next->time > time) { midi_event *event = Calloc(); //new midi_event; event->next = current->next; current->next = event; current = event; current->time = time; return; } current = current->next; } current->next = Calloc(); //new midi_event; current = current->next; current->time = time; } // // GetVLQ // // Get a Conventional Variable Length Quantity // int XMIDI::GetVLQ (DataSource *source, uint32 &quant) { int i; quant = 0; unsigned int data; for (i = 0; i < 4; i++) { data = source->read1(); quant <<= 7; quant |= data & 0x7F; if (!(data & 0x80)) { i++; break; } } return i; } // // GetVLQ2 // // Get a XMIDI Variable Length Quantity // int XMIDI::GetVLQ2 (DataSource *source, uint32 &quant) { int i; quant = 0; int data = 0; for (i = 0; i < 4; i++) { data = source->read1(); if (data & 0x80) { source->skip(-1); break; } quant += data; } return i; } // // MovePatchVolAndPan. // // Well, this is just a modified version of what that method used to do. This // is a massive optimization. Speed up should be quite impressive // void XMIDI::ApplyFirstState(first_state &fs, int chan_mask) { for (int channel = 0; channel < 16; channel++) { midi_event *patch = fs.patch[channel]; midi_event *vol = fs.vol[channel]; midi_event *pan = fs.pan[channel]; midi_event *bank = fs.bank[channel]; midi_event *reverb = NULL; midi_event *chorus = NULL; midi_event *temp; // Got no patch change, return and don't try fixing it if (!patch || !(chan_mask & 1 << channel)) continue; #if 0 std::cout << "Channel: " << channel+1 << std::endl; std::cout << "Patch: " << (unsigned int) patch->data[0] << " @ " << patch->time << std::endl; if (bank) std::cout << " Bank: " << (unsigned int) bank->data[1] << " @ " << bank->time << std::endl; if (vol) std::cout << " Vol: " << (unsigned int) vol->data[1] << " @ " << vol->time << std::endl; if (pan) std::cout << " Pan: " << ((signed int) pan->data[1])-64 << " @ " << pan->time << std::endl; std::cout << std::endl; #endif // Copy Patch Change Event temp = patch; patch = Calloc(); //new midi_event; patch->time = temp->time; patch->status = channel|(MIDI_STATUS_PROG_CHANGE << 4); patch->data[0] = temp->data[0]; // Copy Volume if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS)) vol = NULL; temp = vol; vol = Calloc(); //new midi_event; vol->status = channel|(MIDI_STATUS_CONTROLLER << 4); vol->data[0] = 7; if (!temp) { if (convert_type) vol->data[1] = VolumeCurve[90]; else vol->data[1] = 90; } else vol->data[1] = temp->data[1]; // Copy Bank if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS)) bank = NULL; temp = bank; bank = Calloc(); //new midi_event; bank->status = channel|(MIDI_STATUS_CONTROLLER << 4); if (!temp) bank->data[1] = 0; else bank->data[1] = temp->data[1]; // Copy Pan if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS)) pan = NULL; temp = pan; pan = Calloc(); //new midi_event; pan->status = channel|(MIDI_STATUS_CONTROLLER << 4); pan->data[0] = 10; if (!temp) pan->data[1] = 64; else pan->data[1] = temp->data[1]; if (do_reverb) { reverb = Calloc(); //new midi_event; reverb->status = channel|(MIDI_STATUS_CONTROLLER << 4); reverb->data[0] = 91; reverb->data[1] = reverb_value; } if (do_chorus) { chorus = Calloc(); //new midi_event; chorus->status = channel|(MIDI_STATUS_CONTROLLER << 4); chorus->data[0] = 93; chorus->data[1] = chorus_value; } vol->time = 0; pan->time = 0; patch->time = 0; bank->time = 0; if (do_reverb && do_chorus) reverb->next = chorus; else if (do_reverb) reverb->next = bank; if (do_chorus) chorus->next = bank; bank->next = vol; vol->next = pan; pan->next = patch; patch->next = list; if (do_reverb) list = reverb; else if (do_chorus) list = chorus; else list = bank; } } #ifndef BEOS // Unsigned 64 Bit Int emulation. Only supports SOME operations struct uint64 { uint32 low; // Low is first so uint64 can be cast as uint32 to get low dword uint32 high; // uint64() : low(0), high(0) { } uint64(uint32 i) : low(i), high(0) { } uint64(uint32 h, uint32 l) : low(l), high(h) { } uint64(const uint64 &i) : low(i.low), high(i.high) { } inline void addlow(uint32 l) { uint32 mid = (low >> 16); low = (low & 0xFFFF) + (l & 0xFFFF); mid += (low >> 16) + (l >> 16); low = (low&0xFFFF) + (mid << 16); high += mid >> 16; } // uint64 operations inline uint64 & operator = (uint64 &o) { low = o.low; high = o.high; return *this; } inline uint64 & operator += (uint64 &o) { addlow(o.low); high += o.high; return *this; } inline uint64 operator + (uint64 &o) { uint64 n(*this); n.addlow(o.low); n.high += o.high; return n; } // uint32 operations inline uint64 & operator = (uint32 i) { low = i; high = 0; return *this; } inline uint64 & operator += (uint32 i) { addlow(i); return *this; } inline uint64 operator + (uint32 i) { uint64 n(*this); n.addlow(i); return n; } inline uint64 & operator *= (uint32 i) { // High 16 bits uint32 h1 = i >> 16; uint32 h2 = low >> 16; //uint32 h3 = high >> 16; // Low 16 Bits uint32 l1 = i & 0xFFFF; uint32 l2 = low & 0xFFFF; uint32 l3 = high & 0xFFFF; // The accumulator uint32 accum; // 0 -> 32 low = l1*l2; high = 0; // 16 -> 48 accum = h1*l2; addlow(accum<<16); high += accum>>16; // 16 -> 48 accum = l1*h2; addlow(accum<<16); high += accum>>16; // 32 -> 64 high += h1*h2; // 32 -> 64 high += l1*l3; // 48 -> 80 high += (h1*l3) << 16; // 48 -> 80 high += (l1*l3) << 16; return *this; } inline uint64 operator * (uint32 i) { uint64 n(*this); return n*=i; } inline uint64 & operator /= (uint32 div) { // If there isn't a high dword, we only need to work on the low dword if (!high) { low /= div; return *this; } // modulus of last division uint32 mod = high; uint32 l = low; // Low shift uint32 shift = 32; low = 0; // Only High DWORD // Can divide if (mod >= div) { high = mod / div; mod %= div; } else high = 0; // Only Both high and low while (--shift) { mod <<= 1; mod |= (l>>shift) & 1; // Can divide if (mod >= div) { uint32 v = mod / div; mod %= div; addlow(v << shift); high += v >> (32 - shift); } } // Only Low DWORD mod <<= 1; mod |= l & 1; // Can divide if (mod >= div) { uint32 v = mod / div; mod %= div; addlow(v << shift); } return *this; } inline uint64 operator / (uint32 i) { uint64 n(*this); return n/=i; } inline uint64 & operator %= (uint32 div) { // If there isn't a high dword, we only need to work on the low dword if (!high) { low %= div; return *this; } // Remainder of last division uint32 mod = high; // Low shift uint32 shift = 32; while (1) { // Can divide if (mod >= div) mod %= div; if (shift == 0) break; mod <<= 1; shift--; mod |= (low>>shift) & 1; } high = 0; low = mod; return *this; } inline uint64 operator % (uint32 i) { uint64 n(*this); return n%=i; } inline operator uint32 () { return low; } void printx() { if (high) std::printf ("%X%08X", high, low); else std::printf ("%X", low); } }; #endif // // AdjustTimings // // It converts the midi's to use 120 Hz timing, and also calcs the duration of // the notes. It also strips the tempo events, and adds it's own // // This is used by Midi's ONLY! It will do nothing with Xmidi // void XMIDI::AdjustTimings(uint32 ppqn) { uint32 tempo = 500000; uint32 time_prev = 0; uint32 hs_rem = 0; uint32 hs = 0; ppqn *= 10000; // Virtual playing NoteStack notes; for (midi_event *event = list; event; event = event->next) { // Note 64 bit int is required because multiplication by tempo can // require 52 bits in some circumstances uint64 aim = event->time - time_prev; aim *= tempo; hs_rem += aim%ppqn; hs += aim/ppqn; hs += hs_rem/ppqn; hs_rem %= ppqn; time_prev = event->time; event->time = (hs*6)/5 + (6*hs_rem)/(5*ppqn); // Note on and note off handling if (event->status <= 0x9F) { // Add if it's a note on and remove if it's a note off if ((event->status>>4) == MIDI_STATUS_NOTE_ON && event->data[1]) notes.Push(event); else { midi_event *prev = notes.FindAndPop(event); if (prev) prev->duration = event->time - prev->time; } } else if (event->status == 0xFF && event->data[0] == 0x51) { tempo = (event->buffer[0] << 16) + (event->buffer[1] << 8) + event->buffer[2]; event->buffer[0] = 0x07; event->buffer[1] = 0xA1; event->buffer[2] = 0x20; } } //std::cout << "Max Polyphony: " << notes.GetMaxPolyphony() << std::endl; static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 }; BufferDataSource ds((char *)tempo_buf, 5); current = list; ConvertSystemMessage (0, 0xFF,&ds); } // Converts Events // // Source is at the first data byte // size 1 is single data byte (ConvertEvent Only) // size 2 is dual data byte // size 3 is XMI Note on (ConvertNote only) // Returns bytes converted // // ConvertNote is used for Note On's and Note offs // ConvertSystemMessage is used for SysEx events and Meta events // ConvertEvent is used for everything else int XMIDI::ConvertEvent (const int time, const unsigned char status, DataSource *source, const int size, first_state &fs) { int data; data = source->read1(); // Bank changes are handled here if ((status >> 4) == 0xB && data == 0) { data = source->read1(); bank127[status&0xF] = false; if (convert_type == XMIDI_CONVERT_MT32_TO_GM || convert_type == XMIDI_CONVERT_MT32_TO_GS || convert_type == XMIDI_CONVERT_MT32_TO_GS127) return 2; CreateNewEvent (time); current->status = status; current->data[0] = 0; current->data[1] = data; // Set the bank if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current; if (convert_type == XMIDI_CONVERT_GS127_TO_GS && data == 127) bank127[status&0xF] = true; return 2; } // Handling for patch change mt32 conversion, probably should go elsewhere if ((status >> 4) == 0xC && (status&0xF) != 9 && convert_type != XMIDI_CONVERT_NOCONVERSION) { if (convert_type == XMIDI_CONVERT_MT32_TO_GM) { data = mt32asgm[data]; } else if ((convert_type == XMIDI_CONVERT_GS127_TO_GS && bank127[status&0xF]) || convert_type == XMIDI_CONVERT_MT32_TO_GS) { CreateNewEvent (time); current->status = 0xB0 | (status&0xF); current->data[0] = 0; current->data[1] = mt32asgs[data*2+1]; data = mt32asgs[data*2]; // Set the bank if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current; } else if (convert_type == XMIDI_CONVERT_MT32_TO_GS127) { CreateNewEvent (time); current->status = 0xB0 | (status&0xF); current->data[0] = 0; current->data[1] = 127; // Set the bank if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current; } }// Disable patch changes on Track 10 is doing a conversion else if ((status >> 4) == 0xC && (status&0xF) == 9 && convert_type != XMIDI_CONVERT_NOCONVERSION) { return size; } CreateNewEvent (time); current->status = status; current->data[0] = data; // Check for patch change, and update fs if req if ((status >> 4) == 0xC) { if (!fs.patch[status&0xF] || fs.patch[status&0xF]->time > time) fs.patch[status&0xF] = current; } // Controllers else if ((status >> 4) == 0xB) { // Volume if (current->data[0] == 7) { if (!fs.vol[status&0xF] || fs.vol[status&0xF]->time > time) fs.vol[status&0xF] = current; } // Pan else if (current->data[0] == 10) { if (!fs.pan[status&0xF] || fs.pan[status&0xF]->time > time) fs.pan[status&0xF] = current; } } if (size == 1) return 1; current->data[1] = source->read1(); // Volume modify the volume controller, only if converting if (convert_type && (current->status >> 4) == MIDI_STATUS_CONTROLLER && current->data[0] == 7) current->data[1] = VolumeCurve[current->data[1]]; return 2; } int XMIDI::ConvertNote (const int time, const unsigned char status, DataSource *source, const int size) { uint32 delta = 0; int data; data = source->read1(); CreateNewEvent (time); current->status = status; current->data[0] = data; current->data[1] = source->read1(); // Volume modify the note on's, only if converting if (convert_type && (current->status >> 4) == MIDI_STATUS_NOTE_ON && current->data[1]) current->data[1] = VolumeCurve[current->data[1]]; if (size == 2) return 2; // XMI Note On handling // Get the duration int i = GetVLQ (source, delta); // Set the duration current->duration = delta; // This is an optimization midi_event *prev = current; // Create a note off CreateNewEvent (time+delta); current->status = status; current->data[0] = data; current->data[1] = 0; // Optimization current = prev; return i + 2; } // Simple routine to convert system messages int XMIDI::ConvertSystemMessage (const int time, const unsigned char status, DataSource *source) { int i=0; CreateNewEvent (time); current->status = status; // Handling of Meta events if (status == 0xFF) { current->data[0] = source->read1(); i++; } i += GetVLQ (source, current->len); if (!current->len) { current->buffer = NULL; return i; } current->buffer = Malloc(current->len); source->read (reinterpret_cast(current->buffer), current->len); return i+current->len; } // XMIDI and Midi to List. Returns bit mask of channels used int XMIDI::ConvertFiletoList (DataSource *source, const bool is_xmi, first_state &fs) { int time = 0; // 120th of a second uint32 data; int end = 0; uint32 status = 0; int play_size = 2; int file_size = source->getSize(); int retval = 0; if (is_xmi) play_size = 3; while (!end && source->getPos() < file_size) { if (!is_xmi) { GetVLQ (source, data); time += data; data = source->read1(); if (data >= 0x80) { status = data; } else source->skip (-1); } else { GetVLQ2 (source, data); time += data; status = source->read1(); } switch (status >> 4) { case MIDI_STATUS_NOTE_ON: retval |= 1 << (status & 0xF); ConvertNote (time, status, source, play_size); break; case MIDI_STATUS_NOTE_OFF: ConvertNote (time, status, source, 2); break; // 2 byte data case MIDI_STATUS_AFTERTOUCH: case MIDI_STATUS_CONTROLLER: case MIDI_STATUS_PITCH_WHEEL: ConvertEvent (time, status, source, 2, fs); break; // 1 byte data case MIDI_STATUS_PROG_CHANGE: case MIDI_STATUS_PRESSURE: ConvertEvent (time, status, source, 1, fs); break; case MIDI_STATUS_SYSEX: if (status == 0xFF) { int pos = source->getPos(); uint32 data = source->read1(); if (data == 0x2F) // End, of track end = 1; else if (data == 0x51 && is_xmi) // XMIDI doesn't use tempo { GetVLQ (source, data); source->skip(data); break; } source->seek (pos); } ConvertSystemMessage (time, status, source); break; default: break; } } return retval; } // Assumes correct xmidi int XMIDI::ExtractTracksFromXmi (DataSource *source) { int num = 0; uint32 len = 0; char buf[32]; first_state fs; while (source->getPos() < source->getSize() && num != num_tracks) { // Read first 4 bytes of name source->read (buf, 4); len = source->read4high(); // Skip the FORM entries if (!memcmp(buf,"FORM",4)) { source->skip (4); source->read (buf, 4); len = source->read4high(); } if (memcmp(buf,"EVNT",4)) { source->skip ((len+1)&~1); continue; } list = NULL; memset(&fs, 0, sizeof(fs)); int begin = source->getPos (); // Convert it int chan_mask = ConvertFiletoList (source, true, fs); // Apply the first state ApplyFirstState(fs, chan_mask); // Add tempo static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 }; BufferDataSource ds((char *)tempo_buf, 5); current = list; ConvertSystemMessage (0, 0xFF,&ds); // Set the list events[num]->events = list; // Increment Counter num++; // go to start of next track source->seek (begin + ((len+1)&~1)); } // Return how many were converted return num; } int XMIDI::ExtractTracksFromMid (DataSource *source, const uint32 ppqn, const int num_tracks, const bool type1) { int num = 0; uint32 len = 0; char buf[32]; int chan_mask = 0; first_state fs; memset(&fs, 0, sizeof(fs)); list = NULL; while (source->getPos() < source->getSize() && num != num_tracks) { // Read first 4 bytes of name source->read (buf, 4); len = source->read4high(); if (memcmp(buf,"MTrk",4)) { source->skip (len); continue; } int begin = source->getPos (); // Convert it chan_mask |= ConvertFiletoList (source, false, fs); if (!type1) { ApplyFirstState(fs, chan_mask); AdjustTimings(ppqn); events[num]->events = list; list = NULL; memset(&fs, 0, sizeof(fs)); chan_mask = 0; } // Increment Counter num++; source->seek (begin+len); } if (type1) { ApplyFirstState(fs, chan_mask); AdjustTimings(ppqn); events[0]->events = list; return num == num_tracks ? 1 : 0; } // Return how many were converted return num; } int XMIDI::ExtractTracks (DataSource *source) { uint32 i = 0; int start; uint32 len; uint32 chunk_len; int count; char buf[32]; string s; config->value("config/audio/midi/reverb/enabled",s,"no"); if (s == "yes") do_reverb = true; config->set("config/audio/midi/reverb/enabled",s,true); config->value("config/audio/midi/reverb/level",s,"---"); if (s == "---") config->value("config/audio/midi/reverb",s,"64"); reverb_value = atoi(s.c_str()); if (reverb_value > 127) reverb_value = 127; else if (reverb_value < 0) reverb_value = 0; config->set("config/audio/midi/reverb/level",reverb_value,true); config->value("config/audio/midi/chorus/enabled",s,"no"); if (s == "yes") do_chorus = true; config->set("config/audio/midi/chorus/enabled",s,true); config->value("config/audio/midi/chorus/level",s,"---"); if (s == "---") config->value("config/audio/midi/chorus",s,"16"); chorus_value = atoi(s.c_str()); if (chorus_value > 127) chorus_value = 127; else if (chorus_value < 0) chorus_value = 0; config->set("config/audio/midi/chorus/level",chorus_value,true); config->value("config/audio/midi/volume_curve",s,"---"); if (s == "---") config->value("config/audio/midi/gamma",s,"1"); VolumeCurve.set_gamma (atof(s.c_str())); int igam = (int) ((VolumeCurve.get_gamma()*10000)+0.5); snprintf (buf, 32, "%d.%04d", igam/10000, igam%10000); config->set("config/audio/midi/volume_curve",buf,true); // Read first 4 bytes of header source->read (buf, 4); // Could be XMIDI if (!memcmp (buf, "FORM", 4)) { // Read length of len = source->read4high(); start = source->getPos(); // Read 4 bytes of type source->read (buf, 4); // XDIRless XMIDI, we can handle them here. if (!memcmp (buf, "XMID", 4)) { cerr << "Warning: XMIDI doesn't have XDIR" << endl; num_tracks = 1; } // Not an XMIDI that we recognise else if (memcmp (buf, "XDIR", 4)) { cerr << "Not a recognised XMID" << endl; return 0; } // Seems Valid else { num_tracks = 0; for (i = 4; i < len; i++) { // Read 4 bytes of type source->read (buf, 4); // Read length of chunk chunk_len = source->read4high(); // Add eight bytes i+=8; if (memcmp (buf, "INFO", 4)) { // Must allign source->skip((chunk_len+1)&~1); i+= (chunk_len+1)&~1; continue; } // Must be at least 2 bytes long if (chunk_len < 2) break; num_tracks = source->read2(); break; } // Didn't get to fill the header if (num_tracks == 0) { cerr << "Not a valid XMID" << endl; return 0; } // Ok now to start part 2 // Goto the right place source->seek (start+((len+1)&~1)); // Read 4 bytes of type source->read (buf, 4); // Not an XMID if (memcmp (buf, "CAT ", 4)) { cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (CAT )" << endl; return 0; } // Now read length of this track len = source->read4high(); // Read 4 bytes of type source->read (buf, 4); // Not an XMID if (memcmp (buf, "XMID", 4)) { cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (XMID)" << endl; return 0; } } // Ok it's an XMID, so pass it to the ExtractCode events = Calloc(num_tracks); //new midi_event *[info.tracks]; for (i = 0; i < num_tracks; i++) events[i] = Calloc(); count = ExtractTracksFromXmi (source); if (count != num_tracks) { cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from XMIDI. Only ("<< count << ")" << endl; int i = 0; for (i = 0; i < num_tracks; i++) { events[i]->DecerementCounter(); events[i] = NULL; } //delete [] events; Free (events); return 0; } return 1; }// Definately a Midi else if (!memcmp (buf, "MThd", 4)) { // Simple read length of header len = source->read4high(); if (len < 6) { cerr << "Not a valid MIDI" << endl; return 0; } int type = source->read2high(); int actual_num = num_tracks = source->read2high(); // Type 1 only has 1 track, even though it says it has more if (type == 1) num_tracks = 1; events = Calloc(num_tracks); //new midi_event *[info.tracks]; const uint32 ppqn = source->read2high(); for (i = 0; i < num_tracks; i++) events[i] = Calloc(); count = ExtractTracksFromMid (source, ppqn, actual_num, type == 1); if (count != num_tracks) { cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from MIDI. Only ("<< count << ")" << endl; for (i = 0; i < num_tracks; i++) { events[i]->DecerementCounter(); events[i] = NULL; } Free (events); return 0; } return 1; }// A RIFF Midi, just pass the source back to this function at the start of the midi file else if (!memcmp (buf, "RIFF", 4)) { // Read len len = source->read4(); // Read 4 bytes of type source->read (buf, 4); // Not an RMID if (memcmp (buf, "RMID", 4)) { cerr << "Invalid RMID" << endl; return 0; } // Is a RMID for (i = 4; i < len; i++) { // Read 4 bytes of type source->read (buf, 4); chunk_len = source->read4(); i+=8; if (memcmp (buf, "data", 4)) { // Must allign source->skip ((chunk_len+1)&~1); i+= (chunk_len+1)&~1; continue; } return ExtractTracks (source); } cerr << "Failed to find midi data in RIFF Midi" << endl; return 0; } return 0; } // // XMIDIEventList stuff // int XMIDIEventList::Write (const char *filename) { std::FILE *file = U7open (filename, "wb"); // DARKE FIXME FileDataSource ds(file); int ret = Write(&ds); fclose (file); return ret; } int XMIDIEventList::Write (DataSource *dest) { int len = 0; if (!events) { cerr << "No midi data in loaded." << endl; return 0; } // This is so if using buffer datasource, the caller can know how big to make the buffer if (!dest) { // Header is 14 bytes long and add the rest as well len = ConvertListToMTrk (NULL); return 14 + len; } dest->write1 ('M'); dest->write1 ('T'); dest->write1 ('h'); dest->write1 ('d'); dest->write4high (6); dest->write2high (0); dest->write2high (1); dest->write2high (60); // The PPQN len = ConvertListToMTrk (dest); return len + 14; } // // PutVLQ // // Write a Conventional Variable Length Quantity // int XMIDIEventList::PutVLQ(DataSource *dest, uint32 value) { int buffer; int i = 1; buffer = value & 0x7F; while (value >>= 7) { buffer <<= 8; buffer |= ((value & 0x7F) | 0x80); i++; } if (!dest) return i; for (int j = 0; j < i; j++) { dest->write1(buffer & 0xFF); buffer >>= 8; } return i; } // Converts and event list to a MTrk // Returns bytes of the array // buf can be NULL uint32 XMIDIEventList::ConvertListToMTrk (DataSource *dest) { int time = 0; int lasttime = 0; midi_event *event; uint32 delta; unsigned char last_status = 0; uint32 i = 8; uint32 j; uint32 size_pos=0; if (dest) { dest->write1('M'); dest->write1('T'); dest->write1('r'); dest->write1('k'); size_pos = dest->getPos(); dest->skip(4); } for (event = events; event; event=event->next) { // We don't write the end of stream marker here, we'll do it later if (event->status == 0xFF && event->data[0] == 0x2f) { lasttime = event->time; continue; } delta = (event->time - time); time = event->time; i += PutVLQ (dest, delta); if ((event->status != last_status) || (event->status >= 0xF0)) { if (dest) dest->write1(event->status); i++; } last_status = event->status; switch (event->status >> 4) { // 2 bytes data // Note off, Note on, Aftertouch, Controller and Pitch Wheel case 0x8: case 0x9: case 0xA: case 0xB: case 0xE: if (dest) { dest->write1(event->data[0]); dest->write1(event->data[1]); } i += 2; break; // 1 bytes data // Program Change and Channel Pressure case 0xC: case 0xD: if (dest) dest->write1(event->data[0]); i++; break; // Variable length // SysEx case 0xF: if (event->status == 0xFF) { if (dest) dest->write1(event->data[0]); i++; } i += PutVLQ (dest, event->len); if (event->len) { for (j = 0; j < event->len; j++) { if (dest) dest->write1(event->buffer[j]); i++; } } break; // Never occur default: cerr << "Not supposed to see this" << endl; break; } } // Write out end of stream marker if (lasttime > time) i += PutVLQ (dest, lasttime-time); else i += PutVLQ (dest, 0); if (dest) { dest->write1(0xFF); dest->write1(0x2F); } i += 2+PutVLQ (dest, 0); if (dest) { int cur_pos = dest->getPos(); dest->seek (size_pos); dest->write4high (i-8); dest->seek (cur_pos); } return i; } void XMIDIEventList::DeleteEventList (midi_event *mlist) { midi_event *event; midi_event *next; next = mlist; event = mlist; while ((event = next)) { next = event->next; // We only do this with sysex if ((event->status>>4) == 0xF && event->buffer) Free (event->buffer); Free (event); } } void XMIDIEventList::DecerementCounter() { if (--counter < 0) { DeleteEventList(events); Free(this); } } #endif exult-1.2/dir.h0000644000175000001440000000227607724430447007143 /* * dir.h - Directions. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DIR_H #define DIR_H 1 /* * Directions: */ enum Direction { north = 0, northeast = 1, east = 2, southeast = 3, south = 4, southwest = 5, west = 6, northwest = 7 }; Direction Get_direction ( int deltay, int deltax ); Direction Get_direction4 ( int deltay, int deltax ); int Get_direction16 ( int deltay, int deltax ); #endif exult-1.2/aclocal.m40000644000175000001440000043560310061527023010041 # aclocal.m4 generated automatically by aclocal 1.5 # Copyright 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Do all the work for Automake. This macro actually does too much -- # some checks are only needed if your package does certain things. # But this isn't really a big deal. # serial 5 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # We require 2.13 because we rely on SHELL being computed by configure. AC_PREREQ([2.13]) # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) # ----------------------------------------------------------- # If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED. # The purpose of this macro is to provide the user with a means to # check macros which are provided without letting her know how the # information is coded. # If this macro is not defined by Autoconf, define it here. ifdef([AC_PROVIDE_IFELSE], [], [define([AC_PROVIDE_IFELSE], [ifdef([AC_PROVIDE_$1], [$2], [$3])])]) # AM_INIT_AUTOMAKE(PACKAGE,VERSION, [NO-DEFINE]) # ---------------------------------------------- AC_DEFUN([AM_INIT_AUTOMAKE], [AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first]) fi # Define the identity of the package. PACKAGE=$1 AC_SUBST(PACKAGE)dnl VERSION=$2 AC_SUBST(VERSION)dnl ifelse([$3],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])]) # Autoconf 2.50 wants to disallow AM_ names. We explicitly allow # the ones we care about. ifdef([m4_pattern_allow], [m4_pattern_allow([^AM_[A-Z]+FLAGS])])dnl # Autoconf 2.50 always computes EXEEXT. However we need to be # compatible with 2.13, for now. So we always define EXEEXT, but we # don't compute it. AC_SUBST(EXEEXT) # Similar for OBJEXT -- only we only use OBJEXT if the user actually # requests that it be used. This is a bit dumb. : ${OBJEXT=o} AC_SUBST(OBJEXT) # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_MISSING_PROG(AMTAR, tar) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_DEP_TRACK])dnl AC_REQUIRE([AM_SET_DEPDIR])dnl AC_PROVIDE_IFELSE([AC_PROG_][CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_][CC], defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_][CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_][CXX], defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) # # Check to make sure that the build environment is sane. # # serial 3 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # serial 2 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= am_backtick='`' AC_MSG_WARN([${am_backtick}missing' script is too old or missing]) fi ]) # AM_AUX_DIR_EXPAND # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [ # expand $ac_aux_dir to an absolute path am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` ]) # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # serial 4 -*- Autoconf -*- # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # --------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX" or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_$1_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) $1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type" AC_SUBST([$1DEPMODE]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [rm -f .deps 2>/dev/null mkdir .deps 2>/dev/null if test -d .deps; then DEPDIR=.deps else # MS-DOS does not allow filenames that begin with a dot. DEPDIR=_deps fi rmdir .deps 2>/dev/null AC_SUBST(DEPDIR) ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) pushdef([subst], defn([AC_SUBST])) subst(AMDEPBACKSLASH) popdef([subst]) ]) # Generate code to set up dependency tracking. # This macro should only be invoked once -- use via AC_REQUIRE. # Usage: # AM_OUTPUT_DEPENDENCY_COMMANDS # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],[ AC_OUTPUT_COMMANDS([ test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do case "$mf" in Makefile|GNUmakefile) dirpart=.;; */Makefile|*/GNUmakefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;; *) continue;; esac grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`echo "$file" | sed -e 's|/[^/]*$||'` $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1 # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])]) # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' doit: @echo done END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include='#' am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote='"' _am_result=BSD fi fi AC_SUBST(am__include) AC_SUBST(am__quote) AC_MSG_RESULT($_am_result) rm -f confinc confmf ]) # serial 3 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. # # FIXME: Once using 2.50, use this: # m4_match([$1], [^TRUE\|FALSE$], [AC_FATAL([$0: invalid condition: $1])])dnl AC_DEFUN([AM_CONDITIONAL], [ifelse([$1], [TRUE], [errprint(__file__:__line__: [$0: invalid condition: $1 ])dnl m4exit(1)])dnl ifelse([$1], [FALSE], [errprint(__file__:__line__: [$0: invalid condition: $1 ])dnl m4exit(1)])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi]) # Like AC_CONFIG_HEADER, but automatically create stamp file. # serial 3 # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. We must strip everything past the first ":", # and everything past the last "/". AC_PREREQ([2.12]) AC_DEFUN([AM_CONFIG_HEADER], [ifdef([AC_FOREACH],dnl [dnl init our file count if it isn't already m4_ifndef([_AM_Config_Header_Index], m4_define([_AM_Config_Header_Index], [0])) dnl prepare to store our destination file list for use in config.status AC_FOREACH([_AM_File], [$1], [m4_pushdef([_AM_Dest], m4_patsubst(_AM_File, [:.*])) m4_define([_AM_Config_Header_Index], m4_incr(_AM_Config_Header_Index)) dnl and add it to the list of files AC keeps track of, along dnl with our hook AC_CONFIG_HEADERS(_AM_File, dnl COMMANDS, [, INIT-CMDS] [# update the timestamp echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h]_AM_Config_Header_Index[" ][$2]m4_ifval([$3], [, [$3]]))dnl AC_CONFIG_HEADERS m4_popdef([_AM_Dest])])],dnl [AC_CONFIG_HEADER([$1]) AC_OUTPUT_COMMANDS( ifelse(patsubst([$1], [[^ ]], []), [], [test -z "$CONFIG_HEADERS" || echo timestamp >dnl patsubst([$1], [^\([^:]*/\)?.*], [\1])stamp-h]),dnl [am_indx=1 for am_file in $1; do case " \$CONFIG_HEADERS " in *" \$am_file "*) am_dir=\`echo \$am_file |sed 's%:.*%%;s%[^/]*\$%%'\` if test -n "\$am_dir"; then am_tmpdir=\`echo \$am_dir |sed 's%^\(/*\).*\$%\1%'\` for am_subdir in \`echo \$am_dir |sed 's%/% %'\`; do am_tmpdir=\$am_tmpdir\$am_subdir/ if test ! -d \$am_tmpdir; then mkdir \$am_tmpdir fi done fi echo timestamp > "\$am_dir"stamp-h\$am_indx ;; esac am_indx=\`expr \$am_indx + 1\` done]) ])]) # AM_CONFIG_HEADER # _AM_DIRNAME(PATH) # ----------------- # Like AS_DIRNAME, only do it during macro expansion AC_DEFUN([_AM_DIRNAME], [m4_if(m4_regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1, m4_if(m4_regexp([$1], [^//\([^/]\|$\)]), -1, m4_if(m4_regexp([$1], [^/.*]), -1, [.], m4_patsubst([$1], [^\(/\).*], [\1])), m4_patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])), m4_patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl ]) # _AM_DIRNAME # AM_PROG_LEX # Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT AC_DEFUN([AM_PROG_LEX], [AC_REQUIRE([AM_MISSING_HAS_RUN]) AC_CHECK_PROGS(LEX, flex lex, [${am_missing_run}flex]) AC_PROG_LEX AC_DECL_YYTEXT]) # libtool.m4 - Configure libtool for the host system. -*-Shell-script-*- # serial 46 AC_PROG_LIBTOOL AC_DEFUN([AC_PROG_LIBTOOL], [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl # Prevent multiple expansion define([AC_PROG_LIBTOOL], []) ]) AC_DEFUN([AC_LIBTOOL_SETUP], [AC_PREREQ(2.13)dnl AC_REQUIRE([AC_ENABLE_SHARED])dnl AC_REQUIRE([AC_ENABLE_STATIC])dnl AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_LD])dnl AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([LT_AC_PROG_SED])dnl AC_REQUIRE([AC_PROG_LN_S])dnl AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl _LT_AC_PROG_ECHO_BACKSLASH # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then AC_PATH_MAGIC fi ;; esac AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE(libtool-lock, [ --disable-libtool-lock avoid locking (might break parallel builds)]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi rm -rf conftest* ;; *-*-linux*) # Test if the compiler is 64bit echo 'int i;' > conftest.$ac_ext lt_cv_cc_64bit_output=no if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *"ELF 64"*) lt_cv_cc_64bit_output=yes ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_SAVE AC_LANG_C AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_RESTORE]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain, [AC_TRY_LINK([], [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*); DllMain (0, 0, 0);], [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])]) case $host/$CC in *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*) # old mingw systems require "-dll" to link a DLL, while more recent ones # require "-mdll" SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -mdll" AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch, [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])]) CFLAGS="$SAVE_CFLAGS" ;; *-*-cygwin* | *-*-pw32*) # cygwin systems need to pass --dll to the linker, and not link # crt.o which will require a WinMain@16 definition. lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;; esac ;; ]) esac _LT_AC_LTCONFIG_HACK ]) # AC_LIBTOOL_HEADER_ASSERT # ------------------------ AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT], [AC_CACHE_CHECK([whether $CC supports assert without backlinking], [lt_cv_func_assert_works], [case $host in *-*-solaris*) if test "$GCC" = yes && test "$with_gnu_ld" != yes; then case `$CC --version 2>/dev/null` in [[12]].*) lt_cv_func_assert_works=no ;; *) lt_cv_func_assert_works=yes ;; esac fi ;; esac]) if test "x$lt_cv_func_assert_works" = xyes; then AC_CHECK_HEADERS(assert.h) fi ])# AC_LIBTOOL_HEADER_ASSERT # _LT_AC_CHECK_DLFCN # -------------------- AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h) ])# _LT_AC_CHECK_DLFCN # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris* | sysv5*) symcode='[[BDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $host_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[[ABCDGISTW]]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[[]] = { EOF sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$no_builtin_flag" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AC_FD_CC fi else echo "cannot find nm_test_var in $nlist" >&AC_FD_CC fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC fi else echo "$progname: failed program was:" >&AC_FD_CC cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" if test -z "$lt_cv_sys_global_symbol_pipe"; then global_symbol_to_cdecl= global_symbol_to_c_name_address= else global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address" fi if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # --------------------------------- AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR], [# Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi ])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # _LT_AC_PROG_ECHO_BACKSLASH # -------------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac echo=${ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(ECHO) AC_DIVERT_POP ])# _LT_AC_PROG_ECHO_BACKSLASH # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ------------------------------------------------------------------ AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [if test "$cross_compiling" = yes; then : [$4] else AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_unknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_AC_TRY_DLOPEN_SELF # AC_LIBTOOL_DLOPEN_SELF # ------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; cygwin* | mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ])# AC_LIBTOOL_DLOPEN_SELF AC_DEFUN([_LT_AC_LTCONFIG_HACK], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" need_locks="$enable_libtool_lock" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o if test x"$host" != x"$build"; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case $host_os in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Allow CC to be a program name with arguments. set dummy $CC compiler="[$]2" AC_MSG_CHECKING([for objdir]) rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null AC_MSG_RESULT($objdir) AC_ARG_WITH(pic, [ --with-pic try to use only PIC/non-PIC objects [default=use both]], pic_mode="$withval", pic_mode=default) test -z "$pic_mode" && pic_mode=default # We assume here that the value for lt_cv_prog_cc_pic will not be cached # in isolation, and that seeing it set (from the cache) indicates that # the associated values are set (in the cache) correctly too. AC_MSG_CHECKING([for $compiler option to produce PIC]) AC_CACHE_VAL(lt_cv_prog_cc_pic, [ lt_cv_prog_cc_pic= lt_cv_prog_cc_shlib= lt_cv_prog_cc_wl= lt_cv_prog_cc_static= lt_cv_prog_cc_no_builtin= lt_cv_prog_cc_can_build_shared=$can_build_shared if test "$GCC" = yes; then lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-static' case $host_os in aix*) # Below there is a dirty hack to force normal static linking with -ldl # The problem is because libdl dynamically linked with both libc and # libC (AIX C++ library), which obviously doesn't included in libraries # list by gcc. This cause undefined symbols with -static flags. # This hack allows C programs to be linked with "-static -ldl", but # not sure about C++ programs. lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_cv_prog_cc_pic='-fno-common' ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; sysv4*MP*) if test -d /usr/nec; then lt_cv_prog_cc_pic=-Kconform_pic fi ;; *) lt_cv_prog_cc_pic='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case $host_os in aix3* | aix4* | aix5*) lt_cv_prog_cc_wl='-Wl,' # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_cv_prog_cc_static='-Bstatic' else lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' fi ;; hpux9* | hpux10* | hpux11*) # Is there a better lt_cv_prog_cc_static that works with the bundled CC? lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" lt_cv_prog_cc_pic='+Z' ;; irix5* | irix6* | nonstopux*) lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; newsos6) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' ;; sco3.2v5*) lt_cv_prog_cc_pic='-Kpic' lt_cv_prog_cc_static='-dn' lt_cv_prog_cc_shlib='-belf' ;; solaris*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; sunos4*) lt_cv_prog_cc_pic='-PIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; uts4*) lt_cv_prog_cc_pic='-pic' lt_cv_prog_cc_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_cv_prog_cc_pic='-Kconform_pic' lt_cv_prog_cc_static='-Bstatic' fi ;; *) lt_cv_prog_cc_can_build_shared=no ;; esac fi ]) if test -z "$lt_cv_prog_cc_pic"; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([$lt_cv_prog_cc_pic]) # Check to make sure the pic_flag actually works. AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works]) AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" AC_TRY_COMPILE([], [], [dnl case $host_os in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then # they create non-PIC objects. So, if there were any warnings, we # assume that PIC is not supported. if test -s conftest.err; then lt_cv_prog_cc_pic_works=no else lt_cv_prog_cc_pic_works=yes fi ;; *) lt_cv_prog_cc_pic_works=yes ;; esac ], [dnl lt_cv_prog_cc_pic_works=no ]) CFLAGS="$save_CFLAGS" ]) if test "X$lt_cv_prog_cc_pic_works" = Xno; then lt_cv_prog_cc_pic= lt_cv_prog_cc_can_build_shared=no else lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" fi AC_MSG_RESULT([$lt_cv_prog_cc_pic_works]) fi # Check for any special shared library compilation flags. if test -n "$lt_cv_prog_cc_shlib"; then AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries]) if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then : else AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure]) lt_cv_prog_cc_can_build_shared=no fi fi AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works]) AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl lt_cv_prog_cc_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes]) LDFLAGS="$save_LDFLAGS" ]) # Belt *and* braces to stop my trousers falling down: test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= AC_MSG_RESULT([$lt_cv_prog_cc_static_works]) pic_flag="$lt_cv_prog_cc_pic" special_shlib_compile_flags="$lt_cv_prog_cc_shlib" wl="$lt_cv_prog_cc_wl" link_static_flag="$lt_cv_prog_cc_static" no_builtin_flag="$lt_cv_prog_cc_no_builtin" can_build_shared="$lt_cv_prog_cc_can_build_shared" # Check to see if options -o and -c are simultaneously supported by compiler AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext]) AC_CACHE_VAL([lt_cv_compiler_c_o], [ $rm -r conftest 2>/dev/null mkdir conftest cd conftest echo "int some_variable = 0;" > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then lt_cv_compiler_c_o=no else lt_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&AC_FD_CC lt_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null ]) compiler_c_o=$lt_cv_compiler_c_o AC_MSG_RESULT([$compiler_c_o]) if test x"$compiler_c_o" = x"yes"; then # Check to see if we can write to a .lo AC_MSG_CHECKING([if $compiler supports -c -o file.lo]) AC_CACHE_VAL([lt_cv_compiler_o_lo], [ lt_cv_compiler_o_lo=no save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -c -o conftest.lo" save_objext="$ac_objext" ac_objext=lo AC_TRY_COMPILE([], [int some_variable = 0;], [dnl # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then lt_cv_compiler_o_lo=no else lt_cv_compiler_o_lo=yes fi ]) ac_objext="$save_objext" CFLAGS="$save_CFLAGS" ]) compiler_o_lo=$lt_cv_compiler_o_lo AC_MSG_RESULT([$compiler_o_lo]) else compiler_o_lo=no fi # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi if test "$GCC" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions]) echo "int some_variable = 0;" > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" compiler_rtti_exceptions=no AC_TRY_COMPILE([], [int some_variable = 0;], [dnl # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then compiler_rtti_exceptions=no else compiler_rtti_exceptions=yes fi ]) CFLAGS="$save_CFLAGS" AC_MSG_RESULT([$compiler_rtti_exceptions]) if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi # See if the linker supports building shared libraries. AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries]) allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_into_libs=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= link_all_deplibs=unknown always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ test -f $output_objdir/impgen.exe || (cd $output_objdir && \ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ else $CC -o impgen impgen.c ; fi)~ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' # cygwin and mingw dlls have different entry points and sets of symbols # to exclude. # FIXME: what about values for MSVC? dll_entry=__cygwin_dll_entry@12 dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ case $host_os in mingw*) # mingw values dll_entry=_DllMainCRTStartup@12 dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ ;; esac # mingw and cygwin differ, and it's simplest to just exclude the union # of the two symbol sets. dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one (in ltdll.c) if test "x$lt_cv_need_dllmain" = "xyes"; then ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' else ltdll_obj= ltdll_cmds= fi # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. # Be careful not to strip the DATA tag left be newer dlltools. export_symbols_cmds="$ltdll_cmds"' $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is. # If DATA tags from a recent dlltool are present, honour them! archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname-def; else echo EXPORTS > $output_objdir/$soname-def; _lt_hint=1; cat $export_symbols | while read symbol; do set dummy \$symbol; case \[$]# in 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; 4) echo " \[$]2 \[$]3 \[$]4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;; *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;; esac; _lt_hint=`expr 1 + \$_lt_hint`; done; fi~ '"$ltdll_cmds"' $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw* | pw32*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. hardcode_direct=yes archive_cmds='' hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then shared_flag='${wl}-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall can do strange things, so it is better to # generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. allow_undefined_flag='${wl}-berok' # This is a bit strange, but is similar to how AIX traditionally builds # it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' ;; darwin* | rhapsody*) case "$host_os" in rhapsody* | darwin1.[[012]]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on allow_undefined_flag='-flat_namespace -undefined suppress' ;; esac # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. Also zsh mangles # `"' quotes if we put them in here... so don't! archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)' # We need to add '_' to the symbols in $export_symbols first #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' hardcode_direct=yes hardcode_shlibpath_var=no whole_archive_flag_spec='-all_load $convenience' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case $host_os in hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case "$host_os" in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' #Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes export_dynamic_flag_spec='${wl}-Bexport' ;; solaris*) # gcc --version < 3.0 without binutils cannot create self contained # shared libraries reliably, requiring libgcc.a to resolve some of # the object symbols generated in some cases. Libraries that use # assert need libgcc.a to resolve __eprintf, for example. Linking # a copy of libgcc.a into every shared library to guarantee resolving # such symbols causes other problems: According to Tim Van Holder # , C++ libraries end up with a separate # (to the application) exception stack for one thing. no_undefined_flag=' -z defs' if test "$GCC" = yes; then case `$CC --version 2>/dev/null` in [[12]].*) cat <&2 *** Warning: Releases of GCC earlier than version 3.0 cannot reliably *** create self contained shared libraries on Solaris systems, without *** introducing a dependency on libgcc.a. Therefore, libtool is disabling *** -no-undefined support, which will at least allow you to build shared *** libraries. However, you may find that when you link such libraries *** into an application without using GCC, you have to manually add *** \`gcc --print-libgcc-file-name\` to the link command. We urge you to *** upgrade to a newer version of GCC. Another option is to rebuild your *** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer. EOF no_undefined_flag= ;; esac fi # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5uw7* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi AC_MSG_RESULT([$ld_shlibs]) test "$ld_shlibs" = no && can_build_shared=no # Check hardcoding attributes. AC_MSG_CHECKING([how to hardcode library paths into programs]) hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi AC_MSG_RESULT([$hardcode_action]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi reload_cmds='$LD$reload_flag -o $output$reload_objs' test -z "$deplibs_check_method" && deplibs_check_method=unknown # PORTME Fill in your ld.so characteristics AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib /usr/X11R6/lib" case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can # not hardcode correct soname into executable. Probably we can # add versioning support to collect2, so additional links can # be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}.so$major' fi shlibpath_var=LIBPATH fi hardcode_into_libs=yes ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin*) library_names_spec='$libname.dll.a' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog .libs/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' ;; yes,mingw*) library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"` ;; yes,pw32*) library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' ;; *) library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; *) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) version_type=irix ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes case $host_cpu:$lt_cv_cc_64bit_output in powerpc64:yes | s390x:yes | sparc64:yes | x86_64:yes) sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /usr/X11R6/lib64" sys_lib_search_path_spec="/lib64 /usr/lib64 /usr/local/lib64 /usr/X11R6/lib64" ;; esac # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' # Find out which ABI we are using (multilib Linux x86_64 hack). libsuff= case "$host_cpu" in x86_64*) echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 ;; esac fi rm -rf conftest* ;; *) ;; esac sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case "$host_os" in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" hardcode_into_libs=yes ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no # Report the final consequences. AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi AC_LIBTOOL_DLOPEN_SELF if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) AC_CACHE_VAL([lt_cv_archive_cmds_need_lc], [$rm conftest* echo 'static int dummy;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_cv_prog_cc_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$save_allow_undefined_flag else cat conftest.err 1>&5 fi]) AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc]) ;; esac fi need_lc=${lt_cv_archive_cmds_need_lc-yes} # The second clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then : else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi if test -f "$ltmain"; then trap "$rm \"${ofile}T\"; exit 1" 1 2 15 $rm -f "${ofile}T" echo creating $ofile # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS SED \ AR AR_FLAGS CC LD LN_S NM SHELL \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ old_striplib striplib file_magic_cmd export_symbols_cmds \ deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ global_symbol_to_c_name_address \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do case $var in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done cat <<__EOF__ > "${ofile}T" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996-2000 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="${SED} -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$need_lc # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # The default C compiler. CC=$lt_CC # Is the compiler the GNU C compiler? with_gcc=$GCC # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_pic_flag pic_mode=$pic_mode # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_compiler_c_o # Can we write directly to a .lo ? compiler_o_lo=$lt_compiler_o_lo # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "${ofile}T" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac case $host_os in cygwin* | mingw* | pw32* | os2*) cat <<'EOF' >> "${ofile}T" # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include /* for printf() */ # #include /* for open(), lseek(), read() */ # #include /* for O_RDONLY, O_BINARY */ # #include /* for strdup() */ # # /* O_BINARY isn't required (or even defined sometimes) under Unix */ # #ifndef O_BINARY # #define O_BINARY 0 # #endif # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (dll < 1) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) mv -f "${ofile}T" "$ofile" || \ (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") chmod +x "$ofile" fi ])# _LT_AC_LTCONFIG_HACK # AC_LIBTOOL_DLOPEN - enable checks for dlopen support AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) # AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) # AC_ENABLE_SHARED - implement the --enable-shared flag # Usage: AC_ENABLE_SHARED[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(shared, changequote(<<, >>)dnl << --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$ac_save_ifs" ;; esac], enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl ]) # AC_DISABLE_SHARED - set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no)]) # AC_ENABLE_STATIC - implement the --enable-static flag # Usage: AC_ENABLE_STATIC[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(static, changequote(<<, >>)dnl << --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$ac_save_ifs" ;; esac], enable_static=AC_ENABLE_STATIC_DEFAULT)dnl ]) # AC_DISABLE_STATIC - set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no)]) # AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag # Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(fast-install, changequote(<<, >>)dnl << --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$ac_save_ifs" ;; esac], enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl ]) # AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_FAST_INSTALL(no)]) # AC_LIBTOOL_PICMODE - implement the --with-pic flag # Usage: AC_LIBTOOL_PICMODE[(MODE)] # Where MODE is either `yes' or `no'. If omitted, it defaults to # `both'. AC_DEFUN([AC_LIBTOOL_PICMODE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl pic_mode=ifelse($#,1,$1,default)]) # AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="ifelse([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi ]) # AC_PATH_MAGIC - find a file program which can recognise a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH) else MAGIC_CMD=: fi fi ]) # AC_PROG_LD - find the path to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH(gnu-ld, [ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | [[A-Za-z]]:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$lt_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_PROG_LD_GNU ]) # AC_PROG_LD_GNU - AC_DEFUN([AC_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then lt_cv_prog_gnu_ld=yes else lt_cv_prog_gnu_ld=no fi]) with_gnu_ld=$lt_cv_prog_gnu_ld ]) # AC_PROG_LD_RELOAD_FLAG - find reload flag for linker # -- PORTME Some linkers may need a different reload flag. AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], [AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag, [lt_cv_ld_reload_flag='-r']) reload_flag=$lt_cv_ld_reload_flag test -n "$reload_flag" && reload_flag=" $reload_flag" ]) # AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], [AC_CACHE_CHECK([how to recognise dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given egrep regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[[012]]) lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac ;; freebsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20*|hpux11*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux-gnu*) case $host_cpu in alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | s390* | x86_64*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv5uw[[78]]* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method ]) # AC_PROG_NM - find the path to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl AC_MSG_CHECKING([for BSD-compatible nm]) AC_CACHE_VAL(lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/${ac_tool_prefix}nm if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then lt_cv_path_NM="$tmp_nm -B" break elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then lt_cv_path_NM="$tmp_nm -p" break else lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags fi fi done IFS="$ac_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" AC_MSG_RESULT([$NM]) ]) # AC_CHECK_LIBM - check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32*) # These system don't have libm ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, main, LIBM="-lm") ;; esac ]) # AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for # the libltdl convenience library and LTDLINCL to the include flags for # the libltdl header and adds --enable-ltdl-convenience to the # configure arguments. Note that LIBLTDL and LTDLINCL are not # AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not # provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed # with '${top_builddir}/' and LTDLINCL will be prefixed with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ]) # AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for # the libltdl installable library and LTDLINCL to the include flags for # the libltdl header and adds --enable-ltdl-install to the configure # arguments. Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is # AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed # libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will # be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed # with '${top_srcdir}/' (note the single quotes!). If your package is # not flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, main, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # # LT_AC_PROG_SED # -------------- # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. AC_DEFUN([LT_AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_executable_p="test -f" as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext" fi done done done # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. : ${TMPDIR=/tmp} { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=$TMPDIR/sed$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 { (exit 1); exit 1; } } _max=0 _count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for _sed in $_sed_list /usr/xpg4/bin/sed; do test ! -f ${_sed} && break cat /dev/null > "$tmp/sed.in" _count=0 echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in" # Check for GNU sed and select it if it is found. if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then lt_cv_path_SED=${_sed} break fi while true; do cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp" mv "$tmp/sed.tmp" "$tmp/sed.in" cp "$tmp/sed.in" "$tmp/sed.nl" echo >>"$tmp/sed.nl" ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break # 40000 chars as input seems more than enough test $_count -gt 10 && break _count=`expr $_count + 1` if test $_count -gt $_max; then _max=$_count lt_cv_path_SED=$_sed fi done done rm -rf "$tmp" ]) if test "X$SED" != "X"; then lt_cv_path_SED=$SED else SED=$lt_cv_path_SED fi AC_MSG_RESULT([$SED]) ]) # Configure paths for SDL # Sam Lantinga 9/21/99 # stolen from Manish Singh # stolen back from Frank Belew # stolen from Manish Singh # Shamelessly stolen from Owen Taylor dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl AC_DEFUN(AM_PATH_SDL, [dnl dnl Get the cflags and libraries from the sdl-config script dnl AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], sdl_prefix="$withval", sdl_prefix="") AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], sdl_exec_prefix="$withval", sdl_exec_prefix="") AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], , enable_sdltest=yes) if test x$sdl_exec_prefix != x ; then sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config fi fi if test x$sdl_prefix != x ; then sdl_args="$sdl_args --prefix=$sdl_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_prefix/bin/sdl-config fi fi AC_REQUIRE([AC_CANONICAL_TARGET]) PATH="$prefix/bin:$prefix/usr/bin:$PATH" AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) min_sdl_version=ifelse([$1], ,0.11.0,$1) AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) no_sdl="" if test "$SDL_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" dnl dnl Now check if the installed SDL is sufficiently new. (Also sanity dnl checks the results of sdl-config to some extent dnl rm -f conf.sdltest AC_TRY_RUN([ #include #include #include #include "SDL.h" char* my_strdup (char *str) { char *new_str; if (str) { new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); strcpy (new_str, str); } else new_str = NULL; return new_str; } int main (int argc, char *argv[]) { int major, minor, micro; char *tmp_version; /* This hangs on some systems (?) system ("touch conf.sdltest"); */ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = my_strdup("$min_sdl_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); printf("*** to point to the correct copy of sdl-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } ],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$SDL_CONFIG" = "no" ; then echo "*** The sdl-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL_CONFIG environment variable to the" echo "*** full path to sdl-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" AC_TRY_LINK([ #include #include "SDL.h" int main(int argc, char *argv[]) { return 0; } #undef main #define main K_and_R_C_main ], [ return 0; ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) rm -f conf.sdltest ]) exult-1.2/files/0000777000175000001440000000000010062225325007355 5exult-1.2/files/zip/0000777000175000001440000000000010062225325010157 5exult-1.2/files/zip/zip.c0000644000175000001440000005234307427573244011071 /* zip.c -- IO on .zip files using zlib Version 0.15 beta, Mar 19th, 1998, Modified by Ryan Nunn. Nov 9th 2001 Read zip.h for more info */ /* Added by Ryan Nunn */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_ZIP_SUPPORT #include #include #include #include "zlib.h" #include "zip.h" /* Added by Ryan Nunn to overcome DEF_MEM_LEVEL being undeclared */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif /* Added by Max Horn - work around a work around in zlib 1.1.3 on MacOS */ #if defined(MACOS) || defined(TARGET_OS_MAC) typedef unsigned char Byte; /* 8 bits */ #endif #ifndef VERSIONMADEBY # define VERSIONMADEBY (0x0) /* platform depedent */ #endif #ifndef Z_BUFSIZE #define Z_BUFSIZE (16384) #endif #ifndef Z_MAXFILENAMEINZIP #define Z_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif /* #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif const char zip_copyright[] = " zip 0.15 Copyright 1998 Gilles Vollant "; #define SIZEDATA_INDATABLOCK (4096-(4*4)) #define LOCALHEADERMAGIC (0x04034b50) #define CENTRALHEADERMAGIC (0x02014b50) #define ENDHEADERMAGIC (0x06054b50) #define FLAG_LOCALHEADER_OFFSET (0x06) #define CRC_LOCALHEADER_OFFSET (0x0e) #define SIZECENTRALHEADER (0x2e) /* 46 */ typedef struct linkedlist_datablock_internal_s { struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; uLong unused; /* for future use and alignement */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; typedef struct linkedlist_data_s { linkedlist_datablock_internal* first_block; linkedlist_datablock_internal* last_block; } linkedlist_data; typedef struct { z_stream stream; /* zLib stream structure for inflate */ int stream_initialised; /* 1 is stream is initialised */ uInt pos_in_buffered_data; /* last written byte in buffered_data */ uLong pos_local_header; /* offset of the local header of the file currenty writing */ char* central_header; /* central header data for the current file */ uLong size_centralheader; /* size of the central header for cur file */ uLong flag; /* flag of the file currently writing */ int method; /* compression method of file currenty wr.*/ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; } curfile_info; typedef struct { FILE * filezip; linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ curfile_info ci; /* info on the file curretly writing */ uLong begin_pos; /* position of the beginning of the zipfile */ uLong number_entry; } zip_internal; static linkedlist_datablock_internal* allocate_new_datablock() { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); if (ldi!=NULL) { ldi->next_datablock = NULL ; ldi->filled_in_this_block = 0 ; ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; } return ldi; } static void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; TRYFREE(ldi); ldi = ldinext; } } static void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } static void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } static int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; if (ll==NULL) return ZIP_INTERNALERROR; if (ll->last_block == NULL) { ll->first_block = ll->last_block = allocate_new_datablock(); if (ll->first_block == NULL) return ZIP_INTERNALERROR; } ldi = ll->last_block; from_copy = (unsigned char*)buf; while (len>0) { uInt copy_this; uInt i; unsigned char* to_copy; if (ldi->avail_in_this_block==0) { ldi->next_datablock = allocate_new_datablock(); if (ldi->next_datablock == NULL) return ZIP_INTERNALERROR; ldi = ldi->next_datablock ; ll->last_block = ldi; } if (ldi->avail_in_this_block < len) copy_this = (uInt)ldi->avail_in_this_block; else copy_this = (uInt)len; to_copy = &(ldi->data[ldi->filled_in_this_block]); for (i=0;ifilled_in_this_block += copy_this; ldi->avail_in_this_block -= copy_this; from_copy += copy_this ; len -= copy_this; } return ZIP_OK; } static int write_datablock(FILE* fout, linkedlist_data* ll) { linkedlist_datablock_internal* ldi; ldi = ll->first_block; while (ldi!=NULL) { if (ldi->filled_in_this_block > 0) if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1) return ZIP_ERRNO; ldi = ldi->next_datablock; } return ZIP_OK; } /****************************************************************************/ /* =========================================================================== Outputs a long in LSB order to the given file nbByte == 1, 2 or 4 (byte, short or long) */ static int ziplocal_putValue (FILE *file, uLong x, int nbByte); static int ziplocal_putValue (FILE *file, uLong x, int nbByte) { unsigned char buf[4]; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } if (fwrite(buf,nbByte,1,file)!=1) return ZIP_ERRNO; else return ZIP_OK; } static void ziplocal_putValue_inmemory (void* dest, uLong x, int nbByte); static void ziplocal_putValue_inmemory (void* dest, uLong x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } } /****************************************************************************/ static uLong ziplocal_TmzDateToDosDate(const tm_zip* ptm, uLong uLongdosDate) { uLong year = (uLong)ptm->tm_year; if (year>1980) year-=1980; else if (year>80) year-=80; return (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ extern zipFile ZEXPORT zipOpen (const char *pathname, int append) { zip_internal ziinit; zip_internal* zi; ziinit.filezip = NULL; /* Start changes by Ryan Nunn to fix append mode bug */ /* If append, use r+b mode, will fail if not exist */ if (append != 0) ziinit.filezip = fopen(pathname,"r+b"); /* If not append, or failed, use wb */ if (ziinit.filezip == NULL) ziinit.filezip = fopen(pathname,"wb"); /* Still doesn't exist, means can't create */ if (ziinit.filezip == NULL) return NULL; /* Make sure we are at the end of the file */ fseek (ziinit.filezip, 0, SEEK_END); /* End changes by Ryan Nunn to fix append mode bug */ ziinit.begin_pos = ftell(ziinit.filezip); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; init_linkedlist(&(ziinit.central_dir)); zi = (zip_internal*)ALLOC(sizeof(zip_internal)); if (zi==NULL) { fclose(ziinit.filezip); return NULL; } *zi = ziinit; return (zipFile)zi; } extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level) { zip_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; if ((method!=0) && (method!=Z_DEFLATED)) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); if (err != ZIP_OK) return err; } if (filename==NULL) filename="-"; if (comment==NULL) size_comment = 0; else size_comment = strlen(comment); size_filename = strlen(filename); if (zipfi == NULL) zi->ci.dosDate = 0; else { if (zipfi->dosDate != 0) zi->ci.dosDate = zipfi->dosDate; else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); } zi->ci.flag = 0; if ((level==8) || (level==9)) zi->ci.flag |= 2; if ((level==2)) zi->ci.flag |= 4; if ((level==1)) zi->ci.flag |= 6; zi->ci.crc32 = 0; zi->ci.method = method; zi->ci.stream_initialised = 0; zi->ci.pos_in_buffered_data = 0; zi->ci.pos_local_header = ftell(zi->filezip); zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); /* version info */ ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ if (zipfi==NULL) ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); else ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); if (zipfi==NULL) ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); else ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4); for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = *(((const char*)extrafield_global)+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ size_extrafield_global+i) = *(filename+i); if (zi->ci.central_header == NULL) return ZIP_INTERNALERROR; /* write the local header */ err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4); if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */ if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2); if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2); if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4); if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2); if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2); if ((err==ZIP_OK) && (size_filename>0)) if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1) err = ZIP_ERRNO; if ((err==ZIP_OK) && (size_extrafield_local>0)) if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip) !=1) err = ZIP_ERRNO; zi->ci.stream.avail_in = (uInt)0; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; zi->ci.stream.total_in = 0; zi->ci.stream.total_out = 0; if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED)) { zi->ci.stream.zalloc = (alloc_func)0; zi->ci.stream.zfree = (free_func)0; zi->ci.stream.opaque = (voidpf)0; err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); if (err==Z_OK) zi->ci.stream_initialised = 1; } if (err==Z_OK) zi->in_opened_file_inzip = 1; return err; } extern int ZEXPORT zipWriteInFileInZip (zipFile file, const voidp buf, unsigned len) { zip_internal* zi; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.next_in = (Bytef *)buf; zi->ci.stream.avail_in = len; zi->ci.crc32 = crc32(zi->ci.crc32,(Bytef *)buf,len); while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) { if (zi->ci.stream.avail_out == 0) { if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) !=1) err = ZIP_ERRNO; zi->ci.pos_in_buffered_data = 0; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } if (zi->ci.method == Z_DEFLATED) { uLong uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_NO_FLUSH); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } else { uInt copy_this,i; if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) copy_this = zi->ci.stream.avail_in; else copy_this = zi->ci.stream.avail_out; for (i=0;ici.stream.next_out)+i) = *(((const char*)zi->ci.stream.next_in)+i); { zi->ci.stream.avail_in -= copy_this; zi->ci.stream.avail_out-= copy_this; zi->ci.stream.next_in+= copy_this; zi->ci.stream.next_out+= copy_this; zi->ci.stream.total_in+= copy_this; zi->ci.stream.total_out+= copy_this; zi->ci.pos_in_buffered_data += copy_this; } } } return 0; } extern int ZEXPORT zipCloseFileInZip (zipFile file) { zip_internal* zi; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.avail_in = 0; if (zi->ci.method == Z_DEFLATED) while (err==ZIP_OK) { uLong uTotalOutBefore; if (zi->ci.stream.avail_out == 0) { if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) !=1) err = ZIP_ERRNO; zi->ci.pos_in_buffered_data = 0; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_FINISH); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } if (err==Z_STREAM_END) err=ZIP_OK; /* this is normal */ if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) !=1) err = ZIP_ERRNO; if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK)) { err=deflateEnd(&zi->ci.stream); zi->ci.stream_initialised = 0; } ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/ ziplocal_putValue_inmemory(zi->ci.central_header+20, (uLong)zi->ci.stream.total_out,4); /*compr size*/ ziplocal_putValue_inmemory(zi->ci.central_header+24, (uLong)zi->ci.stream.total_in,4); /*uncompr size*/ if (err==ZIP_OK) err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, (uLong)zi->ci.size_centralheader); free(zi->ci.central_header); if (err==ZIP_OK) { long cur_pos_inzip = ftell(zi->filezip); if (fseek(zi->filezip, zi->ci.pos_local_header + 14,SEEK_SET)!=0) err = ZIP_ERRNO; if (err==ZIP_OK) err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */ if (err==ZIP_OK) /* compressed size, unknown */ err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); if (err==ZIP_OK) /* uncompressed size, unknown */ err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4); if (fseek(zi->filezip, cur_pos_inzip,SEEK_SET)!=0) err = ZIP_ERRNO; } zi->number_entry ++; zi->in_opened_file_inzip = 0; return err; } extern int ZEXPORT zipClose (zipFile file, const char* global_comment) { zip_internal* zi; int err = 0; uLong size_centraldir = 0; uLong centraldir_pos_inzip ; uInt size_global_comment; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); } if (global_comment==NULL) size_global_comment = 0; else size_global_comment = strlen(global_comment); centraldir_pos_inzip = ftell(zi->filezip); if (err==ZIP_OK) { linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; while (ldi!=NULL) { if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block, 1,zi->filezip) !=1 ) err = ZIP_ERRNO; size_centraldir += ldi->filled_in_this_block; ldi = ldi->next_datablock; } } free_datablock(zi->central_dir.first_block); if (err==ZIP_OK) /* Magic End */ err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4); if (err==ZIP_OK) /* number of this disk */ err = ziplocal_putValue(zi->filezip,(uLong)0,2); if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = ziplocal_putValue(zi->filezip,(uLong)0,2); if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); if (err==ZIP_OK) /* total number of entries in the central dir */ err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); if (err==ZIP_OK) /* size of the central directory */ err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4); if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4); if (err==ZIP_OK) /* zipfile comment length */ err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2); if ((err==ZIP_OK) && (size_global_comment>0)) if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 ) err = ZIP_ERRNO; fclose(zi->filezip); TRYFREE(zi); return err; } /* Added by Ryan Nunn */ #endif /*HAVE_ZIP_SUPPORT*/ exult-1.2/files/zip/zip.h0000644000175000001440000001216507733065752011074 /* zip.h -- IO for compress .zip files using zlib Version 0.15 alpha, Mar 19th, 1998, Copyright (C) 1998 Gilles Vollant Modified by Ryan Nunn. Nov 9th 2001 This unzip package allow creates .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. Encryption and multi volume ZipFile (span) are not supported. Old compressions used by old PKZip 1.x are not supported For uncompress .zip file, look at unzip.h THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE CAN CHANGE IN FUTURE VERSION !! I WAIT FEEDBACK at mail info@winimage.com Visit also http://www.winimage.com/zLibDll/unzip.html for evolution Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* for more info about .ZIP format, see ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip PkWare has also a specification at : ftp://ftp.pkware.com/probdesc.zip */ #ifndef _zip_H #define _zip_H /* Added by Ryan Nunn */ #ifdef HAVE_ZIP_SUPPORT #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include "zlib.h" #endif #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagzipFile__ { int unused; } zipFile__; typedef zipFile__ *zipFile; #else typedef voidp zipFile; #endif #define ZIP_OK (0) #define ZIP_ERRNO (Z_ERRNO) #define ZIP_PARAMERROR (-102) #define ZIP_INTERNALERROR (-104) /* tm_zip contain date/time info */ typedef struct tm_zip_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct { tm_zip tmz_date; /* date in understandable format */ uLong dosDate; /* if dos_date == 0, tmu_date is used */ /* uLong flag; */ /* general purpose bit flag 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ } zip_fileinfo; extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); /* Create a zipfile. pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on an Unix computer "zlib/zlib111.zip". if the file pathname exist and append=1, the zip will be created at the end of the file. (useful if the file contain a self extractor code) If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. */ extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level)); /* Open a file in the ZIP for writing. filename : the filename in zip (if NULL, '-' without quote will be used *zipfi contain supplemental information if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local contains the extrafield data the the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header if comment != NULL, comment contain the comment string method contain the compression method (0 for store, Z_DEFLATED for deflate) level contain the level of compression (can be Z_DEFAULT_COMPRESSION) */ extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const voidp buf, unsigned len)); /* Write data in the zipfile */ extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); /* Close the current file in the zipfile */ extern int ZEXPORT zipClose OF((zipFile file, const char* global_comment)); /* Close the zipfile */ #ifdef __cplusplus } #endif /* Added by Ryan Nunn */ #endif /*HAVE_ZIP_SUPPORT*/ #endif /* _zip_H */ exult-1.2/files/zip/Makefile.am0000644000175000001440000000031507427573244012147 INCLUDES = $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libminizip.la libminizip_la_SOURCES = \ zip.c \ zip.h \ unzip.c \ unzip.h CLEANFILES = *~ exult-1.2/files/zip/Makefile.in0000644000175000001440000002250310061527046012146 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libminizip.la libminizip_la_SOURCES = \ zip.c \ zip.h \ unzip.c \ unzip.h CLEANFILES = *~ subdir = files/zip mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libminizip_la_LDFLAGS = libminizip_la_LIBADD = am_libminizip_la_OBJECTS = zip.lo unzip.lo libminizip_la_OBJECTS = $(am_libminizip_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/unzip.Plo $(DEPDIR)/zip.Plo COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ DIST_SOURCES = $(libminizip_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libminizip_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu files/zip/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libminizip.la: $(libminizip_la_OBJECTS) $(libminizip_la_DEPENDENCIES) $(LINK) $(libminizip_la_LDFLAGS) $(libminizip_la_OBJECTS) $(libminizip_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/unzip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/zip.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .c.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$< .c.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `cygpath -w $<` .c.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CCDEPMODE = @CCDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/files/zip/unzip.c0000644000175000001440000010226407427573244011432 /* unzip.c -- IO on .zip files using zlib Version 0.15 beta, Mar 19th, 1998, Modified by Ryan Nunn. Nov 9th 2001 Read unzip.h for more info */ /* Added by Ryan Nunn */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_ZIP_SUPPORT #include #include #include #include "zlib.h" #include "unzip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ !defined(CASESENSITIVITYDEFAULT_NO) #define CASESENSITIVITYDEFAULT_NO #endif #ifndef UNZ_BUFSIZE #define UNZ_BUFSIZE (16384) #endif #ifndef UNZ_MAXFILENAMEINZIP #define UNZ_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif const char unz_copyright[] = " unzip 0.15 Copyright 1998 Gilles Vollant "; /* unz_file_info_interntal contain internal info about a file in zipfile*/ typedef struct unz_file_info_internal_s { uLong offset_curfile;/* relative offset of local header 4 bytes */ } unz_file_info_internal; /* file_in_zip_read_info_s contain internal information about a file in zipfile, when reading and decompress it */ typedef struct { char *read_buffer; /* internal buffer for compressed data */ z_stream stream; /* zLib stream structure for inflate */ uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ uLong offset_local_extrafield;/* offset of the local extra field */ uInt size_local_extrafield;/* size of the local extra field */ uLong pos_local_extrafield; /* position in the local extra field in read*/ uLong crc32; /* crc32 of all data uncompressed */ uLong crc32_wait; /* crc32 we must obtain after decompress all */ uLong rest_read_compressed; /* number of byte to be decompressed */ uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ FILE* file; /* io structore of the zipfile */ uLong compression_method; /* compression method (0==store) */ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ } file_in_zip_read_info_s; /* unz_s contain internal information about the zipfile */ typedef struct { FILE* file; /* io structore of the zipfile */ unz_global_info gi; /* public global information */ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ uLong num_file; /* number of the current file in the zipfile*/ uLong pos_in_central_dir; /* pos of the current file in the central dir*/ uLong current_file_ok; /* flag about the usability of the current file*/ uLong central_pos; /* position of the beginning of the central dir*/ uLong size_central_dir; /* size of the central directory */ uLong offset_central_dir; /* offset of start of central directory with respect to the starting disk number */ unz_file_info cur_file_info; /* public info about the current file in zip*/ unz_file_info_internal cur_file_info_internal; /* private info about it*/ file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current file if we are decompressing it */ } unz_s; /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. */ local int unzlocal_getByte(FILE *fin, int *pi) { unsigned char c; int err = fread(&c, 1, 1, fin); if (err==1) { *pi = (int)c; return UNZ_OK; } else { if (ferror(fin)) return UNZ_ERRNO; else return UNZ_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int unzlocal_getShort (FILE*fin, uLong *pX) { uLong x ; int i; int err; err = unzlocal_getByte(fin,&i); x = (uLong)i; if (err==UNZ_OK) err = unzlocal_getByte(fin,&i); x += ((uLong)i)<<8; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unzlocal_getLong (FILE*fin, uLong *pX) { uLong x ; int i; int err; err = unzlocal_getByte(fin,&i); x = (uLong)i; if (err==UNZ_OK) err = unzlocal_getByte(fin,&i); x += ((uLong)i)<<8; if (err==UNZ_OK) err = unzlocal_getByte(fin,&i); x += ((uLong)i)<<16; if (err==UNZ_OK) err = unzlocal_getByte(fin,&i); x += ((uLong)i)<<24; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } /* My own strcmpi / strcasecmp */ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); char c2=*(fileName2++); if ((c1>='a') && (c1<='z')) c1 -= 0x20; if ((c2>='a') && (c2<='z')) c2 -= 0x20; if (c1=='\0') return ((c2=='\0') ? 0 : -1); if (c2=='\0') return 1; if (c1c2) return 1; } } #ifdef CASESENSITIVITYDEFAULT_NO #define CASESENSITIVITYDEFAULTVALUE 2 #else #define CASESENSITIVITYDEFAULTVALUE 1 #endif #ifndef STRCMPCASENOSENTIVEFUNCTION #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal #endif /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); } #define BUFREADCOMMENT (0x400) /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local uLong unzlocal_SearchCentralDir(FILE *fin) { unsigned char* buf; uLong uSizeFile; uLong uBackRead; uLong uMaxBack=0xffff; /* maximum size of global comment */ uLong uPosFound=0; if (fseek(fin,0,SEEK_END) != 0) return 0; uSizeFile = ftell( fin ); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); if (fseek(fin,uReadPos,SEEK_SET)!=0) break; if (fread(buf,(uInt)uReadSize,1,fin)!=1) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } /* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer "zlib/zlib109.zip". If the zipfile cannot be opened (file don't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ extern unzFile ZEXPORT unzOpen (const char *path) { unz_s us; unz_s *s; uLong central_pos,uL; FILE * fin ; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ int err=UNZ_OK; if (unz_copyright[0]!=' ') return NULL; fin=fopen(path,"rb"); if (fin==NULL) return NULL; central_pos = unzlocal_SearchCentralDir(fin); if (central_pos==0) err=UNZ_ERRNO; if (fseek(fin,central_pos,SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unzlocal_getLong(fin,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir on this disk */ if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir */ if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* zipfile comment length */ if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; if ((central_pospfile_in_zip_read!=NULL) unzCloseCurrentFile(file); fclose(s->file); TRYFREE(s); return UNZ_OK; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info) { unz_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; *pglobal_info=s->gi; return UNZ_OK; } /* Translate date/time from Dos format to tm_unz (readable more easilty) */ local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) { uLong uDate; uDate = (uLong)(ulDosDate>>16); ptm->tm_mday = (uInt)(uDate&0x1f) ; ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; } /* Get Info about the current file in the zipfile, with internal only info */ local int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info, unz_file_info_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize); local int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info, unz_file_info_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize) { unz_s* s; unz_file_info file_info; unz_file_info_internal file_info_internal; int err=UNZ_OK; uLong uMagic; long lSeek=0; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) err=UNZ_ERRNO; /* we check the magic */ if (err==UNZ_OK) { if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x02014b50) err=UNZ_BADZIPFILE; } if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) err=UNZ_ERRNO; unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) err=UNZ_ERRNO; lSeek+=file_info.size_filename; if ((err==UNZ_OK) && (szFileName!=NULL)) { uLong uSizeRead ; if (file_info.size_filename0) && (fileNameBufferSize>0)) if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) err=UNZ_ERRNO; lSeek -= uSizeRead; } if ((err==UNZ_OK) && (extraField!=NULL)) { uLong uSizeRead ; if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) err=UNZ_ERRNO; lSeek += file_info.size_file_extra - uSizeRead; } else lSeek+=file_info.size_file_extra; if ((err==UNZ_OK) && (szComment!=NULL)) { uLong uSizeRead ; if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) err=UNZ_ERRNO; lSeek+=file_info.size_file_comment - uSizeRead; } else lSeek+=file_info.size_file_comment; if ((err==UNZ_OK) && (pfile_info!=NULL)) *pfile_info=file_info; if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) *pfile_info_internal=file_info_internal; return err; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize) { return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); } /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToFirstFile (unzFile file) { int err=UNZ_OK; unz_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; s->pos_in_central_dir=s->offset_central_dir; s->num_file=0; err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzGoToNextFile (unzFile file) { unz_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; if (s->num_file+1==s->gi.number_entry) return UNZ_END_OF_LIST_OF_FILE; s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; s->num_file++; err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzipStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) { unz_s* s; int err; uLong num_fileSaved; uLong pos_in_central_dirSaved; if (file==NULL) return UNZ_PARAMERROR; if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; num_fileSaved = s->num_file; pos_in_central_dirSaved = s->pos_in_central_dir; err = unzGoToFirstFile(file); while (err == UNZ_OK) { char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; unzGetCurrentFileInfo(file,NULL, szCurrentFileName,sizeof(szCurrentFileName)-1, NULL,0,NULL,0); if (unzStringFileNameCompare(szCurrentFileName, szFileName,iCaseSensitivity)==0) return UNZ_OK; err = unzGoToNextFile(file); } s->num_file = num_fileSaved ; s->pos_in_central_dir = pos_in_central_dirSaved ; return err; } /* Read the local header of the current zipfile Check the coherency of the local header and info in the end of central directory about this file store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ local int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar, uLong *poffset_local_extrafield, uInt *psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; int err=UNZ_OK; *piSizeVar = 0; *poffset_local_extrafield = 0; *psize_local_extrafield = 0; if (fseek(s->file,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO; if (err==UNZ_OK) { if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; } if (unzlocal_getShort(s->file,&uData) != UNZ_OK) err=UNZ_ERRNO; /* else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) err=UNZ_BADZIPFILE; */ if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(s->file,&uData) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) err=UNZ_BADZIPFILE; if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ err=UNZ_ERRNO; if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) err=UNZ_BADZIPFILE; *piSizeVar += (uInt)size_filename; if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) err=UNZ_ERRNO; *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; *psize_local_extrafield = (uInt)size_extra_field; *piSizeVar += (uInt)size_extra_field; return err; } /* Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile (unzFile file) { int err=UNZ_OK; int Store; uInt iSizeVar; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; uLong offset_local_extrafield; /* offset of the local extra field */ uInt size_local_extrafield; /* size of the local extra field */ if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_PARAMERROR; if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) return UNZ_BADZIPFILE; pfile_in_zip_read_info = (file_in_zip_read_info_s*) ALLOC(sizeof(file_in_zip_read_info_s)); if (pfile_in_zip_read_info==NULL) return UNZ_INTERNALERROR; pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; if (pfile_in_zip_read_info->read_buffer==NULL) { TRYFREE(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } pfile_in_zip_read_info->stream_initialised=0; if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; Store = s->cur_file_info.compression_method==0; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; pfile_in_zip_read_info->file=s->file; pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; pfile_in_zip_read_info->stream.total_out = 0; if (!Store) { pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=1; /* windowBits is passed < 0 to tell that there is no zlib header. * Note that in this case inflate *requires* an extra "dummy" byte * after the compressed stream in order to complete decompression and * return Z_STREAM_END. * In unzip, i don't wait absolutely Z_STREAM_END because I known the * size of both compressed and uncompressed data */ } pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ; pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ; pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; pfile_in_zip_read_info->stream.avail_in = (uInt)0; s->pfile_in_zip_read = pfile_in_zip_read_info; return UNZ_OK; } /* Read bytes from the current file. buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE; if (len==0) return 0; pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; pfile_in_zip_read_info->stream.avail_out = (uInt)len; if (len>pfile_in_zip_read_info->rest_read_uncompressed) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; while (pfile_in_zip_read_info->stream.avail_out>0) { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) { uInt uReadThis = UNZ_BUFSIZE; if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; if (uReadThis == 0) return UNZ_EOF; if (fseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO; if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO; pfile_in_zip_read_info->pos_in_zipfile += uReadThis; pfile_in_zip_read_info->rest_read_compressed-=uReadThis; pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer; pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; } if (pfile_in_zip_read_info->compression_method==0) { uInt uDoCopy,i ; if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) uDoCopy = pfile_in_zip_read_info->stream.avail_out ; else uDoCopy = pfile_in_zip_read_info->stream.avail_in ; for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; pfile_in_zip_read_info->stream.avail_in -= uDoCopy; pfile_in_zip_read_info->stream.avail_out -= uDoCopy; pfile_in_zip_read_info->stream.next_out += uDoCopy; pfile_in_zip_read_info->stream.next_in += uDoCopy; pfile_in_zip_read_info->stream.total_out += uDoCopy; iRead += uDoCopy; } else { uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; uLong uOutThis; int flush=Z_SYNC_FLUSH; uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; bufBefore = pfile_in_zip_read_info->stream.next_out; /* if ((pfile_in_zip_read_info->rest_read_uncompressed == pfile_in_zip_read_info->stream.avail_out) && (pfile_in_zip_read_info->rest_read_compressed == 0)) flush = Z_FINISH; */ err=inflate(&pfile_in_zip_read_info->stream,flush); uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); if (err==Z_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=Z_OK) break; } } if (err==Z_OK) return iRead; return err; } /* Give the current position in uncompressed data */ extern z_off_t ZEXPORT unztell (unzFile file) { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; return (z_off_t)pfile_in_zip_read_info->stream.total_out; } /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzeof (unzFile file) { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->rest_read_uncompressed == 0) return 1; else return 0; } /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field that can be read if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; uInt read_now; uLong size_to_read; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield); if (buf==NULL) return (int)size_to_read; if (len>size_to_read) read_now = (uInt)size_to_read; else read_now = (uInt)len ; if (read_now==0) return 0; if (fseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) return UNZ_ERRNO; if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO; return (int)read_now; } /* Close the file in zip opened with unzipOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzCloseCurrentFile (unzFile file) { int err=UNZ_OK; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->rest_read_uncompressed == 0) { if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } TRYFREE(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised) inflateEnd(&pfile_in_zip_read_info->stream); pfile_in_zip_read_info->stream_initialised = 0; TRYFREE(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; return err; } /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ extern int ZEXPORT unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf) { unz_s* s; uLong uReadThis ; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; uReadThis = uSizeBuf; if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) return UNZ_ERRNO; if (uReadThis>0) { *szComment='\0'; if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) return UNZ_ERRNO; } if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } /* Added by Ryan Nunn */ #endif /*HAVE_ZIP_SUPPORT*/ exult-1.2/files/zip/unzip.h0000644000175000001440000002353307733065752011440 /* unzip.h -- IO for uncompress .zip files using zlib Version 0.15 beta, Mar 19th, 1998, Copyright (C) 1998 Gilles Vollant Modified by Ryan Nunn. Nov 9th 2001 This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. Encryption and multi volume ZipFile (span) are not supported. Old compressions used by old PKZip 1.x are not supported THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE CAN CHANGE IN FUTURE VERSION !! I WAIT FEEDBACK at mail info@winimage.com Visit also http://www.winimage.com/zLibDll/unzip.html for evolution Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* for more info about .ZIP format, see ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip PkWare has also a specification at : ftp://ftp.pkware.com/probdesc.zip */ #ifndef _unz_H #define _unz_H /* Added by Ryan Nunn */ #ifdef HAVE_ZIP_SUPPORT #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include "zlib.h" #endif #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagunzFile__ { int unused; } unzFile__; typedef unzFile__ *unzFile; #else typedef voidp unzFile; #endif #define UNZ_OK (0) #define UNZ_END_OF_LIST_OF_FILE (-100) #define UNZ_ERRNO (Z_ERRNO) #define UNZ_EOF (0) #define UNZ_PARAMERROR (-102) #define UNZ_BADZIPFILE (-103) #define UNZ_INTERNALERROR (-104) #define UNZ_CRCERROR (-105) /* tm_unz contain date/time info */ typedef struct tm_unz_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_unz; /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ typedef struct unz_global_info_s { uLong number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info; /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_info_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ uLong compressed_size; /* compressed size 4 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info; extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, const char* fileName2, int iCaseSensitivity)); /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern unzFile ZEXPORT unzOpen OF((const char *path)); /* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer "zlib/zlib111.zip". If the zipfile cannot be opened (file don't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ extern int ZEXPORT unzClose OF((unzFile file)); /* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info)); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *szComment, uLong uSizeBuf)); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToNextFile OF((unzFile file)); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzLocateFile OF((unzFile file, const char *szFileName, int iCaseSensitivity)); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); /* Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain somes info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) */ /***************************************************************************/ /* for reading the content of the current zipfile, you can open it, read data from it, and close it (you can close it before reading all the file) */ extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len)); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern z_off_t ZEXPORT unztell OF((unzFile file)); /* Give the current position in uncompressed data */ extern int ZEXPORT unzeof OF((unzFile file)); /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len)); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ #ifdef __cplusplus } #endif /* Added by Ryan Nunn */ #endif /*HAVE_ZIP_SUPPORT*/ #endif /* _unz_H */ exult-1.2/files/IFF.cc0000644000175000001440000000561510054030556010214 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "IFF.h" #ifndef ALPHA_LINUX_CXX # include #endif #include #include "exceptions.h" #include "utils.h" using std::string; using std::vector; #ifndef UNDER_CE using std::cout; using std::cerr; using std::endl; using std::FILE; using std::memcmp; using std::memset; using std::size_t; #endif IFF::IFF(const string &n) : U7file(n) { IndexIFFFile(); } void IFF::IndexIFFFile(void) { FILE *fp; char ckid[4]; fp=U7open(filename.c_str(),"rb"); std::fread(ckid,4,1,fp); if(memcmp(ckid,"FORM",4)) throw wrong_file_type_exception(filename,"IFF"); // Not an IFF file we recognise #ifdef DEBUG cout << "Okay. It looks like an IFF file chunk" << endl; #endif long full_length; full_length = Read4high(fp); #ifdef DEBUG cout << "length looks like: " << full_length << endl; #endif fseek(fp,4,SEEK_CUR); // We don't really need to know what the general data type is /* -the objects entries entry = type, size, object, [even] type = 4 chars representing the type of this object size = reversed longint (size of the entry excluding the first 8 bytes) even = 1 byte (set to 0) present only to get an even number of bytes (the objects found in U7 IFF files have the following format:) object = name, data name = 8 chars (filled with 0s) data = the data of the object */ while(ftell(fp) < full_length) { Reference r; char type[5]; memset(type,0,sizeof(type)); std::fread(type,4,1,fp); // 4 bytes of type if(type[0]<32) { // We've missed the target. Try to correct fseek(fp,-3,SEEK_CUR); continue; } r.size=Read4high(fp); // 4 bytes for len r.offset=ftell(fp); if(r.size==0||r.offset==0) break; object_list.push_back(r); fseek(fp,r.offset+r.size,SEEK_SET); } fclose(fp); } char * IFF::retrieve(uint32 objnum, size_t &len) { FILE *fp; char *buffer; if (objnum >= object_list.size()) throw exult_exception("objnum too large in IFF::retrieve()"); fp = U7open(filename.c_str(), "rb"); fseek(fp, object_list[objnum].offset, SEEK_SET); len = object_list[objnum].size; buffer = new char[len]; std::fread(buffer, len, 1, fp); fclose(fp); return buffer; } exult-1.2/files/Flat.h0000644000175000001440000000220207431004107010323 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _FLAT_H_ #define _FLAT_H_ #include #include "U7file.h" #include "common_types.h" class Flat : public virtual U7file { public: Flat(const std::string &name); Flat(const Flat &t) {} virtual uint32 number_of_objects(void) { return 1; }; virtual char * retrieve(uint32 objnum, std::size_t &len); // To a memory block virtual const char *get_archive_type() { return "FLAT"; }; private: Flat(); }; #endif exult-1.2/files/Flex.h0000644000175000001440000000520607502172225010350 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __FLEX_H_ #define __FLEX_H_ #ifndef PENTAGRAM // DONT'T INCLUDE THIS IN PENTAGRAM! #include #include #include #include "common_types.h" #include "U7file.h" class DataSource; class Flex : public U7file { protected: char title[80]; uint32 magic1; uint32 count; uint32 magic2; uint32 padding[9]; struct Reference { uint32 offset; uint32 size; Reference() : offset(0),size(0) {}; }; std::vector object_list; public: Flex(const std::string &fname); Flex(const Flex &f) : magic1(f.magic1),count(f.count),magic2(f.magic2),object_list(f.object_list) { std::memcpy(title,f.title,sizeof(title)); std::memcpy(padding,f.padding,sizeof(padding)); } Flex &operator=(const Flex &f) { magic1=f.magic1; count=f.count; magic2=f.magic2; object_list=f.object_list; std::memcpy(title,f.title,sizeof(title)); std::memcpy(padding,f.padding,sizeof(padding)); return *this; } virtual uint32 number_of_objects(void) { return object_list.size(); }; virtual char * retrieve(uint32 objnum,std::size_t &len); // To a memory block virtual const char *get_archive_type() { return "FLEX"; }; // Write header for a Flex file. static void write_header(DataSource* out, const char *title, int count); static bool is_flex(DataSource *in); static bool is_flex(const char *fname); private: Flex(); // No default constructor void IndexFlexFile(void); }; /* * This is for writing out a whole Flex file. */ class Flex_writer { std::ofstream *out; // What we're writing to. int count; // # entries. int index; // Current index. long cur_start; // Start of cur. entry being written. uint8 *table; // Table of offsets & lengths. uint8 *tptr; // ->into table. public: Flex_writer(std::ofstream &o, const char *title, int cnt); ~Flex_writer(); void mark_section_done(); // Finished writing out a section. bool close(); // All done. }; #endif // PENTAGRAM #endif exult-1.2/files/IFF.h0000644000175000001440000000422407431004107010047 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __IFF_H_ #define __IFF_H_ #include #include #include "common_types.h" #include "U7file.h" class IFF : public U7file { public: struct IFFhdr { char form_magic[4]; uint32 size; char data_type[4]; IFFhdr() {} IFFhdr(const IFFhdr &i) : size(i.size) { std::memcpy(form_magic,i.form_magic,sizeof(form_magic)); std::memcpy(data_type,i.data_type,sizeof(data_type)); } IFFhdr &operator=(const IFFhdr &i) { size=i.size; std::memcpy(form_magic,i.form_magic,sizeof(form_magic)); std::memcpy(data_type,i.data_type,sizeof(data_type)); return *this; } }; struct IFFobject { char type[4]; uint32 size; char even; }; struct u7IFFobj { char name[8]; // char data[]; // Variable }; struct Reference { uint32 offset; uint32 size; Reference() : offset(0),size(0) {}; }; protected: IFFhdr header; std::vector object_list; public: IFF(const std::string &fname); IFF(const IFF &i) : header(i.header),object_list(i.object_list) {} IFF operator=(const IFF &i) { header=i.header; object_list=i.object_list; return *this; } // char *read_object(int objnum,uint32 &length); virtual uint32 number_of_objects(void) { return object_list.size(); }; virtual char * retrieve(uint32 objnum,std::size_t &len); // To a memory block virtual const char* get_archive_type() { return "IFF"; }; private: IFF(); // No default constructor void IndexIFFFile(void); }; #endif exult-1.2/files/msgfile.cc0000644000175000001440000000505207724430451011241 /** ** Msgfile.cc - Read in text message file. ** ** Written: 6/25/03 **/ /* * Copyright (C) 2002-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "utils.h" using std::istream; using std::cerr; using std::endl; using std::vector; /* * Read in text, where each line is of the form "nnn:sssss", where nnn is * to be the Flex entry #, and anything after the ':' is the string to * store. * NOTES: Entry #'s may be skipped, and may be given in hex (0xnnn) * or decimal. * Max. text length is 1024. * A line beginning with a '#' is a comment. * Output: # of first message (i.e., lowest-numbered msg), or -1 if * error. */ int Read_text_msg_file ( istream& in, vector& strings // Strings returned here, each // allocated on heap. ) { strings.resize(0); // Initialize. strings.reserve(2000); char buf[1024]; int linenum = 0; #define NONEFOUND 0xffffffff unsigned long first = NONEFOUND;// Index of first one found. while (!in.eof()) { ++linenum; in.get(buf, sizeof(buf)); char delim; // Check for end-of-line. in.get(delim); if (delim != '\n' && !in.eof()) { cerr << "Line #" << linenum << " is too long" << endl; return -1; } if (!buf[0]) continue; // Empty line. char *ptr = &buf[0]; char *endptr; // Get line# in decimal, hex, or oct. long index = strtol(ptr, &endptr, 0); if (endptr == ptr) // No #? { if (*ptr == '#') continue; cerr << "Line " << linenum << " doesn't start with a number" << endl; return -1; } if (*endptr != ':') { cerr << "Missing ':' in line " << linenum << ". Ignoring line" << endl; continue; } if (index >= strings.size()) strings.resize(index + 1); strings[index] = newstrdup(endptr + 1); if (index < first) first = index; } return first == NONEFOUND ? -1 : (int) first; } exult-1.2/files/crc.h0000644000175000001440000000022407431004107010206 #ifndef _CRC_H_ #define _CRC_H_ #include "common_types.h" uint32 crc32(const char *filename); uint32 crc32_syspath(const char *filename); #endif exult-1.2/files/README0000644000175000001440000000120307427573244010166 The goal here is to make a unified files API that is inherently object-centric rather than file-centric. The same (simple) API is used to fetch any given object by any given exult subsystem and the subsystem requesting the object does not need to know what sort of file-format contains the object. The API takes care of all of that ugly need-to-know business. For the future, and a game creator, the API can be extended to pack files as well. I'm also interested in the idea of configurable redirections, where an object in a collection can be overriden and replaced by some other file/object and that redirection be transparent to the core. exult-1.2/files/Table.cc0000644000175000001440000000513607550423657010654 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Table.h" #ifndef ALPHA_LINUX_CXX # include #endif #include #include "exceptions.h" #include "utils.h" using std::string; using std::vector; using std::cout; using std::cerr; using std::endl; using std::FILE; using std::size_t; Table::Table(const string &n) : U7file(n) { IndexTableFile(); } void Table::IndexTableFile(void) { Table &ret=*this; FILE *fp; try { fp=U7open(ret.filename.c_str(),"rb"); } catch (const file_open_exception &e) { cerr << e.what() << ". exiting." << endl; std::exit(1); } fseek(fp,0,SEEK_END); size_t file_size=ftell(fp); fseek(fp,0,SEEK_SET); unsigned int i=0; while(1) { Table::Reference f; f.size = Read2(fp); // fread(&f.size,sizeof(uint16),1,fp); if(f.size==65535) break; f.offset = Read4(fp); // fread(&f.offset,sizeof(uint32),1,fp); if(f.size>file_size||f.offset>file_size) throw wrong_file_type_exception(filename,"Table"); #if 0 cout << "Item " << i << ": " << f.size << " @ " << f.offset << endl; #endif ret.object_list.push_back(f); i++; } fclose(fp); return; } char* Table::retrieve(uint32 objnum,size_t &len) { throw exult_exception("Illegal call to Table::retrieve()"); } #if 0 char *Table::read_object(int objnum,uint32 &length) { if((unsigned)objnum>=object_list.size()) { cerr << "objnum too large in read_object()" << endl; return 0; } FILE *fp; try { fp=U7open(filename.c_str(),"rb"); } catch (const file_open_exception &e) { cerr << e.what() << ". exiting." << endl; exit(1); } if(!fp) { cerr << "File open failed in read_object: " << filename << endl; return 0; } fseek(fp,object_list[objnum].offset,SEEK_SET); // length=object_list[objnum].size; uint16 sz; sz = Read2(fp); // fread(&sz,sizeof(sz),1,fp); length=sz-2; char *ret=new char[length]; fread(ret,length,1,fp); fclose(fp); return ret; } #endif exult-1.2/files/databuf.h0000644000175000001440000002757710054030557011074 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DATA_H #define DATA_H #ifndef ALPHA_LINUX_CXX # include # include #endif #include #include #include #include "U7file.h" #include "utils.h" typedef char * charptr; class DataSource { public: DataSource() {}; virtual ~DataSource() {}; virtual uint32 peek() =0; virtual uint32 read1() =0; virtual uint16 read2() =0; virtual uint16 read2high() =0; virtual uint32 read4() =0; virtual uint32 read4high() =0; virtual void read(char *, int) =0; virtual void write1(uint32) =0; virtual void write2(uint16) =0; virtual void write2high(uint16) =0; virtual void write4(uint32) =0; virtual void write4high(uint32) =0; virtual void write(char *, int) =0; virtual void seek(unsigned int) =0; virtual void skip(int) =0; virtual unsigned int getSize() =0; virtual unsigned int getPos() =0; virtual bool eof() =0; }; class StreamDataSource: public DataSource { private: std::ifstream *in; std::ofstream *out; public: StreamDataSource(std::ifstream *data_stream) : in(data_stream), out(0) { }; StreamDataSource(std::ofstream *data_stream) : in(0), out(data_stream) { }; virtual ~StreamDataSource() {}; virtual uint32 peek() { return in->peek(); }; virtual uint32 read1() { return Read1(*in); }; virtual uint16 read2() { return Read2(*in); }; virtual uint16 read2high() { return Read2high(*in); }; virtual uint32 read4() { return Read4(*in); }; virtual uint32 read4high() { return Read4high(*in); }; void read(char *b, int len) { in->read(b, len); }; virtual void write1(uint32 val) { Write1(*out, val); }; virtual void write2(uint16 val) { Write2(*out, val); }; virtual void write2high(uint16 val) { Write2high(*out, val); }; virtual void write4(uint32 val) { Write4(*out, val); }; virtual void write4high(uint32 val) { Write4high(*out, val); }; virtual void write(char *b, int len) { out->write(b, len); }; virtual void seek(unsigned int pos) { if (in) in->seekg(pos); else out->seekp(pos); }; virtual void skip(int pos) { in->seekg(pos, std::ios::cur); }; virtual unsigned int getSize() { if (in) { long pos = in->tellg(); in->seekg(0, std::ios::end); long len = in->tellg(); in->seekg(pos); return len; } else { long pos = out->tellp(); out->seekp(0, std::ios::end); long len = out->tellp(); out->seekp(pos); return len; } }; virtual unsigned int getPos() { return in?in->tellg():out->tellp(); }; virtual bool eof() { return in->eof(); } }; class FileDataSource: public DataSource { private: std::FILE *f; public: FileDataSource(std::FILE *fp) { f = fp; }; virtual ~FileDataSource() {}; virtual uint32 peek() { unsigned char b0; b0 = fgetc(f); fseek(f, -1, SEEK_CUR); return (b0); }; virtual uint32 read1() { unsigned char b0; b0 = fgetc(f); return (b0); }; virtual uint16 read2() { unsigned char b0, b1; b0 = fgetc(f); b1 = fgetc(f); return (b0 | (b1 << 8)); }; virtual uint16 read2high() { unsigned char b0, b1; b1 = fgetc(f); b0 = fgetc(f); return (b0 | (b1 << 8)); }; virtual uint32 read4() { unsigned char b0, b1, b2, b3; b0 = fgetc(f); b1 = fgetc(f); b2 = fgetc(f); b3 = fgetc(f); return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); }; virtual uint32 read4high() { unsigned char b0, b1, b2, b3; b3 = fgetc(f); b2 = fgetc(f); b1 = fgetc(f); b0 = fgetc(f); return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); }; void read(char *b, int len) { fread(b, 1, len, f); }; virtual void write1(uint32 val) { fputc(static_cast(val&0xff),f); }; virtual void write2(uint16 val) { fputc(static_cast(val&0xff),f); fputc(static_cast((val>>8)&0xff),f); }; virtual void write2high(uint16 val) { fputc(static_cast((val>>8)&0xff),f); fputc(static_cast(val&0xff),f); }; virtual void write4(uint32 val) { fputc(static_cast(val&0xff),f); fputc(static_cast((val>>8)&0xff),f); fputc(static_cast((val>>16)&0xff),f); fputc(static_cast((val>>24)&0xff),f); }; virtual void write4high(uint32 val) { fputc(static_cast((val>>24)&0xff),f); fputc(static_cast((val>>16)&0xff),f); fputc(static_cast((val>>8)&0xff),f); fputc(static_cast(val&0xff),f); }; virtual void write(char *b, int len) { fwrite(b, 1, len, f); }; virtual void seek(unsigned int pos) { fseek(f, pos, SEEK_SET); }; virtual void skip(int pos) { fseek(f, pos, SEEK_CUR); }; virtual unsigned int getSize() { long pos = ftell(f); fseek(f, 0, SEEK_END); long len = ftell(f); fseek(f, pos, SEEK_SET); return len; }; virtual unsigned int getPos() { return ftell(f); }; virtual bool eof() { return feof(f) != 0; } }; class BufferDataSource: public DataSource { protected: /* const solely so that no-one accidentally modifies it. data is being passed 'non-const' anyway */ const unsigned char *buf; unsigned char *buf_ptr; std::size_t size; public: BufferDataSource(char *data, unsigned int len) { // data can be NULL if len is also 0 assert(data!=0 || len==0); buf = buf_ptr = reinterpret_cast(data); size = len; }; void load(char *data, unsigned int len) { // data can be NULL if len is also 0 assert(data!=0 || len==0); buf = buf_ptr = reinterpret_cast(data); size = len; }; virtual ~BufferDataSource() {}; virtual uint32 peek() { unsigned char b0; b0 = static_cast(*buf_ptr); return (b0); }; virtual uint32 read1() { unsigned char b0; b0 = static_cast(*buf_ptr++); return (b0); }; virtual uint16 read2() { unsigned char b0, b1; b0 = static_cast(*buf_ptr++); b1 = static_cast(*buf_ptr++); return (b0 | (b1 << 8)); }; virtual uint16 read2high() { unsigned char b0, b1; b1 = static_cast(*buf_ptr++); b0 = static_cast(*buf_ptr++); return (b0 | (b1 << 8)); }; virtual uint32 read4() { unsigned char b0, b1, b2, b3; b0 = static_cast(*buf_ptr++); b1 = static_cast(*buf_ptr++); b2 = static_cast(*buf_ptr++); b3 = static_cast(*buf_ptr++); return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); }; virtual uint32 read4high() { unsigned char b0, b1, b2, b3; b3 = static_cast(*buf_ptr++); b2 = static_cast(*buf_ptr++); b1 = static_cast(*buf_ptr++); b0 = static_cast(*buf_ptr++); return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); }; void read(char *b, int len) { std::memcpy(b, buf_ptr, len); buf_ptr += len; }; virtual void write1(uint32 val) { *buf_ptr++ = val & 0xff; }; virtual void write2(uint16 val) { *buf_ptr++ = val & 0xff; *buf_ptr++ = (val>>8) & 0xff; }; virtual void write2high(uint16 val) { *buf_ptr++ = (val>>8) & 0xff; *buf_ptr++ = val & 0xff; }; virtual void write4(uint32 val) { *buf_ptr++ = val & 0xff; *buf_ptr++ = (val>>8) & 0xff; *buf_ptr++ = (val>>16)&0xff; *buf_ptr++ = (val>>24)&0xff; }; virtual void write4high(uint32 val) { *buf_ptr++ = (val>>24)&0xff; *buf_ptr++ = (val>>16)&0xff; *buf_ptr++ = (val>>8) & 0xff; *buf_ptr++ = val & 0xff; }; virtual void write(char *b, int len) { std::memcpy(buf_ptr, b, len); buf_ptr += len; }; virtual void seek(unsigned int pos) { buf_ptr = const_cast(buf)+pos; }; virtual void skip(int pos) { buf_ptr += pos; }; virtual unsigned int getSize() { return size; }; virtual unsigned int getPos() { return (buf_ptr-buf); }; unsigned char *getPtr() { return buf_ptr; }; virtual bool eof() { return (buf_ptr-buf) >= (int)size; } }; class StackBufferDataSource : protected BufferDataSource { public: StackBufferDataSource(unsigned int len=0x1000) : BufferDataSource(new char[len], len) { buf_ptr = const_cast(buf)+len; }; ~StackBufferDataSource() { delete [] const_cast(buf); }; // // Push values to the stack // inline void push2(uint16 val) { buf_ptr-=2; buf_ptr[0] = val & 0xFF; buf_ptr[1] = (val>>8) & 0xFF; } inline void push4(uint32 val) { buf_ptr-=4; buf_ptr[0] = val & 0xFF; buf_ptr[1] = (val>>8) & 0xFF; buf_ptr[2] = (val>>16) & 0xFF; buf_ptr[3] = (val>>24) & 0xFF; } // Push an arbitrary number of bytes of 0 inline void push0(const uint32 size) { buf_ptr -= size; std::memset (buf_ptr, 0, size); }; // Push an arbitrary number of bytes inline void push(const uint8 *in, const uint32 size) { buf_ptr -= size; std::memcpy (buf_ptr, in, size); }; // // Pop values from the stack // inline uint16 pop2() { return read2(); } inline uint32 pop4() { return read4(); } inline void pop(uint8 *out, const uint32 size) { read(reinterpret_cast(out), size); }; // // Access a value from a location in the stacck // inline uint8 access1(const uint32 offset) const { return buf[offset]; } inline uint16 access2(const uint32 offset) const { return (buf[offset] | (buf[offset+1] << 8)); } inline uint32 access4(const uint32 offset) const { return buf[offset] | (buf[offset+1]<<8) | (buf[offset+2]<<16) | (buf[offset+3]<<24); } inline const uint8* access(const uint32 offset) const { return buf+offset; } // // Assign a value to a location in the stack // inline void assign1(const uint32 offset, const uint8 val) { const_cast(buf)[offset] = val & 0xFF; } inline void assign2(const uint32 offset, const uint16 val) { const_cast(buf)[offset] = val & 0xFF; const_cast(buf)[offset+1] = (val>>8) & 0xFF; } inline void assign4(const uint32 offset, const uint32 val) { const_cast(buf)[offset] = val & 0xFF; const_cast(buf)[offset+1] = (val>>8) & 0xFF; const_cast(buf)[offset+2] = (val>>16) & 0xFF; const_cast(buf)[offset+3] = (val>>24) & 0xFF; } inline void assign(const uint32 offset, const uint8 *in, const uint32 len) { std::memcpy (const_cast(buf+offset), in, len); } inline uint32 stacksize() const { return buf+size-buf_ptr; }; inline void resize(const uint32 newsize) { buf_ptr = const_cast(buf)+size-newsize; }; inline void addSP(const sint32 offset) { skip(offset); } virtual unsigned int getSP() { return getPos(); }; inline void moveSP(unsigned int pos) { seek(pos); } /* temp debugging */ inline std::ostream &print(std::ostream &o, uint32 bp) { for(const unsigned char *c=buf_ptr; c!=buf+size; ++c) { if (c != buf+bp) std::printf(" %02X", static_cast(*c)); else std::printf(":%02X", static_cast(*c)); } return o; } private: }; class ExultDataSource: public BufferDataSource { public: ExultDataSource(const char *fname, int index): BufferDataSource(0,0) { U7object obj(fname, index); buf = reinterpret_cast(obj.retrieve(size)); buf_ptr = const_cast(buf); }; ~ExultDataSource() { delete [] const_cast(buf); } }; #endif exult-1.2/files/U7file.cc0000644000175000001440000000555207753476060010763 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include #include "U7file.h" #include "Flex.h" #include "IFF.h" #include "Table.h" #include "Flat.h" #include "exceptions.h" #include "utils.h" using std::cerr; using std::endl; using std::size_t; using std::FILE; using std::string; #define TRY_FILE_TYPE(uf,CLASS_NAME) \ if(!uf) \ try { \ uf=new CLASS_NAME(s); \ } catch(const wrong_file_type_exception &) \ { \ } U7file *U7FileManager::get_file_object(const string &s) { U7file *uf=0; if(file_list.count(s)) { return file_list[s]; } // Not in our cache. Attempt to figure it out. TRY_FILE_TYPE(uf,IFF); #ifndef PENTAGRAM TRY_FILE_TYPE(uf,Flex); #endif TRY_FILE_TYPE(uf,Table); TRY_FILE_TYPE(uf,Flat); // Failed if (!uf) { throw (file_open_exception((const string &) s)); return 0; } file_list[s]=uf; return uf; } U7FileManager *U7FileManager::get_ptr(void) { if(!self) new U7FileManager(); // self gets the pointer, so it's okay // This might look like it creates a // leak, but this is a singleton object return self; } void U7FileManager::reset() { std::map::iterator i; for (i = file_list.begin(); i != file_list.end(); ++i) delete (*i).second; file_list.clear(); } U7FileManager::~U7FileManager() {} U7FileManager *U7FileManager::self=0; U7FileManager::U7FileManager() { if(self) { throw exclusive(); std::exit(-1); } else self=this; } uint32 U7object::number_of_objects(void) { U7file *uf=U7FileManager::get_ptr()->get_file_object(filename); if (!uf) return 0; return uf->number_of_objects(); } char* U7object::retrieve(size_t &len) { U7file *uf=U7FileManager::get_ptr()->get_file_object(filename); if (!uf) return 0; return uf->retrieve(objnumber,len); } bool U7object::retrieve(const char *fname) { FILE *fp=U7open(fname,"wb"); char *n; size_t l; try { n = retrieve(l); } catch( const std::exception & err ) { std::fclose(fp); throw (err); } if (!n) { std::fclose(fp); return false; } std::fwrite(n,l,1,fp); // &&&& Should check return value std::fclose(fp); delete [] n; return true; } exult-1.2/files/msgfile.h0000644000175000001440000000046007676473116011114 /** ** Msgfile.h - Read in text message file. ** ** Written: 6/25/03 **/ #ifndef INCL_MSGFILE_H #define INCL_MSGFILE_H 1 using std::istream; using std::vector; int Read_text_msg_file ( istream& in, vector& strings // Strings returned here, each // allocated on heap. ); #endif exult-1.2/files/crc.cc0000644000175000001440000001411407442157511010361 /* * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. * * (modified for use in Exult) * * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1 * * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to hight-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly * * The feedback terms table consists of 256, 32-bit entries. Notes * * The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera * tions for all combinations of data and CRC register values * * The values must be right-shifted by eight bits by the "updcrc * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions * polynomial $edb88320 */ #ifdef HAVE_CONFIG_H # include #endif #include "crc.h" #include "common_types.h" #include "utils.h" #include static uint32 crc32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; /* unsigned int ssh_crc32(const unsigned char *s, unsigned int len) { unsigned int i; unsigned int crc32val; crc32val = 0; for (i = 0; i < len; i ++) { crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); } return crc32val; } */ uint32 crc32(const char *filename) { std::ifstream crcfile(filename, std::ios::binary | std::ios::in); uint32 crc32val = 0; unsigned char c; crcfile.get(reinterpret_cast(c)); while (crcfile.good()) { crc32val = crc32_tab[(crc32val ^ c) & 0xff] ^ (crc32val >> 8); crcfile.get(reinterpret_cast(c)); } return crc32val; } uint32 crc32_syspath(const char *filename) { return crc32(get_system_path(filename).c_str()); } exult-1.2/files/Makefile.am0000644000175000001440000000124607676473116011354 INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../headers $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) SUBDIRS = zip noinst_LTLIBRARIES = libu7file.la noinst_PROGRAMS = rwregress rwregress_SOURCES = \ rwregress.cc \ utils.h rwregress_LDADD = \ libu7file.la \ $(SYSLIBS) if HAVE_SNPRINTF SNPRINTF = else SNPRINTF = snprintf.cc endif libu7file_la_SOURCES = \ Flat.cc \ Flat.h \ Flex.cc \ Flex.h \ Table.cc \ Table.h \ IFF.cc \ IFF.h \ U7file.cc \ U7file.h \ utils.cc \ utils.h \ databuf.h \ listfiles.cc \ listfiles.h \ crc.cc \ crc.h \ msgfile.cc \ msgfile.h \ $(SNPRINTF) EXTRA_DIST = \ README CLEANFILES = *~ exult-1.2/files/Makefile.in0000644000175000001440000003626410061527045011354 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../headers $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) SUBDIRS = zip noinst_LTLIBRARIES = libu7file.la noinst_PROGRAMS = rwregress rwregress_SOURCES = \ rwregress.cc \ utils.h rwregress_LDADD = \ libu7file.la \ $(SYSLIBS) @HAVE_SNPRINTF_TRUE@SNPRINTF = @HAVE_SNPRINTF_FALSE@SNPRINTF = snprintf.cc libu7file_la_SOURCES = \ Flat.cc \ Flat.h \ Flex.cc \ Flex.h \ Table.cc \ Table.h \ IFF.cc \ IFF.h \ U7file.cc \ U7file.h \ utils.cc \ utils.h \ databuf.h \ listfiles.cc \ listfiles.h \ crc.cc \ crc.h \ msgfile.cc \ msgfile.h \ $(SNPRINTF) EXTRA_DIST = \ README CLEANFILES = *~ subdir = files mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libu7file_la_LDFLAGS = libu7file_la_LIBADD = @HAVE_SNPRINTF_TRUE@am_libu7file_la_OBJECTS = Flat.lo Flex.lo Table.lo \ @HAVE_SNPRINTF_TRUE@ IFF.lo U7file.lo utils.lo listfiles.lo \ @HAVE_SNPRINTF_TRUE@ crc.lo msgfile.lo @HAVE_SNPRINTF_FALSE@am_libu7file_la_OBJECTS = Flat.lo Flex.lo Table.lo \ @HAVE_SNPRINTF_FALSE@ IFF.lo U7file.lo utils.lo listfiles.lo \ @HAVE_SNPRINTF_FALSE@ crc.lo msgfile.lo snprintf.lo libu7file_la_OBJECTS = $(am_libu7file_la_OBJECTS) noinst_PROGRAMS = rwregress$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_rwregress_OBJECTS = rwregress.$(OBJEXT) rwregress_OBJECTS = $(am_rwregress_OBJECTS) rwregress_DEPENDENCIES = libu7file.la rwregress_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/Flat.Plo $(DEPDIR)/Flex.Plo \ @AMDEP_TRUE@ $(DEPDIR)/IFF.Plo $(DEPDIR)/Table.Plo \ @AMDEP_TRUE@ $(DEPDIR)/U7file.Plo $(DEPDIR)/crc.Plo \ @AMDEP_TRUE@ $(DEPDIR)/listfiles.Plo $(DEPDIR)/msgfile.Plo \ @AMDEP_TRUE@ $(DEPDIR)/rwregress.Po $(DEPDIR)/snprintf.Plo \ @AMDEP_TRUE@ $(DEPDIR)/utils.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libu7file_la_SOURCES) $(rwregress_SOURCES) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = README Makefile.am Makefile.in DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(libu7file_la_SOURCES) $(rwregress_SOURCES) all: all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu files/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libu7file.la: $(libu7file_la_OBJECTS) $(libu7file_la_DEPENDENCIES) $(CXXLINK) $(libu7file_la_LDFLAGS) $(libu7file_la_OBJECTS) $(libu7file_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) rwregress$(EXEEXT): $(rwregress_OBJECTS) $(rwregress_DEPENDENCIES) @rm -f rwregress$(EXEEXT) $(CXXLINK) $(rwregress_LDFLAGS) $(rwregress_OBJECTS) $(rwregress_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Flat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Flex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/IFF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/U7file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/crc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/listfiles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/msgfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/rwregress.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/utils.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-recursive distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS clean-recursive distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-recursive distclean-tags distdir \ dvi dvi-am dvi-recursive info info-am info-recursive install \ install-am install-data install-data-am install-data-recursive \ install-exec install-exec-am install-exec-recursive \ install-info install-info-am install-info-recursive install-man \ install-recursive install-strip installcheck installcheck-am \ installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ tags tags-recursive uninstall uninstall-am uninstall-info-am \ uninstall-info-recursive uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/files/listfiles.cc0000644000175000001440000002122310054030557011600 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include #endif #include #include #include #ifndef UNDER_CE using std::vector; using std::cout; using std::cerr; using std::endl; using std::free; using std::malloc; using std::string; using std::strcat; using std::strcpy; using std::strlen; #endif #include "utils.h" #include "listfiles.h" #if defined(MACOS) || defined(BEOS) /* * Match a string with a given pattern (DOS like syntax, using * and ?) */ static bool MatchString( const char *str, const std::string& inPat ); static bool MatchString( const char *str, const std::string& inPat ) { const char *pat = inPat.c_str(); const char *p = NULL; const char *q = NULL; for(;;) { switch(*pat) { case '*': p = ++pat; q = str; break; default: if(*pat != *str) { if(p) { pat = p; str = ++q; if(!*str) return !*pat; break; } else return false; } // fallthrough case '?': if(!*str) return !*pat; pat++; str++; } } } #endif // System Specific Code for Windows #if defined(WIN32) // Need this for _findfirst, _findnext, _findclose #include #include #include int U7ListFiles(const std::string mask, FileList& files) { string path(get_system_path(mask)); const TCHAR *lpszT; WIN32_FIND_DATA fileinfo; HANDLE handle; char *stripped_path; int i, nLen, nLen2; #ifdef UNICODE const char *name = path.c_str(); nLen = strlen(name)+1; LPTSTR lpszT2 = (LPTSTR) _alloca(nLen*2); lpszT = lpszT2; MultiByteToWideChar(CP_ACP, 0, name, -1, lpszT2, nLen); #else lpszT = path.c_str(); #endif handle = FindFirstFile (lpszT, &fileinfo); stripped_path = new char [path.length()+1]; strcpy (stripped_path, path.c_str()); for (i = strlen (stripped_path)-1; i; i--) if (stripped_path[i] == '\\' || stripped_path[i] == '/') break; if (stripped_path[i] == '\\' || stripped_path[i] == '/') stripped_path[i+1] = 0; #ifdef DEBUG std::cerr << "U7ListFiles: " << mask << " = " << path << std::endl; #endif // Now search the files if (handle != INVALID_HANDLE_VALUE) { do { nLen = std::strlen(stripped_path); nLen2 = _tcslen (fileinfo.cFileName)+1; char *filename = new char [nLen+nLen2]; strcpy (filename, stripped_path); #ifdef UNICODE WideCharToMultiByte(CP_ACP, 0, fileinfo.cFileName, -1, filename+nLen, nLen2, NULL, NULL); #else std::strcat (filename, fileinfo.cFileName); #endif files.push_back(filename); #ifdef DEBUG std::cerr << filename << std::endl; #endif delete [] filename; } while (FindNextFile( handle, &fileinfo )); } if (GetLastError() != ERROR_NO_MORE_FILES) { LPTSTR lpMsgBuf; char* str; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); #ifdef UNICODE nLen2 = _tcslen (lpMsgBuf) + 1; str = (char*) _alloca(nLen); WideCharToMultiByte(CP_ACP, 0, lpMsgBuf, -1, str, nLen2, NULL, NULL); #else str = lpMsgBuf; #endif std::cerr << "Error while listing files: " << str << std::endl; LocalFree( lpMsgBuf ); } #ifdef DEBUG std::cerr << files.size() << " filenames" << std::endl; #endif delete [] stripped_path; FindClose (handle); return 0; } #elif defined(MACOS) #include #include OSErr GetCatInfoNoName(short vRefNum, long dirID, std::string name, CInfoPBPtr pb); OSErr GetCatInfoNoName(short vRefNum, long dirID, std::string name, CInfoPBPtr pb) { Str255 tempName; OSErr err; CopyCStringToPascal(name.c_str(), tempName); if (tempName[0] == 0) pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ else pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ pb->dirInfo.ioNamePtr = tempName; pb->dirInfo.ioVRefNum = vRefNum; pb->dirInfo.ioDrDirID = dirID; err = PBGetCatInfoSync(pb); pb->dirInfo.ioNamePtr = NULL; return err; } int U7ListFiles(const std::string pathMask, FileList& files) { CInfoPBRec cPB; // the parameter block used for PBGetCatInfo calls Str63 itemName; // the name of the current item OSErr err; // temporary holder of results - saves 2 bytes of stack each level short index = 0; short vRefNum; long dirID; char filename[256]; string path(get_system_path(pathMask)); string mask; string::size_type pos; pos = path.rfind(':'); if(pos == string::npos) { mask = path; path.clear(); } else { mask = path.substr(pos+1); path = path.substr(0,pos); } err = HGetVol( NULL, &vRefNum, &dirID ); if (err != noErr) return err; err = GetCatInfoNoName(vRefNum,dirID,path,&cPB); if (err != noErr) return err; dirID = cPB.dirInfo.ioDrDirID; itemName[0] = 0; cPB.hFileInfo.ioNamePtr = (StringPtr)&itemName; do { // Get next source item at the current directory level ++index; cPB.dirInfo.ioFDirIndex = index; cPB.dirInfo.ioDrDirID = dirID; err = PBGetCatInfoSync(&cPB); if (err == noErr) { // Is it a file (i.e. not a directory)? if ( (cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) { CopyPascalStringToC(itemName, filename); if (MatchString(filename, mask)) { cout << "File name: " << filename << endl; files.push_back(filename); } } } } while (err == noErr ); if ( (err == fnfErr) || // fnfErr is OK - it only means we hit the end of this level (err == afpAccessDenied) ) // afpAccessDenied is OK, too - it only means we cannot see inside a directory { err = noErr; } return err; } #elif defined(BEOS) #include #include int U7ListFiles(const std::string pathMask, FileList& files) { char filename[255]; string path(get_system_path(pathMask)); string mask; string::size_type pos; pos = path.rfind('/'); if(pos == string::npos) { mask = path; path = ""; } else { mask = path.substr(pos+1); path = path.substr(0,pos); } BDirectory dir(path.c_str()); if (dir.InitCheck() != B_OK) return -1; do { BEntry entry; if (dir.GetNextEntry(&entry, true) == B_ENTRY_NOT_FOUND) break; // done // is it a regular file? (symlinks have already been traversed) if (!entry.IsFile()) continue; entry.GetName(filename); if (MatchString(filename, mask)) { cout << "Filename: " << filename << endl; files.push_back(filename); } } while (true); return 0; } #elif defined(__MORPHOS__) || defined(AMIGA) #define NO_PPCINLINE_VARARGS #define NO_PPCINLINE_STDARG #include static struct AnchorPath ap __attribute__((aligned(4))); int U7ListFiles(const std::string mask, FileList& files) { string path(get_system_path(mask)); char buffer[ 256 ]; size_t pos; // convert MS-DOS jokers to AmigaDOS wildcards while( (pos = path.find( '*' )) != string::npos ) path.replace( pos, 1, "#?" ); if( ParsePattern( path.c_str(), buffer, sizeof( buffer ) ) != -1 ) { LONG error = MatchFirst( buffer, &ap ); while( error == DOSFALSE ) { char *filename = (char *)malloc( strlen( ap.ap_Info.fib_FileName )+1 ); strcpy( filename, ap.ap_Info.fib_FileName ); files.push_back( filename ); error = MatchNext( &ap ); } MatchEnd( &ap ); } else cout << "ParsePattern() failed." << endl; return 0; } #else // This system has glob.h #include int U7ListFiles(const std::string mask, FileList& files) { glob_t globres; string path(get_system_path(mask)); int err = glob(path.c_str(), GLOB_NOSORT, 0, &globres); switch (err) { case 0: //OK for (int i=0; i #include #include "U7file.h" #include "common_types.h" class Table : public U7file { protected: struct Reference { uint32 offset; uint16 size; Reference() : offset(0),size(0) {}; }; std::vector object_list; public: Table(const std::string &name); Table(const Table &t) : object_list(t.object_list) { } Table &operator=(const Table &t) { object_list=t.object_list; return *this; } virtual uint32 number_of_objects(void) { return object_list.size(); }; virtual char * retrieve(uint32 objnum,std::size_t &len); // To a memory block virtual const char *get_archive_type() { return "TABLE"; }; private: void IndexTableFile(void); Table(); }; #endif exult-1.2/files/utils.h0000644000175000001440000001645410003025430010602 /* * utils.h - Common utility routines. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UTILS_H_ #define _UTILS_H_ #include #include #ifndef ALPHA_LINUX_CXX # include #endif #include "common_types.h" #ifndef HAVE_SNPRINTF extern int snprintf(char *, size_t, const char *, /*args*/ ...); #endif /* * Read a 1-byte value. */ inline uint8 Read1 (std::istream &in) { return static_cast(in.get()); } /* * Read a 2-byte value, lsb first. */ inline uint16 Read2 (std::istream &in) { uint16 val = 0; val |= static_cast(in.get()); val |= static_cast(in.get()<<8); return val; } /* * Read a 2-byte value from a buffer. */ inline uint16 Read2 ( uint8 *& in ) { uint8 b0 = *in++; uint8 b1 = *in++; return (b0 | (b1 << 8)); } #ifdef BUFSIZ /* Kludgy, but I don't want to include stdio.h all the time.*/ /* * Read a 2-byte value from a file. */ inline uint16 Read2 ( std::FILE* in ) { uint8 b0, b1; std::fread(&b0,sizeof(uint8),1,in); std::fread(&b1,sizeof(uint8),1,in); return (b0 | (b1 << 8)); } #endif /* * Read a 2-byte value, hsb first. */ inline uint16 Read2high (std::istream &in) { uint16 val = 0; val |= static_cast(in.get()<<8); val |= static_cast(in.get()); return val; } /* * Read a 2-byte value from a buffer. */ inline uint16 Read2high ( uint8 *& in ) { uint8 b0 = *in++; uint8 b1 = *in++; return ((b0 << 8) | b1); } #ifdef BUFSIZ /* Kludgy, but I don't want to include stdio.h all the time.*/ /* * Read a 2-byte value from a file. */ inline uint16 Read2high ( std::FILE* in ) { uint8 b0, b1; std::fread(&b0,sizeof(uint8),1,in); std::fread(&b1,sizeof(uint8),1,in); return ((b0 << 8) | b1); } #endif /* * Read a 4-byte long value, lsb first. */ inline uint32 Read4 (std::istream &in) { uint32 val = 0; val |= static_cast(in.get()); val |= static_cast(in.get()<<8); val |= static_cast(in.get()<<16); val |= static_cast(in.get()<<24); return val; } /* * Read a 4-byte value from a buffer. */ inline uint32 Read4 ( uint8 *& in ) { uint8 b0 = *in++; uint8 b1 = *in++; uint8 b2 = *in++; uint8 b3 = *in++; return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); } #ifdef BUFSIZ /* Kludgy, but I don't want to include stdio.h all the time.*/ /* * Read a 4-byte value from a file. */ inline uint32 Read4 ( std::FILE* in ) { uint8 b0, b1, b2, b3; std::fread(&b0,sizeof(uint8),1,in); std::fread(&b1,sizeof(uint8),1,in); std::fread(&b2,sizeof(uint8),1,in); std::fread(&b3,sizeof(uint8),1,in); return (b0 | (b1<<8) | (b2<<16) | (b3<<24)); } #endif /* * Read a 4-byte long value, hsb first. */ inline uint32 Read4high (std::istream &in) { uint32 val = 0; val |= static_cast(in.get()<<24); val |= static_cast(in.get()<<16); val |= static_cast(in.get()<<8); val |= static_cast(in.get()); return val; } /* * Read a 4-byte value from a buffer. */ inline uint32 Read4high ( uint8 *& in ) { uint8 b0 = *in++; uint8 b1 = *in++; uint8 b2 = *in++; uint8 b3 = *in++; return ((b0<<24) | (b1<<16) | (b2<<8) | b3); } #ifdef BUFSIZ /* Kludgy, but I don't want to include stdio.h all the time.*/ /* * Read a 4-byte value from a file. */ inline uint32 Read4high ( std::FILE* in ) { uint8 b0, b1, b2, b3; std::fread(&b0,sizeof(uint8),1,in); std::fread(&b1,sizeof(uint8),1,in); std::fread(&b2,sizeof(uint8),1,in); std::fread(&b3,sizeof(uint8),1,in); return ((b0<<24) | (b1<<16) | (b2<<8) | b3); } #endif /* * Write a 1-byte value. */ inline void Write1(std::ostream& out, uint16 val) { out.put(static_cast (val&0xff)); } /* * Write a 2-byte value, lsb first. */ inline void Write2 ( std::ostream& out, uint16 val ) { out.put(static_cast (val&0xff)); out.put(static_cast ((val>>8)&0xff)); } /* * Write a 2-byte value, msb first. */ inline void Write2high ( std::ostream& out, uint16 val ) { out.put(static_cast ((val>>8)&0xff)); out.put(static_cast (val&0xff)); } /* * Write a 2-byte value to a buffer, lsb first. */ inline void Write2 ( uint8 *& out, // Write here and update. uint16 val ) { *out++ = val & 0xff; *out++ = (val>>8) & 0xff; } /* * Write a 4-byte value, lsb first. */ inline void Write4 ( std::ostream& out, uint32 val ) { out.put(static_cast (val&0xff)); out.put(static_cast ((val>>8)&0xff)); out.put(static_cast ((val>>16)&0xff)); out.put(static_cast ((val>>24)&0xff)); } /* * Write a 4-byte value, msb first. */ inline void Write4high ( std::ostream& out, uint32 val ) { out.put(static_cast ((val>>24)&0xff)); out.put(static_cast ((val>>16)&0xff)); out.put(static_cast ((val>>8)&0xff)); out.put(static_cast (val&0xff)); } /* * Write a 4-byte value to a buffer, lsb first. */ inline void Write4 ( uint8 *& out, // Write here and update. uint32 val ) { *out++ = val & 0xff; *out++ = (val>>8) & 0xff; *out++ = (val>>16)&0xff; *out++ = (val>>24)&0xff; } inline void Write4s(std::ostream& out, sint32 val) { Write4(out, static_cast(val)); } bool U7open ( std::ifstream& in, // Input stream to open. const char *fname, // May be converted to upper-case. bool is_text = false // Should the file be opened in text mode ); bool U7open ( std::ofstream& out, // Output stream to open. const char *fname, // May be converted to upper-case. bool is_text = false // Should the file be opened in text mode ); #ifdef BUFSIZ /* Kludgy, but I don't want to include stdio.h all the time.*/ std::FILE* U7open ( const char *fname, // May be converted to upper-case. const char *mode // File access mode. ); #endif void U7remove( const char *fname ); bool U7exists( const char *fname ); inline bool U7exists(std::string fname) { return U7exists(fname.c_str()); } int U7mkdir( const char *dirname, int mode ); // These are not supported in WinCE (PocketPC) for now #ifndef UNDER_CE int U7chdir( const char *dirname ); void U7copy ( const char *src, const char *dest ); #endif //UNDER_CE bool is_system_path_defined(const std::string& key); void store_system_paths(); void reset_system_paths(); void clear_system_path(const std::string& key); void add_system_path(const std::string& key, const std::string& value); void clone_system_path(const std::string& new_key, const std::string& old_key); std::string get_system_path(const std::string &path); void to_uppercase(std::string &str); std::string to_uppercase(const std::string &str); int Log2(uint32 n); char *newstrdup(const char *s); #endif /* _UTILS_H_ */ exult-1.2/files/U7file.h0000644000175000001440000000406207753476060010620 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _U7FILE_H_ #define _U7FILE_H_ #include #include #include "common_types.h" class U7file { public: std::string filename; U7file() {} U7file(const std::string &name) : filename(name) {} U7file(const U7file &f) : filename(f.filename) {} U7file &operator=(const U7file &u) { filename=u.filename; return *this; } virtual ~U7file() {} virtual uint32 number_of_objects(void)=0; virtual char * retrieve(uint32 objnum,std::size_t &len)=0; virtual const char *get_archive_type()=0; }; class U7FileManager { protected: class exclusive {}; #if 0 struct ltstr { bool operator()(const std::string &s1, const std::string &s2) const { return s1 file_list; #endif std::map file_list; static U7FileManager *self; public: U7FileManager(); ~U7FileManager(); void reset(); U7file *get_file_object(const std::string &s); static U7FileManager *get_ptr(void); }; class U7object { protected: std::string filename; int objnumber; public: U7object(const std::string &file,int objnum) : filename(file),objnumber(objnum) {} virtual ~U7object() {} uint32 number_of_objects(void); virtual char * retrieve(std::size_t &len); bool retrieve(const char *fname); // FIX ME - this is only used in Game::play_audio and should be removed }; #endif exult-1.2/files/Flat.cc0000644000175000001440000000266107550423657010513 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Flat.h" #ifndef ALPHA_LINUX_CXX # include #endif #include #include "exceptions.h" #include "utils.h" using std::string; // using std::vector; using std::cout; using std::cerr; using std::endl; using std::FILE; using std::size_t; Flat::Flat(const string &n) : U7file(n) { // Make sure the file exists and is readable FILE *fp; fp=U7open(filename.c_str(),"rb"); fclose(fp); } char * Flat::retrieve(uint32 objnum, size_t &len) { FILE *fp; char *buffer; fp=U7open(filename.c_str(),"rb"); fseek(fp,0,SEEK_END); len = ftell(fp); buffer = new char[len]; fseek(fp,0,SEEK_SET); fread(buffer,len,1,fp); fclose(fp); return buffer; } exult-1.2/files/Flex.cc0000644000175000001440000001141010054030556010474 /* Copyright (C) 2000 Dancer A.L Vesperman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef PENTAGRAM // DONT'T INCLUDE THIS IN PENTAGRAM! #define DEBUGFLEX 0 #include "Flex.h" #ifndef ALPHA_LINUX_CXX # include #endif #include #include #include "exceptions.h" #include "utils.h" #include "databuf.h" #ifndef UNDER_CE using std::cerr; using std::endl; using std::FILE; using std::memset; using std::size_t; using std::string; using std::strncpy; using std::ofstream; using std::ios; #endif Flex::Flex(const string &n) : U7file(n) { IndexFlexFile(); } void Flex::IndexFlexFile(void) { FILE *fp; fp=U7open(filename.c_str(),"rb"); FileDataSource flex(fp); flex.read(title, sizeof(title)); magic1 = flex.read4(); count = flex.read4(); magic2 = flex.read4(); if(magic1!=0xffff1a00UL) { std::fclose (fp); throw wrong_file_type_exception(filename,"FLEX"); // Not a flex file } for(int i=0;i<9;i++) padding[i] = flex.read4(); #if DEBUGFLEX cout << "Title: " << title << endl; cout << "Count: " << count << endl; #endif // We should already be there. fseek(fp,128,SEEK_SET); for(uint32 c=0;c= object_list.size()) throw exult_exception("objnum too large in Flex::retrieve()"); fp = U7open(filename.c_str(), "rb"); fseek(fp, object_list[objnum].offset, SEEK_SET); len = object_list[objnum].size; buffer = new char[len]; std::fread(buffer, len, 1, fp); fclose(fp); return buffer; } /* * Write out a FLEX header. Note that this is a STATIC method. */ void Flex::write_header ( DataSource* out, // File to write to. const char *title, int count // # entries. ) { char titlebuf[0x50]; // Use savename for title. memset(titlebuf, 0, sizeof(titlebuf)); strncpy(titlebuf, title, sizeof(titlebuf) - 1); out->write(titlebuf, sizeof(titlebuf)); out->write4(0xFFFF1A00); // Magic number. out->write4(count); out->write4(0x000000CC); // 2nd magic number. long pos = out->getPos(); // Fill to data (past table at 0x80). long fill = 0x80 + 8*count - pos; while (fill--) out->write1((char) 0); } /* * Verify if a file is a FLEX. Note that this is a STATIC method. */ bool Flex::is_flex(DataSource *in) { long pos = in->getPos(); // Fill to data (past table at 0x80). long len = in->getSize() - pos; // Check length. uint32 magic = 0; if (len >= 0x80) // Has to be at least this long. { in->seek(0x50); magic = in->read4(); } in->seek(pos); // Is a flex if(magic==0xffff1a00UL) return true; // Isn't a flex return false; } bool Flex::is_flex(const char *fname) { bool is = false; std::ifstream in; U7open (in, fname); StreamDataSource ds(&in); if (in.good()) is = is_flex(&ds); in.close(); return is; } /* * Start writing out a new Flex file. */ Flex_writer::Flex_writer ( std::ofstream& o, // Where to write. const char *title, // Flex title. int cnt // #entries we'll write. ) : out(&o), count(cnt), index(0) { // Write out header. StreamDataSource ds(out); Flex::write_header(&ds, title, count); // Create table. tptr = table = new uint8[2*count*4]; cur_start = out->tellp(); // Store start of 1st entry. } /* * Clean up. */ Flex_writer::~Flex_writer ( ) { close(); } /* * Call this when done writing out a section. */ void Flex_writer::mark_section_done ( ) { long pos = out->tellp(); // Location past end of section. Write4(tptr, cur_start); // Store start of section. Write4(tptr, pos - cur_start); // Store length. cur_start = pos; } /* * All done. * * Output: False if error. */ bool Flex_writer::close ( ) { if (!table) return true; // Already done. out->seekp(0x80, ios::beg); // Write table. out->write(reinterpret_cast(table), 2*count*4); out->flush(); bool ok = out->good(); out->close(); delete table; table = 0; return ok; } #endif // PENTAGRAM exult-1.2/files/listfiles.h0000644000175000001440000000156507427573244011470 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef LISTFILES_H #define LISTFILES_H typedef std::vector FileList; int U7ListFiles(const std::string mask, FileList& files); #endif //LISTFILES_H exult-1.2/files/rwregress.cc0000644000175000001440000000662507676104167011655 #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "utils.h" using std::cout; using std::endl; using std::istrstream; const char *ss_data = "A BC DE FGHI JKLM NO\0"; #if 0 // just used temporarially for some optimisation tests. inline uint8 Read1diff ( std::istream& in ) { return static_cast(in.get()); } inline uint32 Read4diff ( std::istream& in ) { return static_cast(in.get() | (in.get()<<8) | (in.get()<<16) | (in.get()<<24)); } #include #include void speedtest() { timeval tvstart; timeval tvend; timeval tvstart_diff; timeval tvend_diff; std::ifstream file("random"); assert(!file.fail()); gettimeofday(&tvstart, NULL); while(!file.eof()) uint8 ui8 = Read4(file); gettimeofday(&tvend, NULL); //------------------------- std::ifstream file_diff("random"); assert(!file_diff.fail()); gettimeofday(&tvstart_diff, NULL); while(!file_diff.eof()) uint8 ui8 = Read4diff(file_diff); gettimeofday(&tvend_diff, NULL); cout << tvstart.tv_sec << '\t' << tvstart.tv_usec << endl; cout << tvend.tv_sec << '\t' << tvend.tv_usec << endl; cout << "---------------------" << endl; cout << tvend.tv_sec - tvstart.tv_sec << '\t' << tvend.tv_usec - tvstart.tv_usec << endl; cout << endl; cout << tvstart_diff.tv_sec << '\t' << tvstart_diff.tv_usec << endl; cout << tvend_diff.tv_sec << '\t' << tvend_diff.tv_usec << endl; cout << "---------------------" << endl; cout << tvend_diff.tv_sec - tvstart_diff.tv_sec << '\t' << tvend_diff.tv_usec - tvstart_diff.tv_usec << endl; cout << endl; } #endif int main(int argc, char *argv[]) { istrstream iss(ss_data); uint8 outread1 = Read1(iss); cout << static_cast(outread1) << endl; assert(static_cast(outread1)=='A'); assert(static_cast(Read1(iss))==' '); uint16 outread2 = Read2(iss); cout << static_cast(outread2 & 0xff) << static_cast((outread2>>8) & 0xff) << endl; assert(static_cast(outread2 & 0xff)=='B'); assert(static_cast((outread2>>8) & 0xff)=='C'); assert(static_cast(Read1(iss))==' '); uint16 outread2high = Read2high(iss); cout << static_cast((outread2high>>8) & 0xff) << static_cast(outread2high & 0xff) << endl; assert(static_cast(outread2high & 0xff)=='E'); assert(static_cast((outread2high>>8) & 0xff)=='D'); assert(static_cast(Read1(iss))==' '); uint32 outread4 = Read4(iss); cout << static_cast(outread4 & 0xff) << static_cast((outread4>>8) & 0xff) << static_cast((outread4>>16) & 0xff) << static_cast((outread4>>24) & 0xff) << endl; assert(static_cast(outread4 & 0xff)=='F'); assert(static_cast((outread4>>8) & 0xff)=='G'); assert(static_cast((outread4>>16) & 0xff)=='H'); assert(static_cast((outread4>>24) & 0xff)=='I'); assert(static_cast(Read1(iss))==' '); uint32 outread4high = Read4high(iss); cout << static_cast((outread4high>>24) & 0xff) << static_cast((outread4high>>16) & 0xff) << static_cast((outread4high>>8) & 0xff) << static_cast(outread4high & 0xff) << endl; assert(static_cast(outread4high & 0xff)=='M'); assert(static_cast((outread4high>>8) & 0xff)=='L'); assert(static_cast((outread4high>>16) & 0xff)=='K'); assert(static_cast((outread4high>>24) & 0xff)=='J'); //speedtest(); return 0; } exult-1.2/files/utils.cc0000644000175000001440000003423210003025430010732 /* * utils.cc - Common utility routines. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include # include #endif #include #include #ifdef MACOS #include #elif !defined(UNDER_CE) #include #endif #include #ifdef WIN32 #include #endif #include #include "exceptions.h" #include "utils.h" using std::cerr; using std::string; using std::ios; // Function prototypes static void switch_slashes(string & name); static bool base_to_uppercase(string& str, int count); // Wrap a few functions inline int stat(const std::string &file_name, struct stat *buf) { return stat(file_name.c_str(),buf); } // Ugly hack for supporting different paths static std::map path_map; static std::map stored_path_map; void store_system_paths() { stored_path_map = path_map; } void reset_system_paths() { path_map = stored_path_map; } void add_system_path(const string& key, const string& value) { if (!value.empty()) { path_map[key] = value; } else { clear_system_path(key); } } void clone_system_path(const string& new_key, const string& old_key) { if (is_system_path_defined(old_key)) { path_map[new_key] = path_map[old_key]; } else { clear_system_path(new_key); } } void clear_system_path(const string& key) { std::map::iterator iter = path_map.find(key); if (iter != path_map.end()) path_map.erase(iter); } /* * Has a path been entered? */ bool is_system_path_defined(const string& path) { return (path_map.find(path) != path_map.end()); } /* * Convert an exult path (e.g. "/exult.flx") into a system path */ string get_system_path(const string &path) { string new_path; string::size_type pos; string::size_type pos2; #if defined(__MORPHOS__) || defined(AMIGA) pos = path.find( "../" ); if( pos != string::npos ) new_path = path.substr( 0, pos )+path.substr( pos+2 ); else new_path = path; pos = new_path.find( "./" ); if( pos != string::npos ) new_path = new_path.substr( 0, pos )+new_path.substr( pos+2 ); pos = new_path.find('>'); pos2 = new_path.find('<'); // If there is no separator, return the path as is if(pos != string::npos && pos2 == 0) { pos += 1; // See if we can translate this prefix string syspath = new_path.substr(0, pos); if (is_system_path_defined(syspath)) { string new_prefix = path_map[syspath]; new_path = new_prefix + new_path.substr(pos); } } #else pos = path.find('>'); pos2 = path.find('<'); // If there is no separator, return the path as is if(pos == string::npos || pos2 != 0) { new_path = path; } else { pos += 1; // See if we can translate this prefix string syspath = path.substr(0, pos); if (is_system_path_defined(syspath)) { string new_prefix = path_map[syspath]; new_path = new_prefix + path.substr(pos); } else { new_path = path; } } #endif switch_slashes(new_path); #ifdef WIN32 if (*(new_path.end()-1) == '/' || *(new_path.end()-1) == '\\') { std::cerr << "Trailing slash in path: \"" << new_path << "\"" << std::endl << "...compensating, but go complain to Colourless anyway" << std::endl; new_path += '.'; } #ifdef NO_WIN32_PATH_SPACES pos = new_path.find('*'); pos2 = new_path.find('?'); string::size_type pos3 = new_path.find(' '); // pos and pos2 will equal each other if neither is found // and we'll only convert to short if a space is found // really, we don't need to do this, but hey, you never know if (pos == pos2 && pos3 != string::npos) { int num_chars = GetShortPathName(new_path.c_str(), NULL, 0); if (num_chars > 0) { char *short_path = new char [num_chars+1]; GetShortPathName(new_path.c_str(), short_path, num_chars+1); new_path = short_path; delete [] short_path; } //else std::cerr << "Warning unable to get short path for: " << new_path << std::endl; } #endif #endif return new_path; } /* * Convert a buffer to upper-case. * * Output: ->original buffer, changed to upper case. */ void to_uppercase(string &str) { for(string::iterator X = str.begin(); X != str.end(); ++X) { #if (defined(BEOS) || defined(OPENBSD) || defined(CYGWIN) || defined(__MORPHOS__)) if ((*X >= 'a') && (*X <= 'z')) *X -= 32; #else *X = std::toupper(*X); #endif } } string to_uppercase(const std::string &str) { string s(str); to_uppercase(s); return s; } /* * Convert just the last 'count' parts of a filename to uppercase. * returns false if there are less than 'count' parts */ static bool base_to_uppercase(string& str, int count) { if (count <= 0) return true; int todo = count; // Go backwards. string::reverse_iterator X; for(X = str.rbegin(); X != str.rend(); ++X) { // Stop at separator. if (*X == '/' || *X == '\\' || *X == ':') todo--; if (todo <= 0) break; #if (defined(BEOS) || defined(OPENBSD) || defined(CYGWIN) || defined(__MORPHOS__)) if ((*X >= 'a') && (*X <= 'z')) *X -= 32; #else *X = std::toupper(*X); #endif } if (X == str.rend()) todo--; // start of pathname counts as separator too // false if it didn't reach 'count' parts return (todo <= 0); } static void switch_slashes( string & name ) { #ifdef WIN32 for(string::iterator X = name.begin(); X != name.end(); ++X) { if(*X == '/' ) *X = '\\'; } #elif defined(MACOS) // We use a component-wise algorithm (suggested by Yorick) // Basically, split the path along the "/" seperators // If a component is empty or '.', remove it. If it's '..', replace it // with the empty string. convert all / to : string::size_type begIdx, endIdx;; string component; string new_name; if( name.at(0) != '/' ) new_name = ":"; begIdx = name.find_first_not_of('/'); while( begIdx != string::npos ) { endIdx = name.find_first_of('/', begIdx); if( endIdx == std::string::npos ) component = name.substr(begIdx); else component = name.substr(begIdx, endIdx-begIdx); if( component == ".." ) new_name += ":"; else if( !component.empty() && component != "." ) { new_name += component; if( endIdx != std::string::npos ) new_name += ":"; } begIdx = name.find_first_not_of('/', endIdx); } name = new_name; #else // do nothing #endif } /* * Open a file for input, * trying the original name (lower case), and the upper case version * of the name. * * Output: 0 if couldn't open. */ bool U7open ( std::ifstream& in, // Input stream to open. const char *fname, // May be converted to upper-case. bool is_text // Should the file be opened in text mode ) { #if defined(MACOS) || (__GNUG__ > 2) std::ios_base::openmode mode = std::ios::in; if (!is_text) mode |= std::ios::binary; #elif defined(XWIN) int mode = std::ios::in; #else int mode = std::ios::in; if (!is_text) mode |= std::ios::binary; #endif string name = get_system_path(fname); int uppercasecount = 0; do { // We first "clear" the stream object. This is done to prevent // problems when re-using stream objects in.clear(); try { //std::cout << "trying: " << name << std::endl; in.open(name.c_str(), mode); // Try to open } catch (std::exception &) {} if (in.good() && !in.fail()) { //std::cout << "got it!" << std::endl; return true; // found it! } } while (base_to_uppercase(name, ++uppercasecount)); // file not found. throw (file_open_exception(get_system_path(fname))); return false; } #ifdef ALPHA_LINUX_CXX /* * Wraps around a bug in Compaq's cxx, which doesn't generate an external * symbol for this one implicitly because of is_text = false * * See function above for a functional description */ bool U7open(std::ifstream& in, const char *fname) { return U7open(in, fname, false); } #endif /* * Open a file for output, * trying the original name (lower case), and the upper case version * of the name. * * Output: 0 if couldn't open. */ bool U7open ( std::ofstream& out, // Output stream to open. const char *fname, // May be converted to upper-case. bool is_text // Should the file be opened in text mode ) { #if defined(MACOS) || (__GNUG__ > 2) std::ios_base::openmode mode = std::ios::out | std::ios::trunc; if (!is_text) mode |= std::ios::binary; #elif defined(XWIN) int mode = std::ios::out | std::ios::trunc; #else int mode = std::ios::out | std::ios::trunc; if (!is_text) mode |= std::ios::binary; #endif string name = get_system_path(fname); // We first "clear" the stream object. This is done to prevent // problems when re-using stream objects out.clear(); int uppercasecount = 0; do { out.open(name.c_str(), mode); // Try to open if (out.good()) return true; // found it! out.clear(); // Forget ye not } while (base_to_uppercase(name, ++uppercasecount)); // file not found. throw (file_open_exception(get_system_path(fname))); return false; } #ifdef ALPHA_LINUX_CXX /* * Wraps around a bug in Compaq's cxx, which doesn't generate an external * symbol for this one implicitly because of is_text = false * * See function above for a functional description */ bool U7open(std::ofstream& out, const char *fname) { return U7open(out, fname, false); } #endif /* * Open a file with the access rights specified in mode, * works just like fopen but in a system independant fashion. * * Output: A pointer to a FILE */ std::FILE* U7open ( const char *fname, // May be converted to upper-case. const char *mode // File access mode. ) { std::FILE* f; string name = get_system_path(fname); int uppercasecount = 0; do { f = std::fopen(name.c_str(), mode); // Try to open if (f) return f; // found it! } while (base_to_uppercase(name, ++uppercasecount)); // file not found. throw (file_open_exception(get_system_path(fname))); return 0; } /* * Remove a file taking care of paths etc. * */ void U7remove ( const char *fname // May be converted to upper-case. ) { string name = get_system_path(fname); #if defined(WIN32) && defined(UNICODE) const char *n = name.c_str(); int nLen = std::strlen(n)+1; LPTSTR lpszT = (LPTSTR) alloca(nLen*2); MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen); DeleteFile(lpszT); #else bool exists; struct stat sbuf; int uppercasecount = 0; do { exists = (stat(name, &sbuf) == 0); if (exists) { std::remove(name.c_str()); } } while (base_to_uppercase(name, ++uppercasecount)); std::remove(name.c_str()); #endif } /* * See if a file exists. */ bool U7exists ( const char *fname // May be converted to upper-case. ) { string name = get_system_path(fname); #ifdef UNDER_CE // This is a bit of a hack for WinCE const char *n = name.c_str(); int nLen = std::strlen(n)+1; LPTSTR lpszT = (LPTSTR) alloca(nLen*2); MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen); return GetFileAttributes(lpszT) != 0xFFFFFFFF; #else bool exists; struct stat sbuf; int uppercasecount = 0; do { exists = (stat(name, &sbuf) == 0); if (exists) return true; // found it! } while (base_to_uppercase(name, ++uppercasecount)); // file not found return false; #endif } /* * Create a directory */ int U7mkdir ( const char *dirname, // May be converted to upper-case. int mode ) { string name = get_system_path(dirname); #if (defined(MACOSX) || defined(BEOS)) // remove any trailing slashes string::size_type pos = name.find_last_not_of('/'); if (pos != string::npos) name.resize(pos+1); #endif #if defined(WIN32) && defined(UNICODE) const char *n = name.c_str(); int nLen = std::strlen(n)+1; LPTSTR lpszT = (LPTSTR) alloca(nLen*2); MultiByteToWideChar(CP_ACP, 0, n, -1, lpszT, nLen); return CreateDirectory(lpszT, NULL); #elif defined(WIN32) return mkdir(name.c_str()); #else return mkdir(name.c_str(), mode); // Create dir. if not already there. #endif } // These are not supported in WinCE (PocketPC) for now #ifndef UNDER_CE /* * Change the current directory * * TODO: Make this work in WinCE - Colourless */ int U7chdir ( const char *dirname // May be converted to upper-case. ) { #ifdef MACOS string name(dirname); switch_slashes(name); return chdir(name.c_str()); #else return chdir(dirname); #endif } /* * Copy a file. May throw an exception. * * TODO: Make this work in WinCE - Colourless */ void U7copy ( const char *src, const char *dest ) { std::ifstream in; std::ofstream out; try { U7open(in, src); U7open(out, dest); } catch (exult_exception& e) { in.close(); out.close(); throw (e); } const int bufsize = 0x8000; unsigned char *buf = new unsigned char[0x8000]; in.seekg(0, ios::end); // Get filesize. int filesize = in.tellg(); in.seekg(0, ios::beg); while (filesize > 0) // Copy. { int toread = bufsize < filesize ? bufsize : filesize; in.read(reinterpret_cast(buf), toread); out.write(reinterpret_cast(buf), toread); filesize -= toread; } out.flush(); delete [] buf; bool inok = in.good(), outok = out.good(); in.close(); out.close(); if (!inok) throw (file_read_exception((const char *)src)); if (!outok) throw (file_write_exception((const char *)dest)); return; } #endif //UNDER_CE /* * Take log2 of a number. * * Output: Log2 of n (0 if n==0). */ int Log2 ( uint32 n ) { int result = 0; for (n = n>>1; n; n = n>>1) result++; return result; } /* * Replacement for non-standard strdup function. */ char *newstrdup(const char *s) { if(!s) throw (std::invalid_argument("NULL pointer passed to newstrdup")); char *ret=new char[std::strlen(s)+1]; std::strcpy(ret,s); return ret; } exult-1.2/gumps/0000777000175000001440000000000010062225332007404 5exult-1.2/gumps/Yesno_gump.cc0000755000175000001440000000654507516212522012000 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "Yesno_gump.h" #include "gamewin.h" #include "mouse.h" #include "game.h" #include "Gump_button.h" #include "Gump_manager.h" /* * Statics: */ short Yesno_gump::yesx = 63; short Yesno_gump::yesnoy = 45; short Yesno_gump::nox = 84; /* * A 'yes' or 'no' button. */ class Yesno_button : public Gump_button { int isyes; // 1 for 'yes', 0 for 'no'. public: Yesno_button(Gump *par, int px, int py, int yes) : Gump_button(par, yes ? game->get_shape("gumps/yesbtn") : game->get_shape("gumps/nobtn"), px, py), isyes(yes) { } // What to do when 'clicked': virtual void activate(); }; /* * Handle 'yes' or 'no' button. */ void Yesno_button::activate ( ) { ((Yesno_gump *) parent)->set_answer(isyes); } /* * Create a yes/no box. */ Yesno_gump::Yesno_gump ( const std::string &txt ) : Modal_gump(0, game->get_shape("gumps/yesnobox")), text(txt), answer(-1) { set_object_area(Rectangle(6, 6, 116, 30)); yes_button = new Yesno_button(this, yesx, yesnoy, 1); no_button = new Yesno_button(this, nox, yesnoy, 0); } /* * Done with yes/no box. */ Yesno_gump::~Yesno_gump ( ) { delete yes_button; delete no_button; } /* * Paint on screen. */ void Yesno_gump::paint ( ) { // Paint the gump itself. paint_shape(x, y); // Paint buttons. yes_button->paint(); no_button->paint(); // Paint text. sman->paint_text_box(2, text.c_str(), x + object_area.x, y + object_area.y, object_area.w, object_area.h, 2); gwin->set_painted(); } /* * Handle mouse-down events. */ void Yesno_gump::mouse_down ( int mx, int my // Position in window. ) { // Check buttons. if (yes_button->on_button(mx, my)) pushed = yes_button; else if (no_button->on_button(mx, my)) pushed = no_button; else { pushed = 0; return; } pushed->push(); // Show it. } /* * Handle mouse-up events. */ void Yesno_gump::mouse_up ( int mx, int my // Position in window. ) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) pushed->activate(); pushed = 0; } } /* * Handle ASCII character typed. */ void Yesno_gump::key_down(int chr) { if (chr == 'y' || chr == 'Y' || chr == SDLK_RETURN) set_answer(1); else if (chr == 'n' || chr == 'N' || chr == SDLK_ESCAPE) set_answer(0); } /* * Get an answer to a question. * * Output: 1 if yes, 0 if no or ESC. */ int Yesno_gump::ask ( const char *txt // What to ask. ) { Yesno_gump *dlg = new Yesno_gump(txt); int answer; if (!gumpman->do_modal_gump(dlg, Mouse::hand)) answer = 0; else answer = dlg->get_answer(); delete dlg; return (answer); } exult-1.2/gumps/AudioOptions_gump.cc0000644000175000001440000003216210012472067013304 /* * Copyright (C) 2003-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include #include "Audio.h" #include "AudioOptions_gump.h" #include "Configuration.h" #include "Gump_button.h" #include "Gump_ToggleButton.h" #include "exult.h" #include "exult_flx.h" #include "gamewin.h" #include "mouse.h" #include "xmidi.h" #include "Enabled_button.h" using std::cerr; using std::endl; static const int rowy[] = { 5, 19, 29, 41, 53, 65, 77, 89, 101, 115, 125, 135, 156 }; static const int colx[] = { 35, 55, 130 }; static const char* oktext = "OK"; static const char* canceltext = "CANCEL"; class AudioOptions_button : public Text_button { public: AudioOptions_button(Gump *par, const std::string &text, int px, int py) : Text_button(par, text, px, py, 59, 11) { } // What to do when 'clicked': virtual void activate(); }; void AudioOptions_button::activate() { if (text == canceltext) { ((AudioOptions_gump*)parent)->cancel(); } else if (text == oktext) { ((AudioOptions_gump*)parent)->close(); } } class AudioTextToggle : public Gump_ToggleTextButton { public: AudioTextToggle(Gump* par, std::string *s, int px, int py, int width, int selectionnum, int numsel) : Gump_ToggleTextButton(par, s, selectionnum, numsel, px, py, width) { } friend class AudioOptions_gump; virtual void toggle(int state) { ((AudioOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; class AudioEnabledToggle : public Enabled_button { public: AudioEnabledToggle(Gump* par, int px, int py, int selectionnum) : Enabled_button(par, selectionnum, px, py, 59) { } friend class AudioOptions_gump; virtual void toggle(int state) { ((AudioOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; void AudioOptions_gump::close() { save_settings(); done = 1; } void AudioOptions_gump::cancel() { done = 1; } void AudioOptions_gump::toggle(Gump_button* btn, int state) { if (btn == buttons[0]) { // audio on/off audio_enabled = state; rebuild_buttons(); paint(); } else if (btn == buttons[1]) { // midi on/off midi_enabled = state; rebuild_midi_buttons(); paint(); } else if (btn == buttons[2]) { // midi driver midi_driver = state; rebuild_mididriveroption_buttons(); paint(); } else if (btn == buttons[3]) { // midi conversion midi_conversion = state; } else if (btn == buttons[4]) { // midi reverb/chorus midi_reverb_chorus = state; } else if (btn == buttons[5]) { // midi looping midi_looping = state; } else if (btn == buttons[6]) { // sfx on/off sfx_enabled = state; rebuild_sfx_buttons(); paint(); #ifdef ENABLE_MIDISFX } else if (btn == buttons[7]) { // sfx conversion if (state == 1) { sfx_conversion = XMIDI_CONVERT_GS127_TO_GS; } else { sfx_conversion = XMIDI_CONVERT_NOCONVERSION; } #endif } else if (btn == buttons[8]) { // speech on/off speech_enabled = state; } } void AudioOptions_gump::rebuild_buttons() { for (unsigned int i = 1; i < 9; ++i) { delete buttons[i]; buttons[i] = 0; } if (!audio_enabled) return; // midi on/off buttons[1] = new AudioEnabledToggle(this, colx[2], rowy[2], midi_enabled); if (midi_enabled) rebuild_midi_buttons(); // sfx on/off buttons[6] = new AudioEnabledToggle(this, colx[2], rowy[8], sfx_enabled); if (sfx_enabled) rebuild_sfx_buttons(); // speech on/off buttons[8] = new AudioEnabledToggle(this,colx[2],rowy[11], speech_enabled); } void AudioOptions_gump::rebuild_midi_buttons() { for (unsigned int i = 2; i < 6; ++i) { delete buttons[i]; buttons[i] = 0; } if (!midi_enabled) return; std::string* midi_drivertext = new std::string[NUM_MIDI_DRIVER_TYPES]; midi_drivertext[MIDI_DRIVER_NORMAL] = std::string("Normal"); midi_drivertext[MIDI_DRIVER_OGG] = std::string("Digital"); #ifdef USE_FMOPL_MIDI midi_drivertext[MIDI_DRIVER_FMSYNTH] = std::string("FMSynth"); #endif #ifdef USE_MT32EMU_MIDI midi_drivertext[MIDI_DRIVER_MT32EMU] = std::string("MT32Emu"); #endif // midi driver buttons[2] = new AudioTextToggle(this, midi_drivertext, colx[2], rowy[3], 59, midi_driver, NUM_MIDI_DRIVER_TYPES); rebuild_mididriveroption_buttons(); // looping on/off buttons[5] = new AudioEnabledToggle(this, colx[2], rowy[6], midi_looping); } void AudioOptions_gump::rebuild_sfx_buttons() { delete buttons[7]; buttons[7] = 0; if (!sfx_enabled) return; #ifdef ENABLE_MIDISFX std::string* sfx_conversiontext = new std::string[2]; sfx_conversiontext[0] = "None"; sfx_conversiontext[1] = "GS"; // sfx conversion buttons[7] = new AudioTextToggle(this, sfx_conversiontext, colx[2], rowy[9], 59, sfx_conversion/4,2); #endif } void AudioOptions_gump::rebuild_mididriveroption_buttons() { delete buttons[3]; buttons[3] = 0; delete buttons[4]; buttons[4] = 0; std::string* midi_conversiontext = new std::string[4]; midi_conversiontext[0] = std::string("None"); midi_conversiontext[1] = std::string("GM"); midi_conversiontext[2] = std::string("GS"); midi_conversiontext[3] = std::string("GS127"); std::string* midi_reverbchorustext = new std::string[4]; midi_reverbchorustext[0] = std::string("Disabled"); midi_reverbchorustext[1] = std::string("Reverb"); midi_reverbchorustext[2] = std::string("Chorus"); midi_reverbchorustext[3] = std::string("Both"); if (midi_driver == MIDI_DRIVER_NORMAL) { // midi conversion buttons[3] = new AudioTextToggle(this, midi_conversiontext, colx[2], rowy[4], 59, midi_conversion, 4); // reverb/chorus combo buttons[4] = new AudioTextToggle(this, midi_reverbchorustext, colx[2], rowy[5], 59, midi_reverb_chorus, 4); } } void AudioOptions_gump::load_settings() { std::string s; audio_enabled = (Audio::get_ptr()->is_audio_enabled() ? 1 : 0); midi_enabled = (Audio::get_ptr()->is_music_enabled() ? 1 : 0); sfx_enabled = (Audio::get_ptr()->are_effects_enabled() ? 1 : 0); speech_enabled = (Audio::get_ptr()->is_speech_enabled() ? 1 : 0); midi_looping = (Audio::get_ptr()->is_music_looping_allowed() ? 1 : 0); if (Audio::get_ptr()->get_midi()) { midi_conversion = Audio::get_ptr()->get_midi()->get_music_conversion(); midi_driver = Audio::get_ptr()->get_midi()->get_output_driver_type(); #ifdef ENABLE_MIDISFX sfx_conversion =Audio::get_ptr()->get_midi()->get_effects_conversion(); #endif } else { // String for default value for driver type std::string driver_default = "normal"; config->value("config/audio/midi/convert",s,"gm"); if (s == "gs") midi_conversion = XMIDI_CONVERT_MT32_TO_GS; else if (s == "none") midi_conversion = XMIDI_CONVERT_NOCONVERSION; else if (s == "gs127") midi_conversion = XMIDI_CONVERT_MT32_TO_GS127; else if (s == "gs127drum") midi_conversion = XMIDI_CONVERT_MT32_TO_GS; else { midi_conversion = XMIDI_CONVERT_MT32_TO_GM; config->set("config/audio/midi/convert","gm",true); driver_default = "s"; } config->value("config/audio/midi/driver",s,driver_default.c_str()); if (s == "digital") { midi_driver = MIDI_DRIVER_OGG; config->set("config/audio/effects/driver","digital",true); } #ifdef USE_FMOPL_MIDI else if (s == "fmsynth") { midi_driver = MIDI_DRIVER_FMSYNTH; config->set("config/audio/effects/driver","fmsynth",true); } #endif #ifdef USE_MT32EMU_MIDI else if (s == "mt32emu") midi_driver = MIDI_DRIVER_MT32EMU; #endif else midi_driver = MIDI_DRIVER_NORMAL; #ifdef ENABLE_MIDISFX config->value("config/audio/effects/convert",s,"gs"); if (s == "none") sfx_conversion = XMIDI_CONVERT_NOCONVERSION; else if (s == "gs127") sfx_conversion = XMIDI_CONVERT_NOCONVERSION; else sfx_conversion = XMIDI_CONVERT_GS127_TO_GS; #endif } config->value("config/audio/midi/reverb/enabled",s,"no"); midi_reverb_chorus = (s == "yes" ? 1 : 0); config->value("config/audio/midi/chorus/enabled",s,"no"); midi_reverb_chorus |= (s == "yes" ? 2 : 0); } AudioOptions_gump::AudioOptions_gump() : Modal_gump(0, EXULT_FLX_AUDIOOPTIONS_SHP, SF_EXULT_FLX) { set_object_area(Rectangle(0,0,0,0), 8, 172);//++++++ ??? for (int i=0; i<12; i++) buttons[i] = 0; load_settings(); rebuild_buttons(); // audio on/off buttons[0] = new AudioEnabledToggle(this, colx[2], rowy[0], audio_enabled); // Ok buttons[9] = new AudioOptions_button(this, oktext, colx[0], rowy[12]); // Cancel buttons[10] = new AudioOptions_button(this, canceltext, colx[2], rowy[12]); } AudioOptions_gump::~AudioOptions_gump() { for (int i=0; i<12; i++) if (buttons[i]) delete buttons[i]; } void AudioOptions_gump::save_settings() { Audio::get_ptr()->set_audio_enabled(audio_enabled == 1); Audio::get_ptr()->set_music_enabled(midi_enabled == 1); if (!midi_enabled) // Stop what's playing. Audio::get_ptr()->stop_music(); Audio::get_ptr()->set_effects_enabled(sfx_enabled == 1); if (!sfx_enabled) // Stop what's playing. Audio::get_ptr()->stop_sound_effects(); Audio::get_ptr()->set_speech_enabled(speech_enabled == 1); Audio::get_ptr()->set_allow_music_looping(midi_looping == 1); config->set("config/audio/enabled", audio_enabled ? "yes" : "no", true); config->set("config/audio/midi/enabled",midi_enabled ? "yes" : "no", true); config->set("config/audio/effects/enabled",sfx_enabled?"yes":"no", true); config->set("config/audio/speech/enabled",speech_enabled?"yes":"no", true); config->set("config/audio/midi/chorus/enabled", (midi_reverb_chorus&2) ? "yes" : "no", true); config->set("config/audio/midi/reverb/enabled", (midi_reverb_chorus&1)? "yes" : "no", true); config->set("config/audio/midi/looping", midi_looping ? "yes" : "no", true); if (Audio::get_ptr()->get_midi()) { Audio::get_ptr()->get_midi()->set_music_conversion(midi_conversion); Audio::get_ptr()->get_midi()->set_effects_conversion(sfx_conversion); Audio::get_ptr()->get_midi()->set_output_driver_type(midi_driver); } else { switch(midi_conversion) { case XMIDI_CONVERT_MT32_TO_GS: config->set("config/audio/midi/convert","gs",true); break; case XMIDI_CONVERT_NOCONVERSION: config->set("config/audio/midi/convert","none",true); break; case XMIDI_CONVERT_MT32_TO_GS127: config->set("config/audio/midi/convert","gs127",true); break; default: config->set("config/audio/midi/convert","gm",true); break; } switch(midi_driver) { case MIDI_DRIVER_OGG: config->set("config/audio/midi/driver","digital",true); break; #ifdef USE_FMOPL_MIDI case MIDI_DRIVER_FMSYNTH: config->set("config/audio/midi/driver","fmsynth",true); break; #endif #ifdef USE_MT32EMU_MIDI case MIDI_DRIVER_MT32EMU: config->set("config/audio/midi/driver","mt32emu",true); break; #endif default: config->set("config/audio/midi/driver","normal",true); break; } #ifdef ENABLE_MIDISFX switch(sfx_conversion) { case XMIDI_CONVERT_NOCONVERSION: config->set("config/audio/effects/convert","none",true); break; default: config->set("config/audio/effects/convert","gs",true); break; } #endif } } void AudioOptions_gump::paint() { Gump::paint(); for (int i=0; i<11; i++) if (buttons[i]) buttons[i]->paint(); sman->paint_text(2, "Audio:", x + colx[0], y + rowy[0] + 1); if (audio_enabled) { sman->paint_text(2, "Music options:", x + colx[0], y + rowy[1] + 1); sman->paint_text(2, "music", x + colx[1], y + rowy[2] + 1); if (midi_enabled) { sman->paint_text(2, "driver", x + colx[1], y + rowy[3] + 1); if (midi_driver == MIDI_DRIVER_NORMAL) { sman->paint_text(2, "conversion", x+colx[1], y+rowy[4] + 1); sman->paint_text(2, "effects", x + colx[1], y + rowy[5] + 1); } sman->paint_text(2, "looping", x + colx[1], y + rowy[6] + 1); } sman->paint_text(2, "SFX options:", x + colx[0], y + rowy[7] + 1); sman->paint_text(2, "SFX", x + colx[1], y + rowy[8] + 1); #ifdef ENABLE_MIDISFX if (sfx_enabled) { sman->paint_text(2, "conversion", x + colx[1], y + rowy[9] + 1); } #endif sman->paint_text(2, "Speech options:", x + colx[0], y + rowy[10] + 1); sman->paint_text(2, "speech", x + colx[1], y + rowy[11] + 1); } gwin->set_painted(); } void AudioOptions_gump::mouse_down(int mx, int my) { pushed = Gump::on_button(mx, my); // First try checkmark. // Try buttons at bottom. if (!pushed) for (int i=0; i<11; i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } } void AudioOptions_gump::mouse_up(int mx, int my) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) ((Gump_button*)pushed)->activate(); pushed = 0; } } exult-1.2/gumps/Text_gump.h0000755000175000001440000000271007506441032011456 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _TEXT_GUMP_H_ #define _TEXT_GUMP_H_ #include "Gump.h" /* * A text gump is the base class for books and scrolls. */ class Text_gump : public Gump { UNREPLICATABLE_CLASS(Text_gump); protected: char *text; // The text. int textlen; // Length of text. int curtop; // Offset of top of current page. int curend; // Offset past end of current page(s). bool serpentine; // Serpentine text. SI ONLY! public: Text_gump(int shapenum, bool serp = false) : Gump(0, shapenum), text(0), textlen(0), curtop(0), curend(0), serpentine(serp) { } ~Text_gump() { delete [] text; } void add_text(const char *str); // Append text. int paint_page(Rectangle box, int start); // Next page of book/scroll. int show_next_page(); }; #endif exult-1.2/gumps/Jawbone_gump.cc0000644000175000001440000000701107506445352012262 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "game.h" #include "Jawbone_gump.h" #include "contain.h" #include "gamewin.h" #include "objiter.h" #include "misc_buttons.h" #include "jawbone.h" const int toothx[19] = { 34, 32, 31, 31, 28, 31, 27, 31, 40, 50, 57, 63, 72, 70, 75, 82, 83, 87, 0 }; const int toothy[19] = { 19, 30, 37, 44, 52, 57, 66, 77, 82, 84, 80, 71, 69, 61, 50, 42, 36, 32, 0 }; Jawbone_gump::Jawbone_gump ( Jawbone_object *cont, // Jawbone it represents. int initx, int inity // Coords. on screen. ) : Gump(cont, initx, inity, game->get_shape("gumps/jawbone")), jawbone(cont) { set_object_area(Rectangle(0, 0, 138, 116), 10, 109); } int Jawbone_gump::add(Game_object *obj, int mx, int my, int sx, int sy, bool dont_check, bool combine) { // Jawbone_object handles all the checks required return jawbone->add(obj, dont_check, combine); } void Jawbone_gump::paint() { // Paint gump itself paint_shape(x, y); // Paint red "checkmark". check_button->paint(); jawbone->find_teeth(); int i; // Blame MSVC for (i=0; i<9; i++) if (jawbone->teeth[i]) paint_tooth(i); for (i=17; i>8; i--) if (jawbone->teeth[i]) paint_tooth(i); } void Jawbone_gump::paint_tooth(int index) { ShapeID shape(game->get_shape("gumps/tooth"), index, SF_GUMPS_VGA); int objx = toothx[index]; int objy = toothy[index]; shape.paint_shape(x + objx, y + objy); } Game_object *Jawbone_gump::find_object(int mx, int my) { jawbone->find_teeth(); // get position relative to gump mx -= x; my -= y; int i; // Blame MSVC // reverse of drawing order for (i=9; i<18; i++) if (jawbone->teeth[i] && on_tooth(mx, my, i)) { // set correct position (otherwise tooth won't be on mouse cursor) set_to_spot(jawbone->teeth[i], mx, my); return jawbone->teeth[i]; } for (i=8; i>=0; i--) if (jawbone->teeth[i] && on_tooth(mx, my, i)) { // set correct position (otherwise tooth won't be on mouse cursor) set_to_spot(jawbone->teeth[i], mx, my); return jawbone->teeth[i]; } return 0; } bool Jawbone_gump::on_tooth(int sx, int sy, int index) { ShapeID sid(game->get_shape("gumps/tooth"), index, SF_GUMPS_VGA); Shape_frame *shape = sid.get_shape(); int objx = toothx[index]; int objy = toothy[index]; Rectangle r = gwin->get_shape_rect (shape, 0, 0); if (r.has_point (sx - objx, sy - objy) && shape->has_point (sx - objx, sy - objy)) return true; return false; } void Jawbone_gump::set_to_spot(Game_object *obj, int sx, int sy) { if (obj->get_shapenum() != 559) // not a serpent tooth? return; int fr = obj->get_framenum(); // Get shape. Shape_frame *shape = obj->get_shape(); // Height and width int w = shape->get_width(), h = shape->get_height(); // Set object's position. obj->set_chunk(sx + shape->get_xleft() - w/2, sy + shape->get_yabove() - h/2); } exult-1.2/gumps/Modal_gump.h0000755000175000001440000000363307567577644011625 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MODAL_GUMP_H_ #define _MODAL_GUMP_H_ #include "Gump.h" #include "SDL_events.h" /* * A modal gump object represents a 'dialog' that grabs the mouse until * the user clicks okay. */ class Modal_gump : public Gump { UNREPLICATABLE_CLASS(Modal_gump); protected: bool done; // true when user clicks checkmark. Gump_button *pushed; // Button currently being pushed. public: Modal_gump(Container_game_object *cont, int initx, int inity, int shnum, ShapeFile shfile = SF_GUMPS_VGA) : Gump(cont, initx, inity, shnum, shfile), done(false), pushed(0) { } // Create centered. Modal_gump(Container_game_object *cont, int shnum, ShapeFile shfile = SF_GUMPS_VGA) : Gump(cont, shnum, shfile), done(false), pushed(0) { } bool is_done() { return done; } // Handle events: virtual void mouse_down(int mx, int my) = 0; virtual void mouse_up(int mx, int my) = 0; virtual void mousewheel_down() { } virtual void mousewheel_up() { } virtual void mouse_drag(int mx, int my) { } virtual void key_down(int chr) // Key pressed { } virtual void text_input(int chr, int unicode) // Character typed (unicode) { } virtual bool is_modal() const { return true; } }; #endif exult-1.2/gumps/Gump.cc0000755000175000001440000002273107570073355010567 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "game.h" #include "gamewin.h" #include "Gump_button.h" #include "Gump.h" #include "misc_buttons.h" #include "contain.h" #include "objiter.h" #include "Gump_manager.h" #include "cheat.h" /* * Create a gump. */ Gump::Gump ( Container_game_object *cont, // Container it represents. int initx, int inity, // Coords. on screen. int shnum, // Shape #. ShapeFile shfile ) : ShapeID(shnum, 0, shfile), container(cont), x(initx), y(inity), check_button(0) { } /* * Create, centered on screen. */ Gump::Gump ( Container_game_object *cont, // Container it represents. int shnum, // Shape #. ShapeFile shfile ) : ShapeID(shnum, 0, shfile), container(cont), check_button(0) { Shape_frame *shape = get_shape(); x = (gwin->get_width() - shape->get_width())/2; y = (gwin->get_height() - shape->get_height())/2; } /* * Delete gump. */ Gump::~Gump() { if( check_button ) { delete check_button; check_button = 0; } } /* * Set centered. */ void Gump::set_pos() { Shape_frame *shape = get_shape(); x = (gwin->get_width() - shape->get_width())/2; y = (gwin->get_height() - shape->get_height())/2; } /* * Sets object area and creates checkmark button */ void Gump::set_object_area ( Rectangle area, int checkx, int checky ) { object_area = area; checkx += 16; checky -= 12; check_button = new Checkmark_button(this, checkx, checky); } /* * Get screen rectangle for one of our objects. */ Rectangle Gump::get_shape_rect ( Game_object *obj ) { Shape_frame *s = obj->get_shape(); if (!s) return Rectangle(0, 0, 0, 0); return Rectangle(x + object_area.x + obj->get_cx() - s->get_xleft(), y + object_area.y + obj->get_cy() - s->get_yabove(), s->get_width(), s->get_height()); } /* * Get screen location of object within. */ void Gump::get_shape_location ( Game_object *obj, int& ox, int& oy ) { ox = x + object_area.x + obj->get_cx(), oy = y + object_area.y + obj->get_cy(); } /* * Find object a screen point is on. * * Output: Object found, or null. */ Game_object *Gump::find_object ( int mx, int my // Mouse pos. on screen. ) { int cnt = 0; Game_object *list[100]; if (!container) return (0); Object_iterator next(container->get_objects()); Game_object *obj; Shape_frame *s; int ox, oy; while ((obj = next.get_next()) != 0) { Rectangle box = get_shape_rect(obj); if (box.has_point(mx, my)) { s = obj->get_shape(); get_shape_location(obj, ox, oy); if (s->has_point(mx-ox, my-oy)) list[cnt++] = obj; } obj = obj->get_next(); } // ++++++Return top item. return (cnt ? list[cnt - 1] : 0); } /* * Get the entire screen rectangle covered by this gump and its contents. */ Rectangle Gump::get_dirty ( ) { Rectangle rect = get_rect(); if (!container) return rect; Object_iterator next(container->get_objects()); Game_object *obj; while ((obj = next.get_next()) != 0) { Rectangle orect = get_shape_rect(obj); rect = rect.add(orect); } return rect; } /* * Get object this belongs to. */ Game_object *Gump::get_owner() { return container; } /* * Is a given screen point on the checkmark? * * Output: ->button if so. */ Gump_button *Gump::on_button ( int mx, int my // Point in window. ) { return (check_button->on_button(mx, my) ? check_button : 0); } /* * Add an object. If mx, my, sx, sy are all -1, the object's position * is calculated by 'paint()'. If they're all -2, it's assumed that * obj->cx, obj->cy are already correct. * * Output: 0 if cannot add it. */ int Gump::add ( Game_object *obj, int mx, int my, // Mouse location. int sx, int sy, // Screen location of obj's hotspot. bool dont_check, // Skip volume check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { if (!container || (!dont_check && !container->has_room(obj))) return (0); // Full. // Dropping on same thing? Game_object *onobj = find_object(mx, my); // If possible, combine. if (onobj && onobj != obj && onobj->drop(obj)) return (1); if (!container->add(obj, dont_check)) // DON'T combine here. return (0); // Not a valid spot? if (sx == -1 && sy == -1 && mx == -1 && my == -1) // Let paint() set spot. obj->set_chunk(255, 255); // -2's mean cx, cy are already set. else if (sx != -2 && sy != -2 && mx != -2 && my != -2) { // Put it where desired. sx -= x + object_area.x;// Get point rel. to object_area. sy -= y + object_area.y; Shape_frame *shape = obj->get_shape(); // But shift within range. if (sx - shape->get_xleft() < 0) sx = shape->get_xleft(); else if (sx + shape->get_xright() > object_area.w) sx = object_area.w - shape->get_xright(); if (sy - shape->get_yabove() < 0) sy = shape->get_yabove(); else if (sy + shape->get_ybelow() > object_area.h) sy = object_area.h - shape->get_ybelow(); obj->set_chunk(sx, sy); } return (1); } /* * Remove object. */ void Gump::remove ( Game_object *obj ) { container->remove(obj); // Paint Objects Rectangle box = object_area; // Paint objects inside. box.shift(x, y); // Set box to screen location. gwin->set_all_dirty(); gwin->paint_dirty(); } /* * Paint on screen. */ void Gump::paint ( ) { // Paint the gump itself. paint_shape(x, y); // Paint red "checkmark". if (check_button) check_button->paint(); if (!container) return; // Empty. Object_list& objects = container->get_objects(); if (objects.is_empty()) return; // Empty. Rectangle box = object_area; // Paint objects inside. box.shift(x, y); // Set box to screen location. int cury = 0, curx = 0; int endy = box.h, endx = box.w; int loop = 0; // # of times covering container. Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { Shape_frame *shape = obj->get_shape(); if (!shape) continue; int objx = obj->get_cx() - shape->get_xleft() + 1 + object_area.x; int objy = obj->get_cy() - shape->get_yabove() + 1 + object_area.y; // Does obj. appear to be placed? if (!object_area.has_point(objx, objy) || !object_area.has_point(objx + shape->get_xright() - 1, objy + shape->get_ybelow() - 1)) { // No. int px = curx + shape->get_width(), py = cury + shape->get_height(); if (px > endx) px = endx; if (py > endy) py = endy; obj->set_chunk(px - shape->get_xright(), py - shape->get_ybelow()); // Mostly avoid overlap. curx += shape->get_width() - 1; if (curx >= endx) { cury += 8; curx = 0; if (cury >= endy) cury = 2*(++loop); } } obj->paint_shape(box.x + obj->get_cx(),box.y + obj->get_cy()); obj = obj->get_next(); } // Outline selections in this gump. const Game_object_vector& sel = cheat.get_selected(); for (Game_object_vector::const_iterator it = sel.begin(); it != sel.end(); ++it) { Game_object *obj = *it; if (container == obj->get_owner()) { int x, y; get_shape_location(obj, x, y); obj->ShapeID::paint_outline(x, y, HIT_PIXEL); } } } /* * Close and delete. */ void Gump::close ( ) { gumpman->close_gump(this); } /* * Does the gump have this spot */ bool Gump::has_point(int sx, int sy) { Shape_frame *s = get_shape(); if (s && s->has_point(sx - x, sy - y)) return true; return false; } /* * Get screen area used by a gump. */ Rectangle Gump::get_rect() { Shape_frame *s = get_shape(); if (!s) return Rectangle(0,0,0,0); return Rectangle(x - s->get_xleft(), y - s->get_yabove(), s->get_width(), s->get_height()); } /* * Container_gump Initialize */ void Container_gump::initialize ( int shnum ) { if(shnum==game->get_shape("gumps/box")) { set_object_area(Rectangle(46, 28, 74, 32), 8, 56); } else if(shnum==game->get_shape("gumps/crate")) { set_object_area(Rectangle(50, 20, 80, 24), 8, 64); } else if(shnum==game->get_shape("gumps/barrel")) { set_object_area(Rectangle(32, 32, 40, 40), 12, 124); } else if(shnum==game->get_shape("gumps/bag")) { set_object_area(Rectangle(48, 20, 66, 44), 8, 66); } else if(shnum==game->get_shape("gumps/backpack")) { set_object_area(Rectangle(36, 36, 85, 40), 8, 62); } else if(shnum==game->get_shape("gumps/basket")) { set_object_area(Rectangle(42, 32, 70, 26), 8, 56); } else if(shnum==game->get_shape("gumps/chest")) { set_object_area(Rectangle(40, 18, 60, 37), 8, 46); } else if(shnum==game->get_shape("gumps/shipshold")) { set_object_area(Rectangle(38, 10, 82, 80), 8, 92); } else if(shnum==game->get_shape("gumps/drawer")) { set_object_area(Rectangle(36, 12, 70, 26), 8, 46); } else if(shnum==game->get_shape("gumps/tree")) { set_object_area(Rectangle(62, 22, 36, 44), 9, 100); } else if(shnum==game->get_shape("gumps/body")) { set_object_area(Rectangle(36, 46, 84, 40), 8, 70); } else set_object_area(Rectangle(52, 22, 60, 40)); } exult-1.2/gumps/Jawbone_gump.h0000644000175000001440000000274507506445352012135 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _JAWBONE_GUMP_H_ #define _JAWBONE_GUMP_H_ #include "Gump.h" class Game_object; class Container_game_object; class Game_window; class Jawbone_object; class Jawbone_gump : public Gump { public: Jawbone_gump(Jawbone_object *cont, int initx, int inity); ~Jawbone_gump() {} // Find the object the mouse is over virtual Game_object *find_object(int mx, int my); // Add object. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false); // Paint it and its contents. virtual void paint(); private: void set_to_spot(Game_object *obj, int sx, int sy); void paint_tooth(int index); bool on_tooth(int sx, int sy, int index); // is spot on tooth? Jawbone_object *jawbone; }; #endif exult-1.2/gumps/Gump.h0000755000175000001440000000771507516676114010440 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_H_ #define _GUMP_H_ #include "exceptions.h" #include "rect.h" #include "shapeid.h" class Checkmark_button; class Container_game_object; class Game_object; class Game_window; class Gump_button; class Gump_manager; /* * A gump contains an image of an open container from "gumps.vga". */ class Gump : public ShapeID, public Paintable { UNREPLICATABLE_CLASS(Gump); protected: Gump() : ShapeID() { }; Container_game_object *container;// What this gump shows. int x, y; // Location on screen. unsigned char shapenum; Rectangle object_area; // Area to paint objects in, rel. to // Where the 'checkmark' goes. Checkmark_button *check_button; void set_object_area(Rectangle area, int checkx = 8, int checky = 64); public: Gump(Container_game_object *cont, int initx, int inity, int shnum, ShapeFile shfile = SF_GUMPS_VGA); // Create centered. Gump(Container_game_object *cont, int shnum, ShapeFile shfile = SF_GUMPS_VGA); virtual ~Gump(); int get_x() // Get coords. { return x; } int get_y() { return y; } void set_pos(int newx, int newy)// Set new spot on screen. { x = newx; y = newy; } void set_pos(); // Set centered. Container_game_object *get_container() { return container; } virtual Container_game_object *find_actor(int mx, int my) { return 0; } inline Container_game_object *get_cont_or_actor(int mx, int my) { Container_game_object *ret = find_actor(mx, my); if (ret) return ret; return get_container(); } // Get screen rect. of obj. in here. Rectangle get_shape_rect(Game_object *obj); // Get screen loc. of object. void get_shape_location(Game_object *obj, int& ox, int& oy); // Find obj. containing mouse point. virtual Game_object *find_object(int mx, int my); virtual Rectangle get_dirty(); // Get dirty rect. for gump+contents. virtual Game_object *get_owner();// Get object this belongs to. // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); // Paint button. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false); virtual void remove(Game_object *obj); // Paint it and its contents. virtual void paint(); // Close (and delete). virtual void close(); // update the gump, if required virtual void update_gump () { } // Can be dragged with mouse virtual bool is_draggable() const { return true; } // Close on end_gump_mode virtual bool is_persistent() const { return false; } virtual bool is_modal() const { return false; } // Show the hand cursor virtual bool no_handcursor() const { return false; } virtual bool has_point(int x, int y); virtual Rectangle get_rect(); }; /* * A generic gump used by generic containers: */ class Container_gump : public Gump { UNREPLICATABLE_CLASS(Container_gump); void initialize(int shnum); // Initialize object_area. public: Container_gump(Container_game_object *cont, int initx, int inity, int shnum, ShapeFile shfile = SF_GUMPS_VGA) : Gump(cont, initx, inity, shnum, shfile) { initialize(shnum); } // Create centered. Container_gump(Container_game_object *cont, int shnum, ShapeFile shfile = SF_GUMPS_VGA) : Gump(cont, shnum, shfile) { initialize(shnum); } }; #endif exult-1.2/gumps/Slider_gump.h0000755000175000001440000000413007516212522011753 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SLIDER_GUMP_H_ #define _SLIDER_GUMP_H_ #include "Modal_gump.h" class Slider_button; /* * A slider for choosing a number. */ class Slider_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(Slider_gump,Modal_gump(0,0,0,0)); protected: // The arrows at each end: Slider_button *left_arrow, *right_arrow; int diamondx; // Rel. pos. where diamond is shown. static short diamondy; int min_val, max_val; // Max., min. values to choose from. int step_val; // Amount to step by. int val; // Current value. unsigned char dragging; // 1 if dragging the diamond. int prev_dragx; // Prev. x-coord. of mouse. void set_val(int newval); // Set to new value. // Coords: static short leftbtnx, rightbtnx, btny; static short xmin, xmax; ShapeID diamond; // Diamond public: Slider_gump(int mival, int mxval, int step, int defval); ~Slider_gump(); int get_val() // Get last value set. { return val; } // An arrow was clicked on. void clicked_arrow(Slider_button *arrow); void move_diamond(int dir); // Paint it and its contents. virtual void paint(); virtual void close() { done = 1; } // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); virtual void mouse_drag(int mx, int my); virtual void key_down(int chr); // Character typed. virtual void mousewheel_up(); virtual void mousewheel_down(); }; #endif exult-1.2/gumps/CombatStats_gump.h0000644000175000001440000000277207506445352012774 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMBATSTATS_GUMP_H_ #define _COMBATSTATS_GUMP_H_ #include "Gump.h" #include "misc_buttons.h" #include "Face_button.h" class Actor; /* * A rectangular area showing party combat statistics: */ class CombatStats_gump : public Gump { UNREPLICATABLE_CLASS(CombatStats_gump); public: CombatStats_gump(int initx, int inity); ~CombatStats_gump(); // Add object. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false) { return 0; } // Can't drop onto it. // Paint it and its contents. virtual void paint(); virtual Gump_button *on_button(int mx, int my); private: Actor* party[9]; int party_size; Halo_button* halo_btn[9]; Combat_mode_button* cmb_btn[9]; Face_button* face_btn[9]; }; #endif exult-1.2/gumps/Stats_gump.h0000755000175000001440000000301507506441032011627 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STATS_GUMP_H_ #define _STATS_GUMP_H_ #include "Gump.h" #include "misc_buttons.h" class Actor; /* * A rectangular area showing a character's statistics: */ class Stats_gump : public Gump { UNREPLICATABLE_CLASS(Stats_gump); protected: Actor *get_actor() { return (Actor *) container; } static short textx; // X-coord. of where to write. static short texty[10]; // Y-coords. public: Stats_gump(Container_game_object *cont, int initx, int inity); ~Stats_gump() { } // Add object. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false) { return 0; } // Can't drop onto it. // Paint it and its contents. virtual void paint(); virtual Game_object *find_object(int mx, int my) { return 0; } }; #endif exult-1.2/gumps/Face_stats.h0000644000175000001440000000422507506445352011567 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PARTY_PORTRAIT_H #define PARTY_PORTRAIT_H #include "Configuration.h" #include "Gump.h" class Actor; class Portrait_button; class Face_stats : public Gump { // Only allow for one to be made static Face_stats *self; static int mode; Face_stats(); int party_size; Portrait_button *party[8]; int npc_nums[8]; int resx; int resy; bool has_changed(); void create_buttons(); void delete_buttons(); Rectangle region; public: virtual ~Face_stats(); // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); virtual void paint(); // Don't close on end_gump_mode virtual bool is_persistent() const { return true; } // Can't be dragged with mouse virtual bool is_draggable() const { return false; } // Show the hand cursor virtual bool no_handcursor() const { return true; } virtual Rectangle get_rect() { return region; } virtual bool has_point(int x, int y); // add dirty region, if dirty virtual void update_gump(); virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false); virtual Container_game_object *find_actor(int mx, int my); static int get_state() { return self ? mode : -1; } static void CreateGump(); static void RemoveGump(); static void AdvanceState(); static void save_config(Configuration *config); static void load_config(Configuration *config); }; #endif //PARTY_PORTRAIT exult-1.2/gumps/Newfile_gump.cc0000644000175000001440000006764310054030560012266 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include #endif #include "exult_flx.h" #include "Audio.h" #include "Configuration.h" #include "Gump_button.h" #include "Newfile_gump.h" #include "Yesno_gump.h" #include "actors.h" #include "exult.h" #include "game.h" #include "gameclk.h" #include "gamewin.h" #include "listfiles.h" #include "mouse.h" #include "party.h" #include "Text_button.h" #ifndef UNDER_CE using std::atoi; using std::cout; using std::endl; using std::isdigit; using std::memcpy; using std::memset; using std::memmove; using std::qsort; using std::string; using std::strlen; using std::strncpy; using std::strcpy; using std::strcat; using std::time_t; using std::tm; #endif /* * Macros: */ /* * Statics: */ // Button Coords const short Newfile_gump::btn_rows[5] = {186, 2, 15, 158, 171}; const short Newfile_gump::btn_cols[5] = {2, 46, 88, 150, 210}; // Text field info const short Newfile_gump::fieldx = 2; // Start Y of each field const short Newfile_gump::fieldy = 2; // Start X of first const short Newfile_gump::fieldw = 207; // Width of each field const short Newfile_gump::fieldh = 12; // Height of each field const short Newfile_gump::fieldgap = 1; // Gap between fields const short Newfile_gump::fieldcount = 14; // Number of fields const short Newfile_gump::textx = 12; // X Offset in field const short Newfile_gump::texty = 2; // Y Offset in field const short Newfile_gump::textw = 190; // Maximum allowable width of text (pixels) const short Newfile_gump::iconx = 2; // X Offset in field const short Newfile_gump::icony = 2; // Y Offset in field // Scrollbar and Slider Info const short Newfile_gump::scrollx = 212; // X Offset const short Newfile_gump::scrolly = 28; // Y Offset const short Newfile_gump::scrollh = 129; // Height of Scroll Bar const short Newfile_gump::sliderw = 7; // Width of Slider const short Newfile_gump::sliderh = 7; // Height of Slider const short Newfile_gump::infox = 224; const short Newfile_gump::infoy = 67; const short Newfile_gump::infow = 92; const short Newfile_gump::infoh = 79; const char Newfile_gump::infostring[] = "Avatar: %s\n" "Exp: %i Hp: %i\n" "Str: %i Dxt: %i\n" "Int: %i Trn: %i\n" "\n" "Game Day: %i\n" "Game Time: %02i:%02i\n" "\n" "Save Count: %i\n" "Date: %i%s %s %04i\n" "Time: %02i:%02i"; const char *Newfile_gump::months[12] = {"Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" }; static const char *loadtext = "LOAD"; static const char *savetext = "SAVE"; static const char *deletetext = "DELETE"; static const char *canceltext = "CANCEL"; #ifdef UNDER_CE struct tm * __cdecl localtime(const time_t *it) { static tm t; memset(&t,0,sizeof(t)); SYSTEMTIME systime; FILETIME filetime; FILETIME local_filetime; LONGLONG time; SYSTEMTIME systime_1970; FILETIME filetime_1970; LONGLONG time_1970; systime_1970.wYear = 1970; systime_1970.wMonth = 1; systime_1970.wDay = 1; systime_1970.wHour = 0; systime_1970.wMinute = 0; systime_1970.wSecond = 0; systime_1970.wMilliseconds = 0; SystemTimeToFileTime(&systime_1970, &filetime_1970); memcpy(&time_1970, &filetime_1970, 8); // Seconds to 100 nanoseconds time = *it; time *= 10000000; time += time_1970; memcpy(&filetime, &time, 8); FileTimeToLocalFileTime(&filetime, &local_filetime); FileTimeToSystemTime(&local_filetime, &systime); t.tm_sec = systime.wSecond; t.tm_min = systime.wMinute; t.tm_hour = systime.wHour; t.tm_isdst = 0; t.tm_wday = systime.wDayOfWeek; t.tm_mday = systime.wDay; t.tm_mon = systime.wMonth - 1; t.tm_yday = 0; t.tm_year = systime.wYear - 1900; return &t; } time_t __cdecl time(time_t *t) { SYSTEMTIME systime; FILETIME filetime; LONGLONG time; SYSTEMTIME systime_1970; FILETIME filetime_1970; LONGLONG time_1970; GetSystemTime(&systime); SystemTimeToFileTime(&systime, &filetime); memcpy(&time, &filetime, 8); systime_1970.wYear = 1970; systime_1970.wMonth = 1; systime_1970.wDay = 1; systime_1970.wHour = 0; systime_1970.wMinute = 0; systime_1970.wSecond = 0; systime_1970.wMilliseconds = 0; SystemTimeToFileTime(&systime_1970, &filetime_1970); memcpy(&time_1970, &filetime_1970, 8); // Time since Jan First 1970 time -= time_1970; if (time < 0) time = 0; // 100 nanoseconds to Seconds time /= 10000000; if (t) *t = time; return time; } #endif /* * One of our buttons. */ class Newfile_button : public Gump_button { public: Newfile_button(Gump *par, int px, int py, int shapenum) : Gump_button(par, shapenum, px, py, SF_EXULT_FLX) { } // What to do when 'clicked': virtual void activate(); }; class Newfile_Textbutton : public Text_button { public: Newfile_Textbutton(Gump *par, string text, int px, int py, int width) : Text_button(par, text, px, py, width) { } virtual void activate(); }; /* * Clicked a 'load' or 'save' button. */ void Newfile_button::activate ( ) { int shapenum = get_shapenum(); if (shapenum == EXULT_FLX_SAV_DOWNDOWN_SHP) ((Newfile_gump *) parent)->scroll_page(1); else if (shapenum == EXULT_FLX_SAV_DOWN_SHP) ((Newfile_gump *) parent)->scroll_line(1); else if (shapenum == EXULT_FLX_SAV_UP_SHP) ((Newfile_gump *) parent)->scroll_line(-1); else if (shapenum == EXULT_FLX_SAV_UPUP_SHP) ((Newfile_gump *) parent)->scroll_page(-1); } void Newfile_Textbutton::activate() { if (text == loadtext) ((Newfile_gump *) parent)->load(); else if (text == savetext) ((Newfile_gump *) parent)->save(); else if (text == deletetext) ((Newfile_gump *) parent)->delete_file(); else if (text == canceltext) parent->close(); } /* * Create the load/save box. */ Newfile_gump::Newfile_gump ( ) : Modal_gump(0, gwin->get_width()/2-160, gwin->get_height()/2-100, EXULT_FLX_SAVEGUMP_SHP, SF_EXULT_FLX), restored(0), games(0), num_games(0), first_free(0), cur_shot(0), cur_details(0), cur_party(0), gd_shot(0), gd_details(0), gd_party(0), screenshot(0), details(0), party(0), is_readable(false), filename(0), list_position(-2), selected(-3), cursor(0), slide_start(-1) { set_object_area(Rectangle(0,0,320,200), -22, 190);//+++++ ??? newname[0] = 0; gwin->get_tqueue()->pause(SDL_GetTicks()); back = gwin->get_win()->create_buffer(gwin->get_width(), gwin->get_height()); gwin->get_win()->get(back, 0, 0); // Load/Save/Delete buttons[0] = buttons[1] = buttons[2] = 0; // Cancel buttons[3] = new Newfile_Textbutton(this, canceltext, btn_cols[3], btn_rows[0], 59); // Scrollers. buttons[4] = new Newfile_button(this, btn_cols[4], btn_rows[1], EXULT_FLX_SAV_UPUP_SHP); buttons[5] = new Newfile_button(this, btn_cols[4], btn_rows[2], EXULT_FLX_SAV_UP_SHP); buttons[6] = new Newfile_button(this, btn_cols[4], btn_rows[3], EXULT_FLX_SAV_DOWN_SHP); buttons[7] = new Newfile_button(this, btn_cols[4], btn_rows[4], EXULT_FLX_SAV_DOWNDOWN_SHP); LoadSaveGameDetails(); } /* * Delete the load/save box. */ Newfile_gump::~Newfile_gump ( ) { gwin->get_tqueue()->resume(SDL_GetTicks()); size_t i; for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) delete buttons[i]; FreeSaveGameDetails(); delete back; } /* * 'Load' clicked. */ void Newfile_gump::load() { // Shouldn't ever happen. if (selected == -2 || selected == -3) return; // Aborts if unsuccessful. if (selected != -1) gwin->restore_gamedat(games[selected].num); // Read Gamedat gwin->read(); // Set Done done = true; restored = 1; // Reset Selection selected = -3; delete buttons[0]; buttons[0] = 0; delete buttons[1]; buttons[1] = 0; delete buttons[2]; buttons[2] = 0; //Reread save game details (quick save gets overwritten) //FreeSaveGameDetails(); //LoadSaveGameDetails(); //paint(); //gwin->set_painted(); } /* * 'Save' clicked. */ void Newfile_gump::save() { // Shouldn't ever happen. if (!strlen(newname) || selected == -3) return; // Already a game in this slot? If so ask to delete if (selected != -2) if (!Yesno_gump::ask("Okay to write over existing saved game?")) return; // Write to gamedat gwin->write(); // Now write to savegame file if (selected >= 0) gwin->save_gamedat(games[selected].num, newname); else if (selected == -2) gwin->save_gamedat(first_free, newname); cout << "Saved game #" << selected << " successfully." << endl; // Reset everything selected = -3; delete buttons[0]; buttons[0] = 0; delete buttons[1]; buttons[1] = 0; delete buttons[2]; buttons[2] = 0; FreeSaveGameDetails(); LoadSaveGameDetails(); paint(); gwin->set_painted(); } /* * 'Delete' clicked. */ void Newfile_gump::delete_file() { // Shouldn't ever happen. if (selected == -1 || selected == -2 || selected == -3) return; // Ask to delete if (!Yesno_gump::ask("Okay to delete saved game?")) return; U7remove (games[selected].filename); filename = 0; is_readable = false; cout << "Deleted Save game #" << selected << " (" << games[selected].filename << ") successfully." << endl; // Reset everything selected = -3; delete buttons[0]; buttons[0] = 0; delete buttons[1]; buttons[1] = 0; delete buttons[2]; buttons[2] = 0; FreeSaveGameDetails(); LoadSaveGameDetails(); paint(); gwin->set_painted(); } /* * Scroll Line */ void Newfile_gump::scroll_line(int dir) { list_position += dir; if (list_position > num_games-fieldcount) list_position = num_games-fieldcount; if (list_position < -2) list_position = -2; #ifdef DEBUG cout << "New list position " << list_position << endl; #endif paint(); gwin->set_painted(); } /* * Scroll Page */ void Newfile_gump::scroll_page(int dir) { scroll_line (dir * fieldcount); } void Newfile_gump::PaintSaveName (int line) { int actual_game = line+list_position; if (actual_game < -2 || actual_game >= num_games) return; char *text; if (actual_game == -1) text = "Quick Save"; else if (actual_game == -2 && selected != -2) text = "Empty Slot"; else if (actual_game != selected || buttons[0]) text = games[actual_game].savename; else text = newname; sman->paint_text (2, text, x + fieldx + textx, y + fieldy + texty + line*(fieldh + fieldgap)); // Being Edited? If so paint cursor if (selected == actual_game && cursor != -1) gwin->get_win()->fill8(0, 1, sman->get_text_height(2), x + fieldx + textx + sman->get_text_width(2, text, cursor), y + fieldy + texty + line*(fieldh + fieldgap)); // If selected, show selected icon if (selected == actual_game) { ShapeID icon (EXULT_FLX_SAV_SELECTED_SHP, 0, SF_EXULT_FLX); icon.paint_shape ( x+fieldx+iconx, y+fieldy+icony+line*(fieldh+fieldgap)); } } /* * Paint on screen. */ void Newfile_gump::paint ( ) { if (!games) return; // No list, so skip out. Gump::paint(); // Paint text objects. int i; for (i = 0; i < fieldcount; i++) PaintSaveName (i); // Paint Buttons for (i = 0; i < 8; i++) if (buttons[i]) buttons[i]->paint(); // Paint scroller // First thing, work out number of positions that the scroller can be in int num_pos = (2+num_games)-fieldcount; if (num_pos < 1) num_pos = 1; // Now work out the position int pos = ((scrollh-sliderh)*(list_position+2))/num_pos; ShapeID slider_shape(EXULT_FLX_SAV_SLIDER_SHP, 0, SF_EXULT_FLX); slider_shape.paint_shape(x+scrollx , y+scrolly+pos); // Now paint the savegame details if (screenshot) sman->paint_shape(x + 222, y + 2, screenshot->get_frame(0)); // Need to ensure that the avatar's shape actually exists if (party && party[0].shape_file == SF_BG_SISHAPES_VGA && !sman->can_use_multiracial()) { party[0].shape_file = SF_SHAPES_VGA; // Female if odd, male if even if (party[0].shape %2) party[0].shape = 989; else party[0].shape = 721; } if (details && party) { int i; for (i=0; i<4 && iparty_size; i++) { ShapeID shape(party[i].shape, 16, (ShapeFile) party[i].shape_file); shape.paint_shape(x + 249 + i*23, y + 169); } for (i=4; i<8 && iparty_size; i++) { ShapeID shape(party[i].shape, 16, (ShapeFile) party[i].shape_file); shape.paint_shape(x + 249 + (i-4)*23, y + 198); } char info[320]; char *suffix = "th"; if ((details->real_day%10) == 1 && details->real_day != 11) suffix = "st"; else if ((details->real_day%10) == 2 && details->real_day != 12) suffix = "nd"; else if ((details->real_day%10) == 3 && details->real_day != 13) suffix = "rd"; snprintf (info, 320, infostring, party[0].name, party[0].exp, party[0].health, party[0].str, party[0].dext, party[0].intel, party[0].training, details->game_day, details->game_hour, details->game_minute, details->save_count, details->real_day, suffix, months[details->real_month-1], details->real_year, details->real_hour, details->real_minute); if (filename) { std::strncat (info, "\nFile: ", 320); int offset = strlen(filename); while (offset--) { if (filename[offset] == '/' || filename[offset] == '\\') { offset++; break; } } std::strncat (info, filename+offset, 320); } sman->paint_text_box (4, info, x+infox, y+infoy, infow, infoh); } else { if (filename) { char info[64] = {0}; std::strncat (info, "File: ", 64); int offset = strlen(filename); while (offset--) { if (filename[offset] == '/' || filename[offset] == '\\') { offset++; break; } } std::strncat (info, filename+offset, 64); sman->paint_text_box (4, info, x+infox, y+infoy, infow, infoh); } if (!is_readable) { sman->paint_text (2, "Unreadable", x+infox+(infow-sman->get_text_width(2, "Unreadable"))/2, y+infoy+(infoh-18)/2); sman->paint_text (2, "Savegame", x+infox+(infow-sman->get_text_width(2, "Savegame"))/2, y+infoy+(infoh)/2); } else { sman->paint_text (4, "No Info", x+infox+(infow-sman->get_text_width(4, "No Info"))/2, y+infoy+(infoh-sman->get_text_height(4))/2); } } gwin->set_painted(); } /* * Handle mouse-down events. */ void Newfile_gump::mouse_down ( int mx, int my // Position in window. ) { slide_start = -1; pushed = Gump::on_button(mx, my); // Try buttons at bottom. if (!pushed) for (size_t i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } int gx = mx - x; int gy = my - y; // Check for scroller if (gx >= scrollx && gx < scrollx+sliderw && gy >= scrolly && gy < scrolly+scrollh) { int num_pos = (2+num_games)-fieldcount; if (num_pos < 1) num_pos = 1; // Now work out the position int pos = ((scrollh-sliderh)*(list_position+2))/num_pos; // Pressed above it if (gy < pos+scrolly) { scroll_page(-1); paint(); return; } // Pressed below it else if (gy >= pos+scrolly+sliderh) { scroll_page(1); paint(); return; } // Pressed on it else { slide_start = gy; return; } } // Now check for text fields if (gx < fieldx || gx >= fieldx+fieldw) return; int hit = -1; int i; for (i = 0; i < fieldcount; i++) { int fy = fieldy + i*(fieldh + fieldgap); if (gy >= fy && gy < fy+fieldh) { hit = i; break; } } if (hit == -1) return; if (hit+list_position >= num_games || hit+list_position < -2 || selected == hit+list_position) return; #ifdef DEBUG cout << "Hit a save game field" << endl; #endif selected = hit+list_position; int want_load = true; int want_delete = true; int want_save = true; if (selected == -2) { want_load = false; want_delete = false; want_save = false; screenshot = cur_shot; details = cur_details; party = cur_party; newname[0] = 0; cursor = 0; is_readable = true; filename = 0; } else if (selected == -1) { want_delete = false; screenshot = gd_shot; details = gd_details; party = gd_party; strcpy (newname, "Quick Save"); cursor = -1; // No cursor is_readable = true; filename = 0; } else { screenshot = games[selected].screenshot; details = games[selected].details; party = games[selected].party; strcpy (newname, games[selected].savename); cursor = strlen (newname); is_readable = want_load = games[selected].readable; filename = games[selected].filename; } if (!buttons[0] && want_load) buttons[0] = new Newfile_Textbutton(this, loadtext, btn_cols[1], btn_rows[0], 39); else if (buttons[0] && !want_load) { delete buttons[0]; buttons[0] = 0; } if (!buttons[1] && want_save) buttons[1] = new Newfile_Textbutton(this, savetext, btn_cols[0], btn_rows[0], 40); else if (buttons[1] && !want_save) { delete buttons[1]; buttons[1] = 0; } if (!buttons[2] && want_delete) buttons[2] = new Newfile_Textbutton(this, deletetext, btn_cols[2], btn_rows[0], 59); else if (buttons[2] && !want_delete) { delete buttons[2]; buttons[2] = 0; } paint(); // Repaint. gwin->set_painted(); // See if on text field. } /* * Handle mouse-up events. */ void Newfile_gump::mouse_up ( int mx, int my // Position in window. ) { slide_start = -1; if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) pushed->activate(); pushed = 0; } } void Newfile_gump::mousewheel_up() { SDLMod mod = SDL_GetModState(); if (mod & KMOD_ALT) scroll_page(-1); else scroll_line(-1); } void Newfile_gump::mousewheel_down() { SDLMod mod = SDL_GetModState(); if (mod & KMOD_ALT) scroll_page(1); else scroll_line(1); } /* * Mouse was dragged with left button down. */ void Newfile_gump::mouse_drag ( int mx, int my // Where mouse is. ) { // If not sliding don't do anything if (slide_start == -1) return; int gx = mx - x; int gy = my - y; // First if the position is too far away from the slider // We'll put it back to the start int sy = gy - scrolly; if (gx < scrollx-20 || gx > scrollx+sliderw+20) sy = slide_start - scrolly; if (sy < sliderh/2) sy = sliderh/2; if (sy > scrollh-sliderh/2) sy = scrollh-sliderh/2; sy -= sliderh/2; // Now work out the number of positions int num_pos = (2+num_games)-fieldcount; // Can't scroll if there is less than 1 pos if (num_pos < 1) return; // Now work out the closest position to here position int new_pos = ((sy*num_pos*2)/(scrollh-sliderh)+1)/2-2; if (new_pos != list_position) { list_position = new_pos; paint(); } } /* * Handle character that was typed. */ void Newfile_gump::text_input(int chr, int unicode) { bool update_details = false; int repaint = false; // Are we selected on some text? if (selected == -3) return; switch (chr) { case SDLK_RETURN: // If only 'Save', do it. if (!buttons[0] && buttons[1]) { buttons[1]->push(); gwin->show(1); buttons[1]->unpush(); gwin->show(1); buttons[1]->activate(); } update_details = true; break; case SDLK_BACKSPACE: if (BackspacePressed()) { // Can't restore/delete now. delete buttons[0]; delete buttons[2]; buttons[0] = buttons[2] = 0; // If no chars cant save either if (!newname[0]) { delete buttons[1]; buttons[1] = 0; } update_details = true; } break; case SDLK_DELETE: if (DeletePressed()) { // Can't restore/delete now. delete buttons[0]; delete buttons[2]; buttons[0] = buttons[2] = 0; // If no chars cant save either if (!newname[0]) { delete buttons[1]; buttons[1] = 0; } update_details = true; } break; case SDLK_LEFT: repaint = MoveCursor(-1); break; case SDLK_RIGHT: repaint = MoveCursor(1); break; case SDLK_HOME: repaint = MoveCursor(-MAX_SAVEGAME_NAME_LEN); break; case SDLK_END: repaint = MoveCursor(MAX_SAVEGAME_NAME_LEN); break; default: if ((unicode & 0xFF80) == 0 ) chr = unicode & 0x7F; else chr = 0; if (chr < ' ') return; // Ignore other special chars. if (chr < 256 && isascii(chr)) { if (AddCharacter (chr)) { // Added first character? Need 'Save' button. if (newname[0] && !buttons[1]) { buttons[1] = new Newfile_Textbutton(this, savetext, btn_cols[0], btn_rows[0], 40); buttons[1]->paint(); } // Remove Load and Delete Button if (buttons[0] || buttons[2]) { delete buttons[0]; delete buttons[2]; buttons[0] = buttons[2] = 0; } update_details = true; } } break; } // This sets the game details to the cur set if (update_details) { screenshot = cur_shot; details = cur_details; party = cur_party; repaint = true; } if (repaint) { paint(); gwin->set_painted(); } } int Newfile_gump::BackspacePressed() { if (cursor == -1 || cursor == 0) return 0; cursor--; return DeletePressed(); } int Newfile_gump::DeletePressed() { if (cursor == -1 || cursor == strlen (newname)) return 0; for (int i = cursor; i < strlen (newname); i++) newname[i] = newname[i+1]; return 1; } int Newfile_gump::MoveCursor(int count) { if (cursor == -1) return 0; cursor += count; if (cursor < 0) cursor = 0; if (cursor > strlen (newname)) cursor = strlen (newname); return 1; } int Newfile_gump::AddCharacter(char c) { if (cursor == -1 || cursor == MAX_SAVEGAME_NAME_LEN-1) return 0; char text[MAX_SAVEGAME_NAME_LEN]; strcpy (text, newname); text[cursor+1] = 0; text[cursor] = c; strcat (text, newname+cursor); //Now check the width of the text if (sman->get_text_width(2, text) >= textw) return 0; cursor++; strcpy (newname, text); return 1; } void Newfile_gump::LoadSaveGameDetails() { int i; // Gamedat Details gwin->get_saveinfo(gd_shot, gd_details, gd_party); // Current screenshot cur_shot = gwin->create_mini_screenshot(); // Current Details cur_details = new SaveGame_Details; memset (cur_details, 0, sizeof(SaveGame_Details)); gwin->get_win()->put(back, 0, 0); if (gd_details) cur_details->save_count = gd_details->save_count; else cur_details->save_count = 0; cur_details->party_size = partyman->get_count()+1; cur_details->game_day = gclock->get_total_hours() / 24;; cur_details->game_hour = gclock->get_hour(); cur_details->game_minute = gclock->get_minute(); time_t t = std::time(0); struct tm *timeinfo = std::localtime (&t); cur_details->real_day = timeinfo->tm_mday; cur_details->real_hour = timeinfo->tm_hour; cur_details->real_minute = timeinfo->tm_min; cur_details->real_month = timeinfo->tm_mon+1; cur_details->real_year = timeinfo->tm_year + 1900; cur_details->real_second = timeinfo->tm_sec; // Current Party cur_party = new SaveGame_Party[cur_details->party_size]; for (i=0; iparty_size ; i++) { Actor *npc; if (i == 0) npc = gwin->get_main_actor(); else npc = (Npc_actor *) gwin->get_npc(partyman->get_member(i-1)); std::string namestr = npc->get_npc_name(); strncpy (cur_party[i].name, namestr.c_str(), 18); cur_party[i].shape = npc->get_shapenum(); cur_party[i].shape_file = npc->get_shapefile(); cur_party[i].dext = npc->get_property(Actor::dexterity); cur_party[i].str = npc->get_property(Actor::strength); cur_party[i].intel = npc->get_property(Actor::intelligence); cur_party[i].health = npc->get_property(Actor::health); cur_party[i].combat = npc->get_property(Actor::combat); cur_party[i].mana = npc->get_property(Actor::mana); cur_party[i].magic = npc->get_property(Actor::magic); cur_party[i].training = npc->get_property(Actor::training); cur_party[i].exp = npc->get_property(Actor::exp); cur_party[i].food = npc->get_property(Actor::food_level); cur_party[i].flags = npc->get_flags(); cur_party[i].flags2 = npc->get_flags2(); } party = cur_party; screenshot = cur_shot; details = cur_details; // Now read save game details char mask[256]; snprintf(mask, 256, SAVENAME2, Game::get_game_type() == BLACK_GATE ? "bg" : "si"); FileList filenames; U7ListFiles (mask, filenames); num_games = filenames.size(); games = new SaveInfo[num_games]; // Setup basic details for (i = 0; iget_saveinfo(games[i].num, games[i].savename, games[i].screenshot, games[i].details, games[i].party); if (first_free == -1 && i != games[i].num) first_free = i; } if (first_free == -1) first_free = num_games; // Now sort it again, with all the details so it can be done by date if (num_games) qsort(games, num_games, sizeof(SaveInfo), SaveInfo::CompareGames); // We'll now output the info if debugging #ifdef DEBUG cout << "Listing " << num_games << " Save games" << endl; for (i = 0; idetails) { if (details->real_year < other->details->real_year) return 1; if (details->real_year > other->details->real_year) return -1; if (details->real_month < other->details->real_month) return 1; if (details->real_month > other->details->real_month) return -1; if (details->real_day < other->details->real_day) return 1; if (details->real_day > other->details->real_day) return -1; if (details->real_hour < other->details->real_hour) return 1; if (details->real_hour > other->details->real_hour) return -1; if (details->real_minute < other->details->real_minute) return 1; if (details->real_minute > other->details->real_minute) return -1; if (details->real_second < other->details->real_second) return 1; if (details->real_second > other->details->real_second) return -1; } else if (details) // If the other doesn't have time we are first { return -1; } else if (other->details) // If we don't have time we are last { return 1; } return num - other->num; } static int _U7SaveSeqNr(const char *a) { int i; for (i = strlen((char*)a) - 1; !isdigit(((char*)a)[i]); i--) ; for (; isdigit(((char*)a)[i]); i--) ; return atoi(&a[i+1]); } // Compare Games Static int Newfile_gump::SaveInfo::CompareGames(const void *a, const void *b) { return ((Newfile_gump::SaveInfo*)a)->CompareThis((Newfile_gump::SaveInfo*)b); } exult-1.2/gumps/misc_buttons.cc0000755000175000001440000001020507644746227012370 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "actors.h" #include "Gamemenu_gump.h" #include "game.h" #include "gamewin.h" #include "misc_buttons.h" #include "Modal_gump.h" #include "mouse.h" #include "party.h" #include "Gump_manager.h" /* * A checkmark for closing its parent: */ Checkmark_button::Checkmark_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/check"), px, py) { } /* * Handle click on a 'checkmark'. */ void Checkmark_button::activate ( ) { parent->close(); } /* * A 'heart' button for bringing up stats. */ Heart_button::Heart_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/heart"), px, py) { } /* * Handle click on a heart. */ void Heart_button::activate ( ) { gumpman->add_gump(parent->get_container(), game->get_shape("gumps/statsdisplay")); } /* * A diskette for bringing up the 'save' box. */ Disk_button::Disk_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/disk"), px, py) { } /* * Handle click on a diskette. */ void Disk_button::activate ( ) { Gamemenu_gump *menu = new Gamemenu_gump(); gumpman->do_modal_gump(menu, Mouse::hand); delete menu; } /* * The combat toggle button. */ Combat_button::Combat_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/combat"), px, py) { pushed = gwin->in_combat(); } /* * Handle click on a combat toggle button. */ void Combat_button::activate ( ) { gwin->toggle_combat(); pushed = gwin->in_combat(); parent->paint(); } /* * Check combat mode before painting. */ void Combat_button::paint ( ) { pushed = gwin->in_combat(); Gump_button::paint(); } /* * The halo button. */ Halo_button::Halo_button(Gump *par, int px, int py, Actor *a) : Gump_button(par, game->get_shape("gumps/halo"), px, py), actor(a) { pushed = actor->is_combat_protected(); } /* * Handle click on a halo toggle button. */ void Halo_button::activate ( ) { // Want to toggle it. bool prot = !actor->is_combat_protected(); pushed = prot; parent->paint(); actor->set_combat_protected(prot); if (!prot) // Toggled off? return; // On? Got to turn off others. Actor *party[9]; // Get entire party, including Avatar. int cnt = gwin->get_party(party, 1); for (int i = 0; i < cnt; i++) { if (party[i] != actor && party[i]->is_combat_protected()) party[i]->set_combat_protected(false); // +++++Should also update gumps. } } /* * Combat mode. Has 10 frames corresponding to Actor::Attack_mode. */ Combat_mode_button::Combat_mode_button(Gump *par, int px, int py, Actor *a) : Gump_button(par, game->get_shape("gumps/combatmode"), px, py), actor(a) { set_frame((int) actor->get_attack_mode()); } /* * Handle click on a combat toggle button. */ void Combat_mode_button::activate ( ) { // Only Avatar gets last frame (manual) int nframes = actor == gwin->get_main_actor() ? 10 : 9; set_frame((get_framenum() + 1)%nframes); // Flag that player set the mode. actor->set_attack_mode((Actor::Attack_mode) get_framenum(), true); paint(); gwin->set_painted(); } /* * The Serpent Isle Combat Stats Button. */ Cstats_button::Cstats_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/combat_stats"), px, py) { } /* * Handle click on a combat stats button */ void Cstats_button::activate ( ) { int cnt = partyman->get_count(); gumpman->add_gump(0, game->get_shape("gumps/cstats/1") + cnt); } exult-1.2/gumps/Slider_gump.cc0000755000175000001440000001431607516212522012120 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "SDL_keyboard.h" #include "game.h" #include "gamewin.h" #include "Gump_button.h" #include "misc_buttons.h" #include "Slider_gump.h" #include "Gump_manager.h" using std::cout; using std::endl; /* * Statics: */ short Slider_gump::leftbtnx = 31; short Slider_gump::rightbtnx = 103; short Slider_gump::btny = 14; short Slider_gump::diamondy = 6; short Slider_gump::xmin = 35; // Min., max. positions of diamond. short Slider_gump::xmax = 93; /* * One of the two arrow button on the slider: */ class Slider_button : public Gump_button { public: Slider_button(Gump *par, int px, int py, int shapenum) : Gump_button(par, shapenum, px, py) { } // What to do when 'clicked': virtual void activate(); }; /* * Handle click on a slider's arrow. */ void Slider_button::activate ( ) { ((Slider_gump *) parent)->clicked_arrow(this); } /* * Set slider value. */ void Slider_gump::set_val ( int newval ) { val = newval; static int xdist = xmax - xmin; if(max_val-min_val==0) { val=0; diamondx=xmin; } else diamondx = xmin + ((val - min_val)*xdist)/(max_val - min_val); } /* * Create a slider. */ Slider_gump::Slider_gump ( int mival, int mxval, // Value range. int step, // Amt. to change by. int defval // Default value. ) : Modal_gump(0, game->get_shape("gumps/slider")), min_val(mival), max_val(mxval), step_val(step), val(defval), dragging(0), prev_dragx(0) { diamond = ShapeID(game->get_shape("gumps/slider_diamond"), 0, SF_GUMPS_VGA); set_object_area(Rectangle(0, 0, 0, 0), 6, 30); #ifdef DEBUG cout << "Slider: " << min_val << " to " << max_val << " by " << step << endl; #endif left_arrow = new Slider_button(this, leftbtnx, btny, game->get_shape("gumps/slider_left")); right_arrow = new Slider_button(this, rightbtnx, btny, game->get_shape("gumps/slider_right")); // Init. to middle value. if (defval < min_val) defval = min_val; else if (defval > max_val) defval = max_val; set_val(defval); } /* * Delete slider. */ Slider_gump::~Slider_gump ( ) { delete left_arrow; delete right_arrow; } /* * An arrow on the slider was clicked. */ void Slider_gump::clicked_arrow ( Slider_button *arrow // What was clicked. ) { if (arrow == left_arrow) move_diamond(-step_val); else if (arrow == right_arrow) move_diamond(step_val); } void Slider_gump::move_diamond(int dir) { int newval = val; newval += dir; if (newval < min_val) newval = min_val; if (newval > max_val) newval = max_val; set_val(newval); paint(); gwin->set_painted(); } /* * Paint on screen. */ void Slider_gump::paint ( ) { const int textx = 128, texty = 7; // Paint the gump itself. paint_shape(x, y); // Paint red "checkmark". check_button->paint(); // Paint buttons. left_arrow->paint(); right_arrow->paint(); // Paint slider diamond. diamond.paint_shape(x + diamondx, y + diamondy); // Print value. gumpman->paint_num(val, x + textx, y + texty); gwin->set_painted(); } /* * Handle mouse-down events. */ void Slider_gump::mouse_down ( int mx, int my // Position in window. ) { dragging = 0; Gump_button *btn = Gump::on_button(mx, my); if (btn) pushed = btn; else if (left_arrow->on_button(mx, my)) pushed = left_arrow; else if (right_arrow->on_button(mx, my)) pushed = right_arrow; else pushed = 0; if (pushed) { pushed->push(); return; } // See if on diamond. Shape_frame *d_shape = diamond.get_shape(); if (d_shape->has_point(mx - (x + diamondx), my - (y + diamondy))) { // Start to drag it. dragging = 1; prev_dragx = mx; } else { if(my-get_y()diamondy+d_shape->get_height()) return; diamondx = mx-get_x(); if(diamondxxmax) diamondx = xmax; static int xdist = xmax - xmin; int delta = (diamondx - xmin)*(max_val - min_val)/xdist; // Round down to nearest step. delta -= delta%step_val; int newval = min_val + delta; if (newval != val) // Set value. val = newval; paint(); } } /* * Handle mouse-up events. */ void Slider_gump::mouse_up ( int mx, int my // Position in window. ) { if (dragging) // Done dragging? { set_val(val); // Set diamond in correct pos. paint(); gwin->set_painted(); dragging = 0; } if (!pushed) return; pushed->unpush(); if (pushed->on_button(mx, my)) pushed->activate(); pushed = 0; } /* * Mouse was dragged with left button down. */ void Slider_gump::mouse_drag ( int mx, int my // Where mouse is. ) { if (!dragging) return; diamondx += mx - prev_dragx; prev_dragx = mx; if (diamondx < xmin) // Stop at ends. diamondx = xmin; else if (diamondx > xmax) diamondx = xmax; static int xdist = xmax - xmin; int delta = (diamondx - xmin)*(max_val - min_val)/xdist; // Round down to nearest step. delta -= delta%step_val; int newval = min_val + delta; if (newval != val) // Set value. val = newval; paint(); } /* * Handle ASCII character typed. */ void Slider_gump::key_down(int chr) { switch(chr) { case SDLK_RETURN: done = 1; break; case SDLK_LEFT: clicked_arrow(left_arrow); break; case SDLK_RIGHT: clicked_arrow(right_arrow); break; } } void Slider_gump::mousewheel_up() { SDLMod mod = SDL_GetModState(); if (mod & KMOD_ALT) move_diamond(-10*step_val); else move_diamond(-step_val); } void Slider_gump::mousewheel_down() { SDLMod mod = SDL_GetModState(); if (mod & KMOD_ALT) move_diamond(10*step_val); else move_diamond(step_val); } exult-1.2/gumps/CombatOptions_gump.h0000644000175000001440000000271607570753704013333 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMBATOPTIONS_GUMP_H #define _COMBATOPTIONS_GUMP_H #include "Modal_gump.h" #include class Gump_button; class CombatOptions_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(CombatOptions_gump,Modal_gump(0,0,0,0)); private: Gump_button* buttons[5]; // Below settings, + ok, cancel. int difficulty; // Setting for the buttons. int show_hits; int mode; public: CombatOptions_gump(); ~CombatOptions_gump(); // Paint it and its contents. virtual void paint(); virtual void close(); // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); void toggle(Gump_button* btn, int state); void build_buttons(); void load_settings(); void save_settings(); void cancel(); }; #endif exult-1.2/gumps/Text_gump.cc0000755000175000001440000000611710054030560011611 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "gamewin.h" #include "Text_gump.h" #ifndef UNDER_CE using std::strchr; using std::strcpy; using std::strlen; #endif /* * Add to the text, starting a newline. */ void Text_gump::add_text ( const char *str ) { int slen = strlen(str); // Length of new text. // Allocate new space. char *newtext = new char[textlen + (textlen != 0) + slen + 1]; if (textlen) // Copy over old. { strcpy(newtext, text); // Add new line if not starting a new page and if first char of new string is // not a new line if (newtext[textlen-1] != '*') newtext[textlen++] = '~'; } strcpy(newtext + textlen, str); // Append new. delete [] text; text = newtext; textlen += slen; } /* * Paint a page and find where its text ends. * * Output: Index past end of displayed page. */ int Text_gump::paint_page ( Rectangle box, // Display box rel. to gump. int start // Starting offset into text. ) { const int font = serpentine?8:4; // Black. const int vlead = 1; // Extra inter-line spacing. int ypos = 0; int textheight = sman->get_text_height(font) + vlead; char *str = text + start; while (*str && *str != '*' && ypos + textheight <= box.h) { if (*str == '~') // Empty paragraph? { ypos += textheight; str++; continue; } // Look for page break. char *epage = strchr(str, '*'); // Look for line break. char *eol = strchr(str, '~'); if (epage && (!eol || eol > epage)) eol = epage; if (!eol) // No end found? eol = text + textlen; char eolchr = *eol; // Save char. at EOL. *eol = 0; int endoff = sman->paint_text_box(font, str, x + box.x, y + box.y + ypos, box.w, box.h - ypos, vlead); *eol = eolchr; // Restore char. if (endoff > 0) // All painted? { // Value returned is height. str = eol + (eolchr == '~'); ypos += endoff; } else // Out of room. { str += -endoff; break; } } if (*str == '*') // Saw end of page? str++; gwin->set_painted(); // Force blit. return (str - text); // Return offset past end. } /* * Show next page(s) of book or scroll. * * Output: 0 if already at end. */ int Text_gump::show_next_page ( ) { if (curend >= textlen) return (0); // That's all, folks. curtop = curend; // Start next page or pair of pages. paint(); // Paint. This updates curend. return (1); } exult-1.2/gumps/Paperdoll_gump_info.cc0000644000175000001440000022111310026506333013617 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "game.h" #include "gamewin.h" #include "Paperdoll_gump.h" #include "actors.h" #include "exult_bg_flx.h" /* * * SERPENT ISLE GUMPS * */ /* * * NPC and Item Info Statics * */ Paperdoll_gump::Paperdoll_npc Paperdoll_gump::Characters[] = { // Shp, fmale, bsh, bf, hds, hf, hh, ash, af, a2, as // Avatar Female White { 1029, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, { 1035, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, { 989, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, // Avatar Female Brown { 1027, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, { 1033, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Avatar Female Black { 1025, true, SF_PAPERDOL_VGA, 13, 2, 4, 4, 5, 131, 0, 2, 4 }, { 1031, true, SF_PAPERDOL_VGA, 13, 2, 4, 4, 5, 131, 0, 2, 4 }, // Avatar Male White { 1028, false, SF_PAPERDOL_VGA, 14, 0, 128, 0, 1, 7, 1, 3, 5 }, { 1034, false, SF_PAPERDOL_VGA, 14, 0, 128, 0, 1, 7, 1, 3, 5 }, { 721, false, SF_PAPERDOL_VGA, 14, 0, 128, 0, 1, 7, 1, 3, 5 }, // Avatar Male Brown { 1026, false, SF_PAPERDOL_VGA, 14, 1, 128, 2, 3, 130, 1, 3, 5 }, { 1032, false, SF_PAPERDOL_VGA, 14, 1, 128, 2, 3, 130, 1, 3, 5 }, // Avatar Male Black { 1024, false, SF_PAPERDOL_VGA, 14, 2, 128, 4, 5, 131, 1, 3, 5 }, { 1030, false, SF_PAPERDOL_VGA, 14, 2, 128, 4, 5, 131, 1, 3, 5 }, // Iolo { 465, false, SF_PAPERDOL_VGA, 14, 0, 125, 0, 1, 7, 1, 3, 5 }, // Shamino { 487, false, SF_PAPERDOL_VGA, 14, 0, 126, 0, 1, 7, 1, 3, 5 }, // Dupre { 488, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Automaton { 747, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Boyden { 815, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Petra { 658, true, SF_PAPERDOL_VGA, 13, 3, 137, 0, 1, 136, 0, 2, 4 }, // Gwenno { 669, true, SF_PAPERDOL_VGA, 13, 0, 127, 0, 1, 7, 0, 2, 4 }, // Sethys { 817, false, SF_PAPERDOL_VGA, 14, 0, 159, 0, 1, 7, 1, 3, 5 }, // Wilfred { 816, false, SF_PAPERDOL_VGA, 14, 0, 154, 0, 1, 7, 1, 3, 5 }, // Selina { 652, true, SF_PAPERDOL_VGA, 13, 0, 155, 0, 1, 7, 0, 2, 4 }, // Mortegro { 809, false, SF_PAPERDOL_VGA, 14, 0, 156, 0, 1, 7, 1, 3, 5 }, // Stefano { 451, false, SF_PAPERDOL_VGA, 14, 0, 157, 0, 1, 130, 1, 3, 5 }, // Terminator { 0 } }; Paperdoll_gump::Paperdoll_item Paperdoll_gump::Items[] = { // wshape, wf, Equip spot, Object Type, Gender, shape, frame, frame2, f3, f4 // MISC ITEMS // Usecode container (not drawn normally) { 486, -1, Actor::ucont_spot, OT_Normal, false, SF_PAPERDOL_VGA, 6, 0 }, // Bed roll { 583, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, 9, 0 }, { 583, -1,Actor::back2h_spot, OT_Normal, false, SF_PAPERDOL_VGA, 9, 1 }, // Kidney Belt { 584, -1, Actor::belt, OT_Normal, true, SF_PAPERDOL_VGA, 54, 0 }, // Serpent Earings { 635, -1, Actor::ears_spot, OT_Normal, true, SF_PAPERDOL_VGA, 39, 0 }, // Backpack { 801, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, 6, 0 }, // Bag { 802, -1, Actor::belt, OT_Normal, false, SF_PAPERDOL_VGA, 89, 0 }, // Belt of Strength { 996, -1, Actor::belt, OT_Normal, true, SF_PAPERDOL_VGA, 166, 0 }, // Spell book { 761, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 15, 0 }, // Lit Torch { 701, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 63, 0 }, { 701, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 63, 1 }, // Torch { 595, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 113, 0 }, { 595, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 113, 1 }, { 595, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 113, 2 }, // Serpent Sceptre { 926, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 144, 0 }, { 926, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 144, 1 }, // Body { 400, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 400, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, { 402, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 402, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, { 414, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 414, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, // AMULETS // Ankh { 955, 0, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 0 }, // Fellowship { 955, 1, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 1 }, // Serpent Neclace { 955, 2, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 2 }, // Amulet of Protection { 955, 3, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 3 }, // Batlin's { 955, 4, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 4 }, // Diamond Necklace { 955, 5, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 5 }, // Necklace { 955, 6, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 6 }, // Necklace of Bones { 955, 7, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 7 }, // White Diamond Necklace { 955, 8, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 8 }, // Amulet of Balance { 955, 9, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 9 }, // CLOAKS // Red { 227, 0, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 28, 0, -1 }, { 227, 0, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 28, 1, -1 }, // Bear { 227, 1, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 8, 0, -1 }, { 227, 1, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 8, 1, -1 }, // Snow Leopard { 227, 2, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 61, 0, -1 }, { 227, 2, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 61, 1, -1 }, // Wolf { 227, 3, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 116, 0, -1 }, { 227, 3, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 116, 1, -1 }, // Gwani { 227, 4, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 164, 0, -1 }, { 227, 4, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 164, 1, -1 }, // 'Cloak' { 403, 0, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 28, 0, -1 }, { 403, 0, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 28, 1, -1 }, // ARMOUR // Breast Plate { 419, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 140, 0, 2, 4, 6 }, // Leather { 569, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 57, 0, 2, 4, 6 }, // Scale { 570, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 92, 0, 2, 4, 6 }, // Chain { 571, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 22, 0, 2, 4, 6 }, // Plate { 573, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 85, 0, 2, 4, 6 }, // Serpent { 638, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 94, 0, 2, 4, 6 }, // Magic { 666, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 2, 0, 2, 4, 6 }, // Antique { 836, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 1, 0, 2, 4, 6 }, // HELMS // Magic { 383, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 74, 0 }, // Helm Of Courage { 383, 1, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 162, 0 }, // Chain Coif { 539, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 24, 0 }, // Great Helm { 541, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 30, 0 }, // Crested Helm { 542, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 31, 0 }, // Plummed Helm { 542, 1, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 88, 0 }, // Viking Helm { 542, 2, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 114, 0 }, // Leather Helm { 1004, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 59, 0 }, // Fur Cap { 1004, 1, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 129, 0 }, // Serpent Crown { 1004, 2, Actor::head, OT_Normal, true, SF_PAPERDOL_VGA, 33, 0 }, // Living Toupe { 1004, 3, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 165, 0 }, // Womans Fur Cap { 1004, 4, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 129, 0 }, // Helm of Light { 1013, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 169, 0 }, // LEGGINGS // Leather { 574, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 60, 0 }, // Chain { 575, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 26, 0 }, // Plate { 576, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 87, 0 }, // Fine Stockings { 677, 0, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 152, 0 }, // Fishnet Stockings { 677, 1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 153, 0 }, // Magic Leggings { 686, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 72, 0 }, // GLOVES // Leather { 579, -1, Actor::hands2_spot, OT_Normal, false, SF_PAPERDOL_VGA, 47, 0, 1, 2 }, // Gauntlets { 580, -1, Actor::hands2_spot, OT_Normal, false, SF_PAPERDOL_VGA, 25, 0, 1, 2 }, // Magic Gauntlets { 835, -1, Actor::hands2_spot, OT_Normal, false, SF_PAPERDOL_VGA, 70, 0, 1, 2 }, // Gauntlets of Quickness { 1001, -1, Actor::hands2_spot, OT_Normal, false, SF_PAPERDOL_VGA, 167, 0, 1, 2 }, // RINGS // Invisibilty Ring { 296, 0, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 120, 0, 2, 4 }, { 296, 0, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 120, 1, 3, 5 }, // Ring of Regeneration { 296, 1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 122, 0, 2, 4 }, { 296, 1, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 122, 1, 3, 5 }, // Blink Ring { 296, 2, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 0, 2, 4 }, { 296, 2, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 1, 3, 5 }, // Ring of Reagents { 296, 3, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 0, 2, 4 }, { 296, 3, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 1, 3, 5 }, // Ring { 887, 0, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 0, 2, 4 }, { 887, 0, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 1, 3, 5 }, // Serpent Ring { 887, 1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 149, 0, 2, 4 }, { 887, 1, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 149, 1, 3, 5 }, // BOOTS // Leather { 587, 0, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 58, 0 }, // Magic { 587, 1, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 73, 0 }, // Armoured { 587, 2, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 86, 0 }, // Fur { 587, 3, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 46, 0 }, // Black { 587, 4, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 150, 0 }, // Slippers { 587, 5, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 151, 0 }, // Swamp { 587, 6, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 106, 0 }, // SHIELDS (behind back = 99) // Dupre's { 490, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 141, 0 }, { 490, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Buckler { 543, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 20, 0 }, { 543, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Curved Heater { 545, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 34, 0 }, { 545, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Wooden { 572, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 117, 0 }, { 572, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Spiked { 578, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 104, 0 }, { 578, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Door { 585, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 38, 0 }, { 585, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Brass { 586, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 19, 0 }, { 586, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Kite { 609, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 37, 0 }, { 609, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Magic { 663, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 75, 0 }, { 663, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Shield of Monitor { 729, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 142, 0 }, { 729, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // WEAPONS 1 H // Magebane { 231, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 67, 0}, { 231, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 67, 1}, // Spear { 592, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 103, 0 }, { 592, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 103, 1 }, // Blowgun { 563, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 12, 0 }, { 563, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 12, 1 }, // Boomerang { 605, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 16, 0 }, { 605, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 16, 1 }, // Club { 590, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 29, 0 }, { 590, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 29, 1 }, // Dagger { 594, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 35, 0 }, { 594, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 35, 1 }, // Poisoned Dagger { 564, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 36, 0 }, { 564, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 36, 1 }, // Fire Sword { 551, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 41, 0 }, { 551, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 41, 1 }, // Fire Wand { 630, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 42, 0 }, { 630, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 42, 1 }, // Glass Sword { 604, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 48, 0 }, { 604, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 48, 1 }, // Hammer { 623, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 50, 0 }, { 623, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 50, 1 }, // Lightning Whip { 549, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 62, 0 }, { 549, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 62, 1 }, // Mace { 659, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 66, 0 }, { 659, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 66, 1 }, // Magic Sword { 547, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 76, 0 }, { 547, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 76, 1 }, // Magic Axe { 552, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 77, 0 }, { 552, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 77, 1 }, // Magician's Wand { 792, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 78, 0 }, { 792, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 78, 1 }, // Morning Star { 596, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 81, 0 }, { 596, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 81, 1 }, // Serpentine Dagger { 636, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 95, 0 }, { 636, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 95, 1 }, // Serpent Sword { 637, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 97, 0 }, { 637, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 97, 1 }, // Ophidian Sword { 710, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 97, 0 }, { 710, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 97, 1 }, // Shears { 698, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 98, 0 }, { 698, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 98, 1 }, // Magic Sling { 474, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 102, 0 }, { 474, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 102, 1 }, // Sword { 599, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 107, 0 }, { 599, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 107, 1 }, // Decorative Sword { 608, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 109, 0 }, { 608, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 109, 1 }, // Sword of Defense { 567, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 110, 0 }, { 567, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 110, 1 }, // Throwing Axe { 593, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 111, 0 }, { 593, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 111, 1 }, // Tongs { 994, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 112, 0 }, { 994, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 112, 1 }, // Whip { 622, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 115, 0 }, { 622, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 115, 1 }, // Lightning Wand { 629, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 118, 0 }, { 629, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 118, 1 }, // Rudyom's Wand { 771, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 134, 0 }, { 771, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 134, 1 }, // Dragon Slayer Sword { 535, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 143, 0 }, { 535, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 143, 1 }, // Wooden Sword { 520, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 161, 0 }, { 520, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 161, 1 }, // Hammer { 508, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 163, 0 }, { 508, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 163, 1 }, // Erinons Axe { 990, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 168, 0 }, { 990, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 168, 1 }, // WEAPONS 2H // The Hammer of Dedication { 942, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 138, 0 }, { 942, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 138, 1 }, // Two Handed Sword { 602, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 108, 0 }, { 602, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 108, 1 }, // Staff { 241, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 105, 0 }, { 241, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 105, 1 }, // Shovel { 625, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 100, 0 }, { 625, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 100, 1 }, // Scythe { 618, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 93, 0 }, { 618, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 93, 1 }, // Rake { 620, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 91, 0 }, { 620, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 91, 1 }, // Pitchfork { 589, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 84, 0 }, { 589, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 84, 1 }, // Pick { 624, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 83, 0 }, { 624, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 83, 1 }, // Juggernaught Hammer { 557, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 53, 0 }, { 557, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 53, 1 }, // Hoe { 626, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 52, 0 }, { 626, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 52, 1 }, // Halberd { 603, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 49, 0 }, { 603, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 49, 1 }, // Fishing Rod { 662, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 44, 0 }, { 662, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 44, 1 }, // Firedoom Staff { 553, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 43, 0 }, { 553, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 43, 1 }, // Two Handed Axe { 601, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 5, 0 }, { 601, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 5, 1 }, // Serpent Staff { 640, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 96, 0 }, { 640, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 96, 1 }, // Two Handed Hammer { 600, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 51, 0 }, { 600, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 51, 1 }, // The Black Sword { 806, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 139, 0 }, { 806, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 139, 1 }, // CROSSBOWS & BOLTS // Magic Bolts { 417, 25, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 2, 2, 0 }, // 2 { 417, 26, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 3, 2, 0 }, // 3 { 417, 27, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 3, 3, 0 }, { 417, 28, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 3, 0 }, { 417, 29, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, 30, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, 31, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, -1, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 2, 1, 0 }, // 1 // Bolts { 723, 25, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 2, 0 }, { 723, 26, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 2, 0 }, { 723, 27, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 3, 0 }, { 723, 28, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 3, 0 }, { 723, 29, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, 30, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, 31, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, -1, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 1, 0 }, // Crossbow { 598, -1, Actor::lhand, OT_Crossbow, false, SF_PAPERDOL_VGA, 32, 0 }, { 598, -1, Actor::belt, OT_Crossbow, false, SF_PAPERDOL_VGA, 32, 1 }, // BOWS & ARROWS // Burst Arrows { 554, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 2, 2, 0 }, { 554, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 3, 2, 0 }, { 554, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 3, 3, 0 }, { 554, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 3, 0 }, { 554, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 2, 1, 0 }, // Magic Arrows { 556, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 2, 2, 0 }, { 556, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 3, 2, 0 }, { 556, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 3, 3, 0 }, { 556, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 3, 0 }, { 556, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 2, 1, 0 }, // Lucky Arrows { 558, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 2, 2, 0 }, { 558, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 3, 2, 0 }, { 558, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 3, 3, 0 }, { 558, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 3, 0 }, { 558, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 2, 1, 0 }, // Sleep Arrows { 568, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 2, 2, 0 }, { 568, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 3, 2, 0 }, { 568, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 3, 3, 0 }, { 568, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 3, 0 }, { 568, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 2, 1, 0 }, // Serpent Arrows { 591, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 2, 2, 0 }, { 591, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 3, 2, 0 }, { 591, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 3, 3, 0 }, { 591, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 3, 0 }, { 591, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 591, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 591, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 591, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 2, 1, 0 }, // Arrows { 722, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 2, 2, 0 }, { 722, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 3, 2, 0 }, { 722, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 3, 3, 0 }, { 722, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 3, 0 }, { 722, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 2, 1, 0 }, // Bow { 597, -1, Actor::lhand, OT_Bow, false, SF_PAPERDOL_VGA, 17, 0 }, { 597, -1,Actor::back2h_spot, OT_Bow, false, SF_PAPERDOL_VGA, 17, 1 }, // Magic Bow { 606, -1, Actor::lhand, OT_Bow, false, SF_PAPERDOL_VGA, 69, 0 }, { 606, -1,Actor::back2h_spot, OT_Bow, false, SF_PAPERDOL_VGA, 69, 1 }, // Infinity Bow { 711, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 160, 0 }, { 711, -1,Actor::back2h_spot, OT_Single, false, SF_PAPERDOL_VGA, 160, 1 }, // Terminator { 0 } }; // // Black Gate // Paperdoll_gump::Paperdoll_npc Paperdoll_gump::Characters_BG[] = { // Shp, fmale, head_file, bsh, bf, hds, hf, hh, ash, af, a2, as // Avatar Female White { 1029, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, { 1035, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, { 989, true, SF_GAME_FLX, 13, 0, EXULT_BG_FLX_FEM_AV_FACE_SHP, 0, 1, 7, 0, 2, 4 }, // Avatar Female Brown { 1027, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, { 1033, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Avatar Female Black { 1025, true, SF_PAPERDOL_VGA, 13, 2, 4, 4, 5, 131, 0, 2, 4 }, { 1031, true, SF_PAPERDOL_VGA, 13, 2, 4, 4, 5, 131, 0, 2, 4 }, // Avatar Male White { 1028, false, SF_PAPERDOL_VGA, 14, 0, 128, 0, 1, 7, 1, 3, 5 }, { 1034, false, SF_PAPERDOL_VGA, 14, 0, 128, 0, 1, 7, 1, 3, 5 }, { 721, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_MALE_AV_FACE_SHP, 0, 1, 7, 1, 3, 5 }, // Avatar Male Brown { 1026, false, SF_PAPERDOL_VGA, 14, 1, 128, 2, 3, 130, 1, 3, 5 }, { 1032, false, SF_PAPERDOL_VGA, 14, 1, 128, 2, 3, 130, 1, 3, 5 }, // Avatar Male Black { 1024, false, SF_PAPERDOL_VGA, 14, 2, 128, 4, 5, 131, 1, 3, 5 }, { 1030, false, SF_PAPERDOL_VGA, 14, 2, 128, 4, 5, 131, 1, 3, 5 }, // Iolo { 465, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_IOLO_FACE_SHP, 0, 1, 7, 1, 3, 5 }, // Shamino { 487, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_SHAMINO_FACE_SHP, 0, 1, 7, 1, 3, 5 }, // Dupre { 488, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_DUPRE_FACE_SHP, 0, 1, 7, 1, 3, 5 }, // Jaana { 490, true, SF_GAME_FLX, 13, 0, EXULT_BG_FLX_FACES_SHP, 0, 1, 7, 0, 2, 4 }, // Sentri { 462, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_FACES2_SHP, 0, 1, 7, 1, 3, 5 }, // Julia { 454, true, SF_GAME_FLX, 13, 0, EXULT_BG_FLX_FACES_SHP, 2, 3, 7, 0, 2, 4 }, // Katrina { 452, true, SF_GAME_FLX, 13, 0, EXULT_BG_FLX_FACES_SHP, 4, 5, 7, 0, 2, 4 }, // Tseramed { 460, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_FACES2_SHP, 2, 3, 7, 1, 3, 5 }, // Spark { 489, false, SF_GAME_FLX, 14, 0, EXULT_BG_FLX_FACES2_SHP, 4, 5, 7, 1, 3, 5 }, // Female Ghost/Rowena { 299, true, SF_GAME_FLX, 13, 0, EXULT_BG_FLX_FEM_AV_FACE_SHP, 2, 1, 7, 0, 2, 4 }, // For Pick pocket mode // Mage { 154, false, SF_PAPERDOL_VGA, 14, 0, 125, 0, 1, 7, 1, 3, 5 }, // Ferry man { 155, false, SF_PAPERDOL_VGA, 14, 0, 156, 0, 1, 7, 1, 3, 5 }, // flying gargoyle { 226, false, SF_PAPERDOL_VGA, 14, 0, 156, 0, 1, 7, 1, 3, 5 }, // Allanger { 227, false, SF_PAPERDOL_VGA, 14, 0, 159, 0, 1, 7, 1, 3, 5 }, // Papa { 228, false, SF_PAPERDOL_VGA, 14, 0, 159, 0, 1, 7, 1, 3, 5 }, // Mama { 229, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, // Paladin { 247, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Fighter { 259, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Townsman { 259, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Blacksmith { 304, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Ghost { 317, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Sage { 318, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Peasant { 319, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Ghost { 337, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Liche { 354, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Kissme { 382, true, SF_PAPERDOL_VGA, 13, 0, 127, 0, 1, 7, 0, 2, 4 }, // Guard { 394, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Pirate { 401, false, SF_PAPERDOL_VGA, 14, 0, 126, 0, 1, 7, 1, 3, 5 }, // Batlin { 403, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Mage { 445, false, SF_PAPERDOL_VGA, 14, 0, 125, 0, 1, 7, 1, 3, 5 }, // Mage { 446, true, SF_PAPERDOL_VGA, 13, 0, 4, 0, 1, 7, 0, 2, 4 }, // Sage { 448, true, SF_PAPERDOL_VGA, 13, 0, 155, 0, 1, 7, 0, 2, 4 }, // Beggar { 449, false, SF_PAPERDOL_VGA, 14, 0, 154, 0, 1, 7, 1, 3, 5 }, // Beggar { 450, false, SF_PAPERDOL_VGA, 14, 0, 154, 0, 1, 7, 1, 3, 5 }, // Noble { 451, false, SF_PAPERDOL_VGA, 14, 0, 157, 0, 1, 130, 1, 3, 5 }, // Shopkeeper { 455, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Noble { 456, true, SF_PAPERDOL_VGA, 13, 0, 155, 0, 1, 7, 0, 2, 4 }, // Gypsy { 457, false, SF_PAPERDOL_VGA, 14, 1, 128, 2, 3, 130, 1, 3, 5 }, // Pirate { 458, false, SF_PAPERDOL_VGA, 14, 0, 126, 0, 1, 7, 1, 3, 5 }, // Wench { 459, true, SF_PAPERDOL_VGA, 13, 0, 127, 0, 1, 7, 0, 2, 4 }, // Ranger { 461, true, SF_PAPERDOL_VGA, 13, 0, 127, 0, 1, 7, 0, 2, 4 }, // Ranger { 463, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Paladin { 464, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Lord British { 466, false, SF_PAPERDOL_VGA, 14, 0, 126, 0, 1, 7, 1, 3, 5 }, // Jester { 467, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Entertainer { 469, true, SF_PAPERDOL_VGA, 13, 0, 127, 0, 1, 7, 0, 2, 4 }, // Jester { 471, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Jester { 472, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Batlin { 482, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Highwayman { 484, false, SF_PAPERDOL_VGA, 14, 0, 158, 0, 1, 7, 1, 3, 5 }, // Hook { 506, false, SF_PAPERDOL_VGA, 14, 0, 159, 0, 1, 7, 1, 3, 5 }, // Liche { 519, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Skeleton { 528, false, SF_PAPERDOL_VGA, 14, 3, 145, 0, 1, 146, 1, 3, 5 }, // Harpie { 532, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Guard { 720, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Stone Harpie { 753, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Guard { 806, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Elizabeth { 881, true, SF_PAPERDOL_VGA, 13, 0, 155, 0, 1, 7, 0, 2, 4 }, // Abraham { 882, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Fellowship Member { 884, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Fellowship Member { 929, true, SF_PAPERDOL_VGA, 13, 1, 4, 2, 3, 130, 0, 2, 4 }, // Guard { 946, false, SF_PAPERDOL_VGA, 14, 0, 124, 0, 1, 7, 1, 3, 5 }, // Ferry man { 952, false, SF_PAPERDOL_VGA, 14, 0, 156, 0, 1, 7, 1, 3, 5 }, // Barkeep { 957, false, SF_PAPERDOL_VGA, 14, 0, 126, 0, 1, 7, 1, 3, 5 }, { 0 } }; Paperdoll_gump::Paperdoll_item Paperdoll_gump::Items_BG[] = { // wshape, wf, Equip spot, Object Type, Gender, file, shape, frame, frame2, f3, f4 // MISC ITEMS // Body { 400, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 400, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, { 402, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 402, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, { 414, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 0 }, { 414, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 135, 1 }, // Bed roll { 583, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, 9, 0 }, { 583, -1,Actor::back2h_spot, OT_Normal, false, SF_PAPERDOL_VGA, 9, 1 }, // Kidney Belt { 584, -1, Actor::belt, OT_Normal, true, SF_PAPERDOL_VGA, 54, 0 }, // Torch { 595, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 113, 0 }, { 595, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 113, 1 }, { 595, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 113, 2 }, // Lit Torch { 701, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 63, 0 }, { 701, -1, Actor::rhand, OT_Single, false, SF_PAPERDOL_VGA, 63, 1 }, // Spell book { 761, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 15, 0 }, // Backpack { 801, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, 6, 0 }, // Bag (Belt) { 802, -1, Actor::belt, OT_Normal, false, SF_PAPERDOL_VGA, 89, 0 }, // Bag (Behind back) **NEEDS ART** { 802, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Barrel (Behind back) **NEEDS ART** { 819, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Sealed Box (Behind back) **NEEDS ART** { 798, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Box (Behind back) **NEEDS ART** { 799, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Locked Chest (Behind back) **NEEDS ART** { 522, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Chest (Behind back) **NEEDS ART** { 800, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Basket (Behind back) **NEEDS ART** { 803, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // Crate (Behind back) **NEEDS ART** { 804, -1, Actor::back, OT_Normal, false, SF_PAPERDOL_VGA, -1, 0 }, // AMULETS and COLLARS // Leather Collar { 582, 0, Actor::neck, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_COLLAR_SHP, 0 }, // Gorget { 586, 0, Actor::neck, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_GORGET_SHP, 0 }, // Magic Gorget { 843, 0, Actor::neck, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_MAGICGORGET_SHP, 0 }, // Ankh { 955, 0, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 5 }, // Fellowship { 955, 1, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 4 }, // White Heart { 955, 2, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 0 }, // Amulet of Protection??? { 955, 3, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 3 }, // Amulet of ??? { 955, 4, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 3 }, // Amulet of ??? { 955, 5, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 9 }, // Amulet of ??? { 955, 6, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 0, 3 }, // Forge Amulet { 955, 7, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 1 }, // Forge Amulet { 955, 8, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 2 }, // Forge Amulet { 955, 9, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 3 }, // Forge Amulet { 955, 10, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_AMULETS_SHP, 4 }, // CLOAKS // Grey Cloak { 285, 0, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_GREYCLOAK_SHP, 0, -1 }, { 285, 0, Actor::cloak_spot, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_GREYCLOAK_SHP, 0, -1 }, { 285, 0, Actor::special_spot, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_GREYCLOAK_SHP, 1, -1 }, // Green Cloak { 285, 1, Actor::neck, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_GREENCLOAK_SHP, 0, -1 }, { 285, 1, Actor::cloak_spot, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_GREENCLOAK_SHP, 0, -1 }, { 285, 1, Actor::special_spot, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_GREENCLOAK_SHP, 1, -1 }, // Cloak { 285, 2, Actor::neck, OT_Normal, false, SF_PAPERDOL_VGA, 8, 0, -1 }, { 285, 2, Actor::cloak_spot, OT_Normal, false, SF_PAPERDOL_VGA, 8, 0, -1 }, { 285, 2, Actor::special_spot, OT_Normal, true, SF_PAPERDOL_VGA, 8, 1, -1 }, // ARMOUR // Green Top { 249, 0, Actor::torso, OT_Shield, true, SF_GAME_FLX, EXULT_BG_FLX_GREENTOP_SHP, 0, 2, 4, 6 }, // Orange Dress { 249, 1, Actor::torso, OT_Shield, true, SF_GAME_FLX, EXULT_BG_FLX_ORANGEDRESS_SHP, 0, 2, 4, 6 }, // Blue Dress { 249, 2, Actor::torso, OT_Shield, true, SF_GAME_FLX, EXULT_BG_FLX_BLUEDRESS_SHP, 0, 2, 4, 6 }, // Leather { 569, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 57, 0, 2, 4, 6 }, // Scale { 570, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 92, 0, 2, 4, 6 }, // Chain { 571, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 22, 0, 2, 4, 6 }, // Plate { 573, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 85, 0, 2, 4, 6 }, // Magic (shape is different) { 666, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 2, 0, 2, 4, 6 }, // Antique (shape is different) { 836, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, 1, 0, 2, 4, 6 }, // Avatar Costume **NEEDS ART** { 838, -1, Actor::torso, OT_Shield, true, SF_PAPERDOL_VGA, -1, 0, 2, 4, 6 }, // HELMS // Magic (shape is different) { 383, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 74, 0 }, // Hood { 444, 0, Actor::head, OT_Helm, true, SF_GAME_FLX, EXULT_BG_FLX_HOODS_SHP, 0 }, // Hood { 444, 1, Actor::head, OT_Helm, true, SF_GAME_FLX, EXULT_BG_FLX_HOODS_SHP, 2 }, // Chain Coif { 539, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 24, 0 }, // Great Helm { 541, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 30, 0 }, // Crested Helm { 542, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 31, 0 }, // Caddellite Helmet { 638, 0, Actor::head, OT_Helm, true, SF_GAME_FLX, EXULT_BG_FLX_CADDELLITE_HELMET_SHP, 0 }, // Leather Helm { 1004, 0, Actor::head, OT_Helm, true, SF_PAPERDOL_VGA, 59, 0 }, // LEGGINGS // Greaves { 353, -1, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_GREAVES_SHP, 0 }, // Leather { 574, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 60, 0 }, // Chain { 575, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 26, 0 }, // Plate { 576, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 87, 0 }, // Magic Leggings { 686, -1, Actor::legs, OT_Normal, true, SF_PAPERDOL_VGA, 72, 0 }, // Pants { 738, 0, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 2 }, // Pants { 738, 1, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 2 }, // Pants { 738, 2, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 4 }, // Pants { 738, 3, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 0 }, // Pants { 738, 4, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 4 }, // Pants { 738, 5, Actor::legs, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_PANTS_SHP, 0 }, // GLOVES // Leather { 579, -1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 47, 0, 1, 2 }, // Gauntlets { 580, -1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 25, 0, 1, 2 }, // Magic Gauntlets { 835, -1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 70, 0, 1, 2 }, // RINGS // Invisibility Ring { 296, 0, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 120, 0, 2, 4 }, { 296, 0, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 120, 1, 3, 5 }, // Ring of Protection { 297, 0, Actor::lfinger, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_RING_OF_PROTECTION_SHP, 0, 2, 4 }, { 297, 0, Actor::rfinger, OT_Normal, false, SF_GAME_FLX, EXULT_BG_FLX_RING_OF_PROTECTION_SHP, 1, 3, 5 }, // Ring of Regeneration { 298, 0, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 122, 0, 2, 4 }, { 298, 0, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 122, 1, 3, 5 }, // Wedding Ring { 295, 0, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 0, 2, 4 }, { 295, 0, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 1, 3, 5 }, // Ring { 640, -1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 0, 2, 4 }, { 640, -1, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 147, 1, 3, 5 }, // Ethereal Ring { 759, -1, Actor::lfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 0, 2, 4 }, { 759, -1, Actor::rfinger, OT_Normal, false, SF_PAPERDOL_VGA, 148, 1, 3, 5 }, // BOOTS // Shoes { 585, 0, Actor::feet, OT_Normal, true, SF_GAME_FLX, EXULT_BG_FLX_SHOES_SHP, 0 }, // Leather { 587, 0, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 58, 0 }, // Magic { 587, 1, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 73, 0 }, // Swamp { 588, 0, Actor::feet, OT_Normal, true, SF_PAPERDOL_VGA, 106, 0 }, // SHIELDS // Buckler { 543, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 20, 0 }, { 543, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Curved Heater { 545, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 34, 0 }, { 545, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Wooden { 572, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 117, 0 }, { 572, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Spiked { 578, -1, Actor::rhand, OT_Shield, false, SF_GAME_FLX, EXULT_BG_FLX_SPIKED_SHIELD_SHP, 0 }, { 578, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Kite { 609, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 37, 0 }, { 609, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // Magic { 663, -1, Actor::rhand, OT_Shield, false, SF_PAPERDOL_VGA, 75, 0 }, { 663, -1, Actor::shield_spot, OT_Shield, false, SF_PAPERDOL_VGA, 99, 0 }, // WEAPONS 1 H // Sling { 474, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 102, 0 }, { 474, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 102, 1 }, // Magic Sword { 547, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 76, 0 }, { 547, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 76, 1 }, // Lightning Whip { 549, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 62, 0 }, { 549, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 62, 1 }, // Magic Boomerang { 550, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_MAGIC_BOOMERANG_SHP, 0 }, { 550, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_MAGIC_BOOMERANG_SHP, 1 }, // Fire Sword { 551, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_FIRESWORD_SHP, 0 }, { 551, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_FIRESWORD_SHP, 1 }, // Magic Axe { 552, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 77, 0 }, { 552, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 77, 1 }, // Hawk { 555, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_HAWK_SHP, 0 }, { 555, -1, Actor::back2h_spot, OT_Single, true, SF_GAME_FLX, EXULT_BG_FLX_HAWK_SHP, 1 }, // Magebane { 559, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 67, 0}, { 559, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 67, 1}, // Great Dagger { 561, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_GREAT_DAGGER_SHP, 0 }, { 561, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_GREAT_DAGGER_SHP, 1 }, // Blowgun { 563, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 12, 0 }, { 563, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 12, 1 }, // Poisoned Dagger { 564, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 36, 0 }, { 564, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 36, 1 }, // Star Bursts **NEEDS ART** { 565, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, -1, 0 }, { 565, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_STARBURST_SHP, 1 }, // Sword of Defense { 567, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 110, 0 }, { 567, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 110, 1 }, // Club { 590, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 29, 0 }, { 590, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 29, 1 }, // Main Gauche **NEEDS ART** { 591, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 107, 0 }, { 591, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 107, 1 }, // Spear { 592, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 103, 0 }, { 592, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 103, 1 }, // Throwing Axe { 593, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 111, 0 }, { 593, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 111, 1 }, // Dagger { 594, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 35, 0 }, { 594, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 35, 1 }, // Morning Star { 596, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 81, 0 }, { 596, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 81, 1 }, // Sword { 599, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 107, 0 }, { 599, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 107, 1 }, // Glass Sword { 604, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 48, 0 }, { 604, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 48, 1 }, // Boomerang { 605, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 16, 0 }, { 605, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 16, 1 }, // Decorative Sword { 608, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 109, 0 }, { 608, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 109, 1 }, // Cleaver { 614, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_CLEAVER_SHP, 0 }, { 614, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_CLEAVER_SHP, 1 }, // Knives { 615, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_KNIFE_SHP, 0 }, { 615, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_KNIFE_SHP, 1 }, // Whip { 622, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 115, 0 }, { 622, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 115, 1 }, // Hammer { 623, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 50, 0 }, { 623, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 50, 1 }, // Lightning Wand { 629, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 118, 0 }, { 629, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 118, 1 }, // Fire Wand { 630, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_FIREWAND_SHP, 0 }, { 630, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_FIREWAND_SHP, 1 }, // Custom sword { 635, -1, Actor::lhand, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_CUSTOM_SWORD_SHP, 0 }, { 635, -1, Actor::belt, OT_Single, false, SF_GAME_FLX, EXULT_BG_FLX_CUSTOM_SWORD_SHP, 1 }, // Serpentine Dagger { 636, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 95, 0 }, { 636, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 95, 1 }, // Serpentine Sword { 637, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 97, 0 }, { 637, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 97, 1 }, // Mace { 659, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 66, 0 }, { 659, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 66, 1 }, // Shears { 698, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 98, 0 }, { 698, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 98, 1 }, // Rudyom's Wand { 771, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 134, 0 }, { 771, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 134, 1 }, // Magician's Wand { 792, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 78, 0 }, { 792, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 78, 1 }, // Tongs { 994, -1, Actor::lhand, OT_Single, false, SF_PAPERDOL_VGA, 112, 0 }, { 994, -1, Actor::belt, OT_Single, false, SF_PAPERDOL_VGA, 112, 1 }, // WEAPONS 2H // Hoe of Destruction { 548, -1, Actor::lhand, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_HOE_OF_DESTRUCTION_SHP, 0 }, { 548, -1,Actor::back2h_spot, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_HOE_OF_DESTRUCTION_SHP, 1 }, // Firedoom Staff { 553, -1, Actor::lhand, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_BGFIREDOOM_SHP, 0 }, { 553, -1,Actor::back2h_spot, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_BGFIREDOOM_SHP, 1 }, // Juggernaught Hammer { 557, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 53, 0 }, { 557, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 53, 1 }, // Death Scythe { 562, -1, Actor::lhand, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_DEATH_SCYTHE_SHP, 0 }, { 562, -1,Actor::back2h_spot, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_DEATH_SCYTHE_SHP, 1 }, // Pitchfork { 589, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 84, 0 }, { 589, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 84, 1 }, // Two Handed Hammer { 600, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 51, 0 }, { 600, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 51, 1 }, // Two Handed Axe { 601, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 5, 0 }, { 601, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 5, 1 }, // Two Handed Sword { 602, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 108, 0 }, { 602, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 108, 1 }, // Halberd { 603, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 49, 0 }, { 603, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 49, 1 }, // Scythe { 618, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 93, 0 }, { 618, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 93, 1 }, // Rake { 620, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 91, 0 }, { 620, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 91, 1 }, // Pick { 624, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 83, 0 }, { 624, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 83, 1 }, // Shovel { 625, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 100, 0 }, { 625, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 100, 1 }, // Hoe { 626, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 52, 0 }, { 626, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 52, 1 }, // Fishing Rod { 662, -1, Actor::lhand, OT_Staff, false, SF_PAPERDOL_VGA, 44, 0 }, { 662, -1,Actor::back2h_spot, OT_Staff, false, SF_PAPERDOL_VGA, 44, 1 }, // The Black Sword { 707, -1, Actor::lhand, OT_Double, false, SF_PAPERDOL_VGA, 139, 0 }, { 707, -1,Actor::back2h_spot, OT_Double, false, SF_PAPERDOL_VGA, 139, 1 }, // Fallowship Staff { 885, -1, Actor::lhand, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_FELLOWSHIPSTAFF_SHP, 0 }, { 885, -1,Actor::back2h_spot, OT_Staff, false, SF_GAME_FLX, EXULT_BG_FLX_FELLOWSHIPSTAFF_SHP, 1 }, // CROSSBOWS & BOLTS // Magic Bolts { 417, 25, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 2, 2, 0 }, // 2 { 417, 26, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 3, 2, 0 }, // 3 { 417, 27, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 3, 3, 0 }, { 417, 28, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 3, 0 }, { 417, 29, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, 30, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, 31, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 4, 4, 0 }, { 417, -1, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 133, 2, 1, 0 }, // 1 // Crossbow { 598, -1, Actor::lhand, OT_Crossbow, false, SF_PAPERDOL_VGA, 32, 0 }, { 598, -1, Actor::belt, OT_Crossbow, false, SF_PAPERDOL_VGA, 32, 1 }, // Triple Crossbow { 647, -1, Actor::lhand, OT_Crossbow, false, SF_GAME_FLX, EXULT_BG_FLX_TRIPLE_XBOW_SHP, 0 }, { 647, -1, Actor::belt, OT_Crossbow, false, SF_GAME_FLX, EXULT_BG_FLX_TRIPLE_XBOW_SHP, 1 }, // Bolts { 723, 25, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 2, 0 }, { 723, 26, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 2, 0 }, { 723, 27, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 3, 0 }, { 723, 28, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 3, 0 }, { 723, 29, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, 30, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, 31, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 723, -1, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 1, 0 }, // Triple Crossbow Bolts { 948, 25, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 2, 0 }, { 948, 26, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 2, 0 }, { 948, 27, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 3, 3, 0 }, { 948, 28, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 3, 0 }, { 948, 29, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 948, 30, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 948, 31, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 4, 4, 0 }, { 948, -1, Actor::ammo, OT_Crossbow, false, SF_PAPERDOL_VGA, 132, 2, 1, 0 }, // BOWS & ARROWS // Burst Arrows { 554, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 2, 2, 0 }, { 554, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 3, 2, 0 }, { 554, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 3, 3, 0 }, { 554, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 3, 0 }, { 554, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 4, 4, 0 }, { 554, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 21, 2, 1, 0 }, // Magic Arrows { 556, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 2, 2, 0 }, { 556, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 3, 2, 0 }, { 556, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 3, 3, 0 }, { 556, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 3, 0 }, { 556, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 4, 4, 0 }, { 556, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 68, 2, 1, 0 }, // Lucky Arrows { 558, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 2, 2, 0 }, { 558, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 3, 2, 0 }, { 558, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 3, 3, 0 }, { 558, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 3, 0 }, { 558, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 4, 4, 0 }, { 558, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 65, 2, 1, 0 }, // Love Arrows **NEEDS ART** ??? Is Currently Serpent Arrows { 560, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 2, 2, 0 }, { 560, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 3, 2, 0 }, { 560, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 3, 3, 0 }, { 560, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 3, 0 }, { 560, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 560, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 560, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 4, 4, 0 }, { 560, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 64, 2, 1, 0 }, // Sleep (Tseramed) Arrows { 568, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 2, 2, 0 }, { 568, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 3, 2, 0 }, { 568, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 3, 3, 0 }, { 568, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 3, 0 }, { 568, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 4, 4, 0 }, { 568, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 101, 2, 1, 0 }, // Bow { 597, -1, Actor::lhand, OT_Bow, false, SF_PAPERDOL_VGA, 17, 0 }, { 597, -1,Actor::back2h_spot, OT_Bow, false, SF_PAPERDOL_VGA, 17, 1 }, // Magic Bow { 606, -1, Actor::lhand, OT_Bow, false, SF_PAPERDOL_VGA, 69, 0 }, { 606, -1,Actor::back2h_spot, OT_Bow, false, SF_PAPERDOL_VGA, 69, 1 }, // Arrows { 722, 25, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 2, 2, 0 }, { 722, 26, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 3, 2, 0 }, { 722, 27, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 3, 3, 0 }, { 722, 28, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 3, 0 }, { 722, 29, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, 30, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, 31, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 4, 4, 0 }, { 722, -1, Actor::ammo, OT_Bow, false, SF_PAPERDOL_VGA, 3, 2, 1, 0 }, // Musket { 278, -1, Actor::lhand, OT_Musket, false, SF_GAME_FLX, EXULT_BG_FLX_MUSKET_SHP, 0 }, { 278, -1,Actor::back2h_spot, OT_Musket, false, SF_GAME_FLX, EXULT_BG_FLX_MUSKET_SHP, 1 }, // Ammunition { 581, -1, Actor::ammo, OT_Musket, false, SF_GAME_FLX, EXULT_BG_FLX_MUSKET_AMMO_SHP, 0, 1, 1 }, // Terminator { 0 } }; Paperdoll_gump::Paperdoll_npc *Paperdoll_gump::GetCharacterInfo(int shape) { int i=0; Paperdoll_npc *ch; if (Game::get_game_type() == BLACK_GATE) ch = Characters_BG; else ch = Characters; while (ch[i].npc_shape) { if (ch[i].npc_shape == shape) return ch+i; i++; } return NULL; } Paperdoll_gump::Paperdoll_npc *Paperdoll_gump::GetCharacterInfoSafe(int shape) { Paperdoll_npc *ch = GetCharacterInfo(shape); if (ch) return ch; else if (Game::get_game_type() == BLACK_GATE) return Characters_BG; return Characters; } Paperdoll_gump::Paperdoll_item *Paperdoll_gump::GetItemInfo(int shape, int frame, int spot) { int i=0; Paperdoll_item *it; if (Game::get_game_type() == BLACK_GATE) it = Items_BG; else it = Items; while (it[i].world_shape) { if (it[i].world_shape == shape && (frame == -1 || it[i].world_frame == -1 || it[i].world_frame == frame) && (spot == -1 || it[i].spot == spot) ) return it+i; i++; } return NULL; } exult-1.2/gumps/Sign_gump.cc0000755000175000001440000000732207506715220011577 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Sign_gump.h" #include "gamewin.h" #include "game.h" #include "actors.h" /* * Create a sign gump. */ Sign_gump::Sign_gump ( int shapenum, int nlines // # of text lines. ) : Gump(0, shapenum), num_lines(nlines), serpentine(false) { // THIS IS A HACK, but don't ask me why this is like this, if (Game::get_game_type() == SERPENT_ISLE && shapenum==49) { // check for avatar read here Main_actor *avatar = gwin->get_main_actor(); if (!avatar->get_flag(Obj_flags::read)) serpentine = true; shapenum = game->get_shape("gumps/goldsign"); set_shape(shapenum); set_pos(); // Recenter } if(shapenum==game->get_shape("gumps/woodsign")) { set_object_area(Rectangle(0, 4, 196, 92)); } else if(shapenum==game->get_shape("gumps/tombstone")) { set_object_area(Rectangle(0, 8, 200, 112)); } else if(shapenum==game->get_shape("gumps/goldsign")) { if (Game::get_game_type() == BLACK_GATE) set_object_area(Rectangle(0, 4, 232, 96)); else // SI set_object_area(Rectangle(4, 4, 312, 96)); } else if (shapenum==game->get_shape("gumps/scroll")) set_object_area(Rectangle(48, 30, 146, 118)); lines = new std::string[num_lines]; } /* * Delete sign. */ Sign_gump::~Sign_gump ( ) { delete [] lines; } /* * Add a line of text. */ void Sign_gump::add_text ( int line, const std::string &txt ) { if (line < 0 || line >= num_lines) return; // check for avatar read here Main_actor *avatar = gwin->get_main_actor(); if (!serpentine && avatar->get_flag(Obj_flags::read)) { for (int i = 0; i < txt.size(); i++) { if (txt[i] == 40) { lines[line] += 'T'; lines[line] += 'H'; } else if (txt[i] == 41) { lines[line] += 'E'; lines[line] += 'E'; } else if (txt[i] == 42) { lines[line] += 'N'; lines[line] += 'G'; } else if (txt[i] == 43) { lines[line] += 'E'; lines[line] += 'A'; } else if (txt[i] == 44) { lines[line] += 'S'; lines[line] += 'T'; } else if (txt[i] == '|') { lines[line] += ' '; } else if (txt[i] >= 'a') lines[line] += txt[i] - 32; else lines[line] += txt[i]; } } else { lines[line] = txt; } } /* * Paint sign. */ void Sign_gump::paint ( ) { int font = 1; // Normal runes. if (get_shapenum() == game->get_shape("gumps/goldsign")) { if (serpentine) font = 10; else font = 6; // Embossed. } else if (serpentine) font = 8; // Get height of 1 line. int lheight = sman->get_text_height(font); // Get space between lines. int lspace = (object_area.h - num_lines*lheight)/(num_lines + 1); // Paint the gump itself. paint_shape(x, y); int ypos = y + object_area.y; // Where to paint next line. for (int i = 0; i < num_lines; i++) { ypos += lspace; if (lines[i].empty()) continue; sman->paint_text(font, lines[i].c_str(), x + object_area.x + (object_area.w - sman->get_text_width(font, lines[i].c_str()))/2, ypos); ypos += lheight; } gwin->set_painted(); } exult-1.2/gumps/Gump_button.cc0000755000175000001440000000265307506445352012162 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gamewin.h" #include "Gump_button.h" #include "Gump.h" /* * Redisplay as 'pushed'. */ void Gump_button::push ( ) { pushed = 1; paint(); gwin->set_painted(); } /* * Redisplay as 'unpushed'. */ void Gump_button::unpush ( ) { pushed = 0; paint(); gwin->set_painted(); } /* * Default method for double-click. */ void Gump_button::double_clicked ( int x, int y ) { } /* * Repaint checkmark, etc. */ void Gump_button::paint ( ) { int px = 0; int py = 0; if (parent) { px = parent->get_x(); py = parent->get_y(); } int prev_frame = get_framenum(); set_frame(prev_frame + pushed); paint_shape(x+px, y+py); set_frame(prev_frame); } exult-1.2/gumps/Newfile_gump.h0000644000175000001440000001356307515634171012140 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NEWFILE_GUMP_H #define NEWFILE_GUMP_H #include "Modal_gump.h" class Shape_file; class Image_buffer; #define MAX_SAVEGAME_NAME_LEN 0x50 struct SaveGame_Details { // Time that the game was saved (needed????) char real_minute; // 1 char real_hour; // 2 char real_day; // 3 char real_month; // 4 short real_year; // 6 // The Game Time that the save was done at char game_minute; // 7 char game_hour; // 8 short game_day; // 10 short save_count; // 12 char party_size; // 13 char unused; // 14 Quite literally unused char real_second; // 15 //Incase we want to add more later char reserved0; // 16 char reserved1[48]; // 64 }; struct SaveGame_Party { char name[18]; // 18 short shape; // 20 unsigned int exp; // 24 unsigned int flags; // 28 unsigned int flags2; // 32 unsigned char food; // 33 unsigned char str; // 34 unsigned char combat; // 35 unsigned char dext; // 36 unsigned char intel; // 37 unsigned char magic; // 38 unsigned char mana; // 39 unsigned char training; // 40 short health; // 42 short shape_file; // 44 //Incase we want to add more later int reserved1; // 48 int reserved2; // 52 int reserved3; // 56 int reserved4; // 60 int reserved5; // 64 }; /* * The file save/load box: */ class Newfile_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(Newfile_gump,Modal_gump(0,0,0,0)); public: struct SaveInfo { int num; char *filename; char *savename; bool readable; SaveGame_Details *details; SaveGame_Party *party; Shape_file *screenshot; static int CompareGames(const void *a, const void *b); int CompareThis(const SaveInfo *other) const; void SetSeqNumber(); SaveInfo(); ~SaveInfo(); }; protected: Gump_button *buttons[8]; // 2 sets of 4 buttons static const short btn_cols[5]; // x-coord of each button. static const short btn_rows[5]; // y-coord of each button. // Text field info static const short fieldx; // Start Y of each field static const short fieldy; // Start X of first static const short fieldw; // Width of each field static const short fieldh; // Height of each field static const short fieldgap; // Gap between fields static const short fieldcount; // Number of fields static const short textx; // X Offset in field static const short texty; // Y Offset in field static const short textw; // Maximum allowable width of text static const short iconx; // X Offset in field static const short icony; // Y Offset in field // Scrollbar and Slider Info static const short scrollx; // X Offset static const short scrolly; // Y Offset static const short scrollh; // Height of Scroll Bar static const short sliderw; // Width of Slider static const short sliderh; // Height of Slider // Side Text static const short infox; // X Offset for info static const short infoy; // Y Offset for info static const short infow; // Width of info box static const short infoh; // Height of info box static const char infostring[]; // Text format for info static const char *months[12]; // Names of the months unsigned char restored; // Set to 1 if we restored a game. Image_buffer *back; SaveInfo *games; // The list of savegames int num_games; // Number of save games int first_free; // The number of the first free savegame Shape_file *cur_shot; // Screenshot for current game SaveGame_Details *cur_details; // Details of current game SaveGame_Party *cur_party; // Party of current game // Gamedat is being used as a 'quicksave' Shape_file *gd_shot; // Screenshot in Gamedat SaveGame_Details *gd_details; // Details in Gamedat SaveGame_Party *gd_party; // Parts in Gamedat Shape_file *screenshot; // The picture to be drawn SaveGame_Details *details; // The game details to show SaveGame_Party *party; // The party to show bool is_readable; // Is the save game readable const char *filename; // Filename of the savegame, if exists int list_position; // The position in the savegame list (top game) int selected; // The savegame that has been selected (num in list) int cursor; // The position of the cursor int slide_start; // Pixel (v) where a slide started char newname[MAX_SAVEGAME_NAME_LEN]; // The new name for the game int BackspacePressed(); int DeletePressed(); int MoveCursor(int count); int AddCharacter(char c); void LoadSaveGameDetails(); // Loads (and sorts) all the savegame details void FreeSaveGameDetails(); // Frees all the savegame details void PaintSaveName (int line); public: Newfile_gump(); ~Newfile_gump(); void load(); // 'Load' was clicked. void save(); // 'Save' was clicked. void delete_file(); // 'Delete' was clicked. void scroll_line(int dir); // Scroll Line Button Pressed void scroll_page(int dir); // Scroll Page Button Pressed. int restored_game() // 1 if user restored. { return restored; } // Paint it and its contents. virtual void paint(); virtual void close() { done = 1; } // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); virtual void mouse_drag(int mx, int my); virtual void text_input(int chr, int unicode); // Character typed. virtual void mousewheel_up(); virtual void mousewheel_down(); }; #endif //NEWFILE_GUMP_H exult-1.2/gumps/Gump_manager.h0000644000175000001440000000573107724430451012114 /* * Gump_manager.h - Object that manages all available gumps * * Copyright (C) 2001-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GUMP_MANAGER_INCLUDED #define GUMP_MANAGER_INCLUDED #include "singles.h" #include "mouse.h" #include "SDL_events.h" class Gump; class Game_object; class Game_window; class Modal_gump; class Paintable; class Gump_manager : public Game_singletons { struct Gump_list { Gump *gump; Gump_list *next; Gump_list() : gump(0), next(0) { } Gump_list(Gump *g) : gump(g), next(0) { } }; Gump_list *open_gumps; int non_persistent_count; // So we can test for 'gump mode' quickly. int modal_gump_count; bool right_click_close; bool dont_pause_game; // NEVER EVER SET THIS MANUALLY! YOU MUST CALL set_gumps_dont_pause_game public: void add_gump(Gump *gump); // Add a single gump to screen void add_gump(Game_object *obj, int shapenum); // Show a gump for object obj bool remove_gump(Gump *gump); // Detatch a gump from the list bool close_gump(Gump *gump); // Close a gump void close_all_gumps(bool pers = false); // Close all gumps bool showing_gumps(bool no_pers = false) const; // Are gumps showing? bool gump_mode() const // Fast check. { return non_persistent_count > 0; } bool modal_gump_mode() const // displaying a modal gump? { return modal_gump_count > 0; } Gump *find_gump(int x, int y, bool pers = true); // Find gump x,y is in Gump *find_gump(Game_object *obj); // Find gump that object is in Gump *find_gump(Game_object *obj, int shapenum); // Find gump for object obj void update_gumps(); void paint(); bool double_clicked(int x, int y, Game_object *&obj); inline bool can_right_click_close() { return right_click_close; } inline void set_right_click_close(bool r) { right_click_close = r; } inline bool gumps_dont_pause_game() { return dont_pause_game; } void set_gumps_dont_pause_game(bool p); int okay_to_quit(); int prompt_for_number(int minval, int maxval, int step, int def, Paintable *paint = 0); int do_modal_gump(Modal_gump *, Mouse::Mouse_shapes, Paintable *paint = 0); void paint_num(int num, int x, int y); Gump_manager(); ~Gump_manager() { close_all_gumps(true); } private: int handle_modal_gump_event(Modal_gump *gump, SDL_Event& event); }; #endif // GUMP_MANAGER_INCLUDED exult-1.2/gumps/Enabled_button.h0000644000175000001440000000241407506445352012436 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ENABLED_BUTTON_H #define ENABLED_BUTTON_H #include "Text_button.h" #include class Enabled_button : public Text_button { public: Enabled_button(Gump *par, int selectionnum, int px, int py, int width, int height = 0) : Text_button(par, "", px, py, width, height) { set_frame(selectionnum); text = selections[selectionnum]; init(); } virtual ~Enabled_button() { } virtual void activate(); int getselection() const { return get_framenum(); } virtual void toggle(int state) = 0; protected: static const char *selections[]; }; #endif exult-1.2/gumps/CombatStats_gump.cc0000644000175000001440000000572707673267332013142 /* Copyright (C) 2001-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "actors.h" #include "game.h" #include "gamewin.h" #include "misc_buttons.h" #include "CombatStats_gump.h" #include "Paperdoll_gump.h" #include "Gump_manager.h" /* * Statics: */ static const int colx = 110; static const int coldx = 29; static const int rowy[7] = {15, 29, 42, 73, 87, 93, 106}; /* * Create stats display. */ CombatStats_gump::CombatStats_gump(int initx, int inity) : Gump(0, initx, inity, game->get_shape("gumps/cstats/1")) { set_object_area(Rectangle(0,0,0,0), 7, 95); party_size = gwin->get_party(party, 1); Gump::shapenum = game->get_shape("gumps/cstats/1") + party_size - 1; ShapeID::set_shape(Gump::shapenum, 0); int i; // Blame MSVC for (i = 0; i < party_size; i++) { halo_btn[i] = new Halo_button(this, colx + i*coldx, rowy[4], party[i]); cmb_btn[i] = new Combat_mode_button(this, colx + i*coldx + 1, rowy[3], party[i]); face_btn[i] = new Face_button(this, colx + i*coldx - 13, rowy[0], party[i]); } for (i = party_size; i < 9; i++) { halo_btn[i] = 0; cmb_btn[i] = 0; face_btn[i] = 0; } } CombatStats_gump::~CombatStats_gump() { for (int i = 0; i < 9; i++) { delete halo_btn[i]; delete cmb_btn[i]; delete face_btn[i]; } } /* * Paint on screen. */ void CombatStats_gump::paint() { Gump_manager* gman = gumpman; Gump::paint(); // stats for all party members for (int i = 0; i < party_size; i++) { face_btn[i]->paint(); gman->paint_num(party[i]->get_effective_prop(Actor::combat), x + colx + i*coldx, y + rowy[1]); gman->paint_num(party[i]->get_property(Actor::health), x + colx + i*coldx, y + rowy[2]); halo_btn[i]->paint(); cmb_btn[i]->paint(); } // magic stats only for Avatar gman->paint_num(party[0]->get_property(Actor::magic), x + colx, y + rowy[5]); gman->paint_num(party[0]->get_property(Actor::mana), x + colx, y + rowy[6]); } Gump_button* CombatStats_gump::on_button(int mx, int my) { Gump_button *btn = Gump::on_button(mx, my); if (btn) return btn; for (int i = 0; i < party_size; i++) { if (halo_btn[i]->on_button(mx, my)) return halo_btn[i]; if (cmb_btn[i]->on_button(mx, my)) return cmb_btn[i]; if (face_btn[i]->on_button(mx, my)) return face_btn[i]; } return 0; } exult-1.2/gumps/Yesno_gump.h0000755000175000001440000000325407516212522011634 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _YESNO_GUMP_H_ #define _YESNO_GUMP_H_ #include #include "Modal_gump.h" class Yesno_button; /* * A yes/no box. */ class Yesno_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(Yesno_gump,Modal_gump(0,0,0,0)); protected: static short yesx, yesnoy, nox; // Coords. of the buttons. const std::string text; // Text of question. It is drawn in // object_area. int answer; // 1 for yes, 0 for no. Yesno_button *yes_button, *no_button; void set_answer(int y) // Done from 'yes'/'no' button. { answer = (y != 0); done = 1; } public: friend class Yesno_button; Yesno_gump(const std::string &txt); ~Yesno_gump(); int get_answer() { return answer; } // Paint it and its contents. virtual void paint(); // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); virtual void key_down(int chr); // Character typed. static int ask(const char *txt); // Ask question, get answer. }; #endif exult-1.2/gumps/gump_types.h0000644000175000001440000000140707331266364011706 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_TYPES_H_ #define _GUMP_TYPES_H_ #endif exult-1.2/gumps/Gump_ToggleButton.cc0000644000175000001440000000235107506445352013254 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Gump_ToggleButton.h" #include "gamewin.h" #include "Gump.h" void Gump_ToggleButton::activate() { set_frame(get_framenum() + 2); if (get_framenum() >= 2*numselections) set_frame(0); toggle(get_framenum()/2); paint(); gwin->set_painted(); } void Gump_ToggleTextButton::activate() { set_frame(get_framenum() + 1); if (get_framenum() >= numselections) set_frame(0); text = selections[get_framenum()]; init(); toggle(get_framenum()); paint(); gwin->set_painted(); } exult-1.2/gumps/Stats_gump.cc0000755000175000001440000001017007673267332012003 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "actors.h" #include "game.h" #include "gamewin.h" #include "misc_buttons.h" #include "Stats_gump.h" #include "Gump_manager.h" /* * Some gump shape numbers: */ const int ASLEEP = 0, POISONED = 1, CHARMED = 2, HUNGRY = 3, PROTECTED = 4, CURSED = 5, PARALYZED = 6; /* * Statics: */ short Stats_gump::textx = 123; short Stats_gump::texty[10] = {17, 26, 35, 46, 55, 67, 76, 86, 95, 104}; /* * Show one of the atts. * * Output: Amount to increment x-pos for the next one. */ static int Show_atts ( int x, int y, // Pos. on screen. int framenum ) { Shape_manager *sman = Shape_manager::get_instance(); ShapeID sid(game->get_shape("gumps/statatts"), framenum, SF_GUMPS_VGA); Shape_frame *s = sid.get_shape(); sman->paint_shape(x + s->get_xleft(), y + s->get_ybelow(), s, 1); return s->get_width() + 2; } /* * Create stats display. */ Stats_gump::Stats_gump ( Container_game_object *cont, int initx, int inity ) : Gump(cont, initx, inity, game->get_shape("gumps/statsdisplay")) { set_object_area(Rectangle(0,0,0,0), 6, 136); } /* * Paint on screen. */ void Stats_gump::paint ( ) { Gump_manager* gman = gumpman; // Area to print name in. const int namex = 30, namey = 6, namew = 95; Actor *act = get_actor(); // Check for freezing (SI). if (gwin->get_main_actor()->get_flag(Obj_flags::freeze)) { int temp = act->get_temperature(); int framenum = temp/10; // Want it 1-5. if (framenum <= 0) framenum = 1; else if (framenum > 5) framenum = 5; set_frame(framenum); } // Paint the gump itself. paint_shape(x, y); // Paint red "checkmark". check_button->paint(); // Show statistics. std::string nm = act->get_name(); sman->paint_text(2, nm.c_str(), x + namex + (namew - sman->get_text_width(2, nm.c_str()))/2, y + namey); gman->paint_num(act->get_effective_prop(Actor::strength), x + textx, y + texty[0]); gman->paint_num(act->get_effective_prop(Actor::dexterity), x + textx, y + texty[1]); gman->paint_num(act->get_effective_prop(Actor::intelligence), x + textx, y + texty[2]); gman->paint_num(act->get_effective_prop(Actor::combat), x + textx, y + texty[3]); gman->paint_num(act->get_property(Actor::magic), x + textx, y + texty[4]); gman->paint_num(act->get_property(Actor::health), x + textx, y + texty[5]); gman->paint_num(act->get_property(Actor::mana), x + textx, y + texty[6]); gman->paint_num(act->get_property(Actor::exp), x + textx, y + texty[7]); gman->paint_num(act->get_level(), x + textx, y + texty[8]); gman->paint_num(act->get_property(Actor::training), x + textx, y + texty[9]); // Now show atts. at bottom. const int attsy = 130, attsx0 = 29; int attsx = attsx0; if (act->get_flag(Obj_flags::asleep)) attsx += Show_atts(x + attsx, y + attsy, ASLEEP); if (act->get_flag(Obj_flags::poisoned)) attsx += Show_atts(x + attsx, y + attsy, POISONED); if (act->get_flag(Obj_flags::charmed)) attsx += Show_atts(x + attsx, y + attsy, CHARMED); if (act->get_property((int) Actor::food_level) <= 4) attsx += Show_atts(x + attsx, y + attsy, HUNGRY); if (act->get_flag(Obj_flags::protection)) attsx += Show_atts(x + attsx, y + attsy, PROTECTED); if (act->get_flag(Obj_flags::cursed)) attsx += Show_atts(x + attsx, y + attsy, CURSED); if (act->get_flag(Obj_flags::paralyzed)) attsx += Show_atts(x + attsx, y + attsy, PARALYZED); } exult-1.2/gumps/Makefile.am0000755000175000001440000000277607570753704011416 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ -I$(srcdir)/../shapes -I$(srcdir)/../objs -I$(srcdir)/../audio\ -I$(srcdir)/../conf -I$(srcdir)/../usecode -I$(srcdir)/../data\ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libgumps.la libgumps_la_SOURCES = \ Actor_gump.cc \ Actor_gump.h \ Book_gump.cc \ Book_gump.h \ File_gump.cc \ File_gump.h \ Gamemenu_gump.cc \ Gamemenu_gump.h \ Gump.cc \ Gump.h \ Gump_button.cc \ Gump_button.h \ gump_utils.h \ Gump_widget.cc \ Gump_widget.h \ misc_buttons.cc \ misc_buttons.h \ Modal_gump.h \ Paperdoll_gump.cc \ Paperdoll_gump.h \ Paperdoll_gump_info.cc \ Scroll_gump.cc \ Scroll_gump.h \ Sign_gump.cc \ Sign_gump.h \ Slider_gump.cc \ Slider_gump.h \ Spellbook_gump.cc \ Spellbook_gump.h \ Stats_gump.cc \ Stats_gump.h \ Text_gump.cc \ Text_gump.h \ Yesno_gump.cc \ Yesno_gump.h \ Newfile_gump.cc \ Newfile_gump.h \ AudioOptions_gump.cc \ AudioOptions_gump.h \ VideoOptions_gump.cc \ VideoOptions_gump.h \ GameplayOptions_gump.cc \ GameplayOptions_gump.h \ CombatOptions_gump.cc \ CombatOptions_gump.h \ Gump_ToggleButton.cc \ Gump_ToggleButton.h \ CombatStats_gump.cc \ CombatStats_gump.h \ gump_types.h \ Face_button.cc \ Face_button.h \ Jawbone_gump.h \ Jawbone_gump.cc \ Gump_manager.h \ Gump_manager.cc \ Face_stats.h \ Face_stats.cc \ Text_button.h \ Text_button.cc \ Enabled_button.h \ Enabled_button.cc CLEANFILES = *~ exult-1.2/gumps/Makefile.in0000644000175000001440000003526510061527057011410 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ -I$(srcdir)/../shapes -I$(srcdir)/../objs -I$(srcdir)/../audio\ -I$(srcdir)/../conf -I$(srcdir)/../usecode -I$(srcdir)/../data\ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libgumps.la libgumps_la_SOURCES = \ Actor_gump.cc \ Actor_gump.h \ Book_gump.cc \ Book_gump.h \ File_gump.cc \ File_gump.h \ Gamemenu_gump.cc \ Gamemenu_gump.h \ Gump.cc \ Gump.h \ Gump_button.cc \ Gump_button.h \ gump_utils.h \ Gump_widget.cc \ Gump_widget.h \ misc_buttons.cc \ misc_buttons.h \ Modal_gump.h \ Paperdoll_gump.cc \ Paperdoll_gump.h \ Paperdoll_gump_info.cc \ Scroll_gump.cc \ Scroll_gump.h \ Sign_gump.cc \ Sign_gump.h \ Slider_gump.cc \ Slider_gump.h \ Spellbook_gump.cc \ Spellbook_gump.h \ Stats_gump.cc \ Stats_gump.h \ Text_gump.cc \ Text_gump.h \ Yesno_gump.cc \ Yesno_gump.h \ Newfile_gump.cc \ Newfile_gump.h \ AudioOptions_gump.cc \ AudioOptions_gump.h \ VideoOptions_gump.cc \ VideoOptions_gump.h \ GameplayOptions_gump.cc \ GameplayOptions_gump.h \ CombatOptions_gump.cc \ CombatOptions_gump.h \ Gump_ToggleButton.cc \ Gump_ToggleButton.h \ CombatStats_gump.cc \ CombatStats_gump.h \ gump_types.h \ Face_button.cc \ Face_button.h \ Jawbone_gump.h \ Jawbone_gump.cc \ Gump_manager.h \ Gump_manager.cc \ Face_stats.h \ Face_stats.cc \ Text_button.h \ Text_button.cc \ Enabled_button.h \ Enabled_button.cc CLEANFILES = *~ subdir = gumps mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libgumps_la_LDFLAGS = libgumps_la_LIBADD = am_libgumps_la_OBJECTS = Actor_gump.lo Book_gump.lo File_gump.lo \ Gamemenu_gump.lo Gump.lo Gump_button.lo Gump_widget.lo \ misc_buttons.lo Paperdoll_gump.lo Paperdoll_gump_info.lo \ Scroll_gump.lo Sign_gump.lo Slider_gump.lo Spellbook_gump.lo \ Stats_gump.lo Text_gump.lo Yesno_gump.lo Newfile_gump.lo \ AudioOptions_gump.lo VideoOptions_gump.lo \ GameplayOptions_gump.lo CombatOptions_gump.lo \ Gump_ToggleButton.lo CombatStats_gump.lo Face_button.lo \ Jawbone_gump.lo Gump_manager.lo Face_stats.lo Text_button.lo \ Enabled_button.lo libgumps_la_OBJECTS = $(am_libgumps_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/Actor_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/AudioOptions_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Book_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/CombatOptions_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/CombatStats_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Enabled_button.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Face_button.Plo $(DEPDIR)/Face_stats.Plo \ @AMDEP_TRUE@ $(DEPDIR)/File_gump.Plo $(DEPDIR)/Gamemenu_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/GameplayOptions_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Gump.Plo $(DEPDIR)/Gump_ToggleButton.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Gump_button.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Gump_manager.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Gump_widget.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Jawbone_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Newfile_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Paperdoll_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Paperdoll_gump_info.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Scroll_gump.Plo $(DEPDIR)/Sign_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Slider_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Spellbook_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Stats_gump.Plo $(DEPDIR)/Text_button.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Text_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/VideoOptions_gump.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Yesno_gump.Plo $(DEPDIR)/misc_buttons.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libgumps_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libgumps_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu gumps/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libgumps.la: $(libgumps_la_OBJECTS) $(libgumps_la_DEPENDENCIES) $(CXXLINK) $(libgumps_la_LDFLAGS) $(libgumps_la_OBJECTS) $(libgumps_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Actor_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/AudioOptions_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Book_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/CombatOptions_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/CombatStats_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Enabled_button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Face_button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Face_stats.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/File_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gamemenu_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/GameplayOptions_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gump_ToggleButton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gump_button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gump_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Gump_widget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Jawbone_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Newfile_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Paperdoll_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Paperdoll_gump_info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Scroll_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Sign_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Slider_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Spellbook_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Stats_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Text_button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Text_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/VideoOptions_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Yesno_gump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/misc_buttons.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/gumps/Actor_gump.h0000755000175000001440000000446007506445352011617 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ACTOR_GUMP_H_ #define _ACTOR_GUMP_H_ #include "Gump.h" class Heart_button; class Disk_button; class Combat_button; class Halo_button; class Combat_mode_button; /* * A rectangular area showing a character and his/her possessions: */ class Actor_gump : public Gump { UNREPLICATABLE_CLASS(Actor_gump); protected: Heart_button *heart_button;// For bringing up stats. Disk_button *disk_button; // For bringing up 'save' box. Combat_button *combat_button; Halo_button *halo_button; Combat_mode_button *cmode_button; static short coords[24]; // Coords. of where to draw things, // indexed by spot # (0-11). static int spotx(int i) { return coords[2*i]; } static int spoty(int i) { return coords[2*i + 1]; } // Find index of closest spot. int find_closest(int mx, int my, int only_empty = 0); void set_to_spot(Game_object *obj, int index); static short diskx, disky; // Where to show 'diskette' button. static short heartx, hearty; // Where to show 'stats' button. static short combatx, combaty; // Combat button. static short halox, haloy; // "Protected" halo. static short cmodex, cmodey; // Combat mode. public: Actor_gump(Container_game_object *cont, int initx, int inity, int shnum); ~Actor_gump(); // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); // Add object. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false); // Paint it and its contents. virtual void paint(); virtual Container_game_object *find_actor(int mx, int my); }; #endif exult-1.2/gumps/gump_utils.h0000755000175000001440000000267607724430451011712 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_UTILS_H_ #define _GUMP_UTILS_H_ #ifdef XWIN /* Only needed in XWIN. */ #include #endif #ifdef OPENBSD #include #endif #include #ifndef XWIN #include "SDL_timer.h" #endif /* * Delay between animations. */ inline void Delay ( ) { #ifdef XWIN /* * Here's a somewhat better way to delay in X: */ extern int xfd; fd_set rfds; struct timeval timer; timer.tv_sec = 0; timer.tv_usec = 50000; // Try 1/50 second. FD_ZERO(&rfds); FD_SET(xfd, &rfds); // Wait for timeout or event. select(xfd + 1, &rfds, 0, 0, &timer); #else /* May use this for Linux too. */ SDL_Delay(10); // Try 1/100 second. #endif } #endif exult-1.2/gumps/GameplayOptions_gump.cc0000644000175000001440000002451310040665773014014 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "SDL_events.h" #include "Gump_manager.h" #include "Configuration.h" #include "Gump_button.h" #include "Gump_ToggleButton.h" #include "GameplayOptions_gump.h" #include "exult.h" #include "exult_flx.h" #include "game.h" #include "gamewin.h" #include "mouse.h" #include "cheat.h" #include "Face_stats.h" #include "Text_button.h" #include "Enabled_button.h" using std::cerr; using std::endl; using std::string; static const int rowy[] = { 4, 17, 134, 30, 43, 56, 69, 82, 95, 108, 121, 147 }; static const int colx[] = { 35, 50, 120, 195, 192 }; static const char* oktext = "OK"; static const char* canceltext = "CANCEL"; static int framerates[] = { 2, 4, 6, 8, 10, -1 }; // -1 is placeholder for custom framerate static int num_default_rates = sizeof(framerates)/sizeof(framerates[0]) - 1; static string framestring(int fr) { char buf[100]; sprintf(buf, "%i fps", fr); return buf; } class GameplayOptions_button : public Text_button { public: GameplayOptions_button(Gump *par, string text, int px, int py) : Text_button(par, text, px, py, 59, 11) { } // What to do when 'clicked': virtual void activate(); }; void GameplayOptions_button::activate() { if (text == canceltext) { ((GameplayOptions_gump*)parent)->cancel(); } else if (text == oktext) { ((GameplayOptions_gump*)parent)->close(); } } class GameplayTextToggle : public Gump_ToggleTextButton { public: GameplayTextToggle(Gump* par, std::string *s, int px, int py, int width, int selectionnum, int numsel) : Gump_ToggleTextButton(par, s, selectionnum, numsel, px, py, width) { } friend class GameplayOptions_gump; virtual void toggle(int state) { ((GameplayOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; class GameplayEnabledToggle : public Enabled_button { public: GameplayEnabledToggle(Gump* par, int px, int py, int width, int selectionnum) : Enabled_button(par, selectionnum, px, py, width) { } friend class GameplayOptions_gump; virtual void toggle(int state) { ((GameplayOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; void GameplayOptions_gump::close() { save_settings(); done = 1; } void GameplayOptions_gump::cancel() { done = 1; } void GameplayOptions_gump::toggle(Gump_button* btn, int state) { if (btn == buttons[0]) facestats = state; else if (btn == buttons[1]) fastmouse = state; else if (btn == buttons[2]) mouse3rd = state; else if (btn == buttons[3]) doubleclick = state; else if (btn == buttons[4]) cheats = state; else if (btn == buttons[5]) paperdolls = state; else if (btn == buttons[6]) text_bg = state; else if (btn == buttons[8]) frames = state; else if (btn == buttons[11]) rightclick_close = state; else if (btn == buttons[12]) doubleright_move = state; else if (btn == buttons[13]) gumps_pause = state; } void GameplayOptions_gump::build_buttons() { #if 0 std::string *enabledtext1 = new std::string[2]; enabledtext1[0] = "Disabled"; enabledtext1[1] = "Enabled"; std::string *enabledtext2 = new std::string[2]; enabledtext2[0] = "Disabled"; enabledtext2[1] = "Enabled"; std::string *enabledtext3 = new std::string[2]; enabledtext3[0] = "Disabled"; enabledtext3[1] = "Enabled"; std::string *enabledtext4 = new std::string[2]; enabledtext4[0] = "Disabled"; enabledtext4[1] = "Enabled"; std::string *enabledtext5 = new std::string[2]; enabledtext5[0] = "Disabled"; enabledtext5[1] = "Enabled"; #endif std::string *stats = new std::string[4]; stats[0] = "Disabled"; stats[1] = "Left"; stats[2] = "Middle"; stats[3] = "Right"; std::string *textbgcolor = new std::string[12]; textbgcolor[0] = "Disabled"; textbgcolor[1] = "Purple"; textbgcolor[2] = "Orange"; textbgcolor[3] = "Light Gray"; textbgcolor[4] = "Green"; textbgcolor[5] = "Yellow"; textbgcolor[6] = "Pale Blue"; textbgcolor[7] = "Dark Green"; textbgcolor[8] = "Red"; textbgcolor[9] = "Bright White"; textbgcolor[10] = "Dark gray"; textbgcolor[11] = "White"; buttons[0] = new GameplayTextToggle (this, stats, colx[3], rowy[0], 59, facestats, 4); buttons[6] = new GameplayTextToggle (this, textbgcolor, colx[3]-21, rowy[1], 80, text_bg, 12); if (GAME_BG) buttons[5] = new GameplayEnabledToggle(this, colx[3], rowy[2], 59, paperdolls); buttons[1] = new GameplayEnabledToggle(this, colx[3], rowy[3], 59, fastmouse); buttons[2] = new GameplayEnabledToggle(this, colx[3], rowy[4], 59, mouse3rd); buttons[3] = new GameplayEnabledToggle(this, colx[3], rowy[5], 59, doubleclick); buttons[11] = new GameplayEnabledToggle(this, colx[3], rowy[6], 59, rightclick_close); buttons[12] = new GameplayEnabledToggle(this, colx[3], rowy[7], 59, doubleright_move); buttons[13] = new GameplayEnabledToggle(this, colx[3], rowy[8], 59, gumps_pause); buttons[4] = new GameplayEnabledToggle(this, colx[3], rowy[9], 59, cheats); buttons[8] = new GameplayTextToggle(this, frametext, colx[3], rowy[10], 59, frames, num_framerates); } void GameplayOptions_gump::load_settings() { fastmouse = gwin->get_fastmouse(); mouse3rd = gwin->get_mouse3rd(); cheats = cheat(); facestats = Face_stats::get_state() + 1; doubleclick = 0; paperdolls = false; string pdolls; paperdolls = sman->get_bg_paperdolls(); doubleclick = gwin->get_double_click_closes_gumps(); rightclick_close = gumpman->can_right_click_close(); doubleright_move = gwin->get_allow_double_right_move(); text_bg = gwin->get_text_bg()+1; gumps_pause = !gumpman->gumps_dont_pause_game(); int realframes = 1000/gwin->get_std_delay(); int i; frames = -1; framerates[num_default_rates] = realframes; for (i=0; i < num_default_rates; i++) { if (realframes == framerates[i]) { frames = i; break; } } num_framerates = num_default_rates; if (frames == -1) { num_framerates++; frames = num_default_rates; } frametext = new string[num_framerates]; for (i=0; i < num_framerates; i++) { frametext[i] = framestring(framerates[i]); } } GameplayOptions_gump::GameplayOptions_gump() : Modal_gump(0, EXULT_FLX_GAMEPLAYOPTIONS_SHP, SF_EXULT_FLX) { set_object_area(Rectangle(0, 0, 0, 0), 8, 162);//++++++ ??? for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) buttons[i] = 0; load_settings(); build_buttons(); // Ok buttons[9] = new GameplayOptions_button(this, oktext, colx[0], rowy[11]); // Cancel buttons[10] = new GameplayOptions_button(this, canceltext, colx[4], rowy[11]); } GameplayOptions_gump::~GameplayOptions_gump() { for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i]) delete buttons[i]; } void GameplayOptions_gump::save_settings() { gwin->set_text_bg(text_bg-1); config->set("config/gameplay/textbackground", text_bg-1, true); int fps = framerates[frames]; gwin->set_std_delay(1000/fps); config->set("config/video/fps", fps, true); gwin->set_fastmouse(fastmouse!=false); config->set("config/gameplay/fastmouse", fastmouse ? "yes" : "no", true); gwin->set_mouse3rd(mouse3rd!=false); config->set("config/gameplay/mouse3rd", mouse3rd ? "yes" : "no", true); gwin->set_double_click_closes_gumps(doubleclick!=false); config->set("config/gameplay/double_click_closes_gumps", doubleclick ? "yes" : "no", true); gumpman->set_right_click_close(rightclick_close!=false); config->set("config/gameplay/right_click_closes_gumps", rightclick_close ? "yes" : "no" , true); cheat.set_enabled(cheats!=false); while (facestats != Face_stats::get_state() + 1) Face_stats::AdvanceState(); Face_stats::save_config(config); if (GAME_BG && sman->can_use_paperdolls()) sman->set_bg_paperdolls(paperdolls!=false); config->set("config/gameplay/bg_paperdolls", paperdolls ? "yes" : "no", true); gwin->set_allow_double_right_move(doubleright_move != false); config->set("config/gameplay/allow_double_right_move", doubleright_move?"yes":"no", true); gumpman->set_gumps_dont_pause_game(!gumps_pause); config->set("config/gameplay/gumps_dont_pause_game", gumps_pause?"no":"yes", true); } void GameplayOptions_gump::paint() { Gump::paint(); for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i]) buttons[i]->paint(); sman->paint_text(2, "Status Bars:", x + colx[0], y + rowy[0] + 1); sman->paint_text(2, "Text Background:", x + colx[0], y + rowy[1] + 1); if (GAME_BG) sman->paint_text(2, "Paperdolls:", x + colx[0], y + rowy[2] + 1); sman->paint_text(2, "Fast Mouse:", x + colx[0], y + rowy[3] + 1); sman->paint_text(2, "Use Middle Mouse Button:", x + colx[0], y + rowy[4] + 1); sman->paint_text(2, "Doubleclick closes Gumps:", x + colx[0], y + rowy[5] + 1); sman->paint_text(2, "Right click closes Gumps:", x + colx[0], y + rowy[6] + 1); sman->paint_text(2, "Double Right Pathfinds:", x + colx[0], y + rowy[7] + 1); sman->paint_text(2, "Gumps pause game:", x + colx[0], y + rowy[8] + 1); sman->paint_text(2, "Cheats:", x + colx[0], y + rowy[9] + 1); sman->paint_text(2, "Speed:", x + colx[0], y + rowy[10] + 1); gwin->set_painted(); } void GameplayOptions_gump::mouse_down(int mx, int my) { pushed = Gump::on_button(mx, my); // First try checkmark. // Try buttons at bottom. if (!pushed) for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } } void GameplayOptions_gump::mouse_up(int mx, int my) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) ((Gump_button*)pushed)->activate(); pushed = 0; } } exult-1.2/gumps/Text_button.cc0000644000175000001440000001126007550423657012170 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Text_button.h" #include "gamewin.h" #include "font.h" #include "iwin8.h" #include "Gump.h" #define TB_FONTNUM 2 // Palette Indices #define TB_OUTER_BORDER 133 #define TB_OUTER_BORDER_CORNER 142 #define TB_OUTER_BORDER_PUSHED_TOP 144 #define TB_OUTER_BORDER_PUSHED_LEFT 140 #define TB_INNER_BORDER_HIGHLIGHT 138 #define TB_INNER_BORDER_LOWLIGHT 142 #define TB_INNER_BORDER_CORNER 141 #define TB_INNER_BORDER_TR_HIGH 137 #define TB_INNER_BORDER_TR_CORNER 138 #define TB_INNER_BORDER_BL_CORNER 144 #define TB_BACKGROUND 140 #define TB_RT_HIGHLIGHT 139 Text_button::Text_button(Gump *p, const std::string &str, int x, int y, int w, int h) : Gump_button(p, 0, x, y, SF_OTHER), text(str), width(w), height(h) { init(); } void Text_button::init() { // Must be at least 11 units high if (height < 11) height = 11; // Text y is based on gump height of 11 text_y = 2 + (height - 11)/2; // We will get the text width int text_width = sman->get_font(TB_FONTNUM)->get_text_width( text.c_str()); if (width < text_width + 4) width = text_width + 4; // We want to find the starting point for the text (horizontal) text_x = (width - text_width) >> 1; } void Text_button::paint() { Image_window8 *iwin = gwin->get_win(); int offset = 0; int px = x; int py = y; if (parent) { px += parent->get_x(); py += parent->get_y(); } // The the push dependant edges if (pushed) { // Top left corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px, py); // Bottom left corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px, py+height-1); // Top right corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px+width-1, py); // Top edge iwin->fill8(TB_OUTER_BORDER_PUSHED_TOP, width-2, 1, px+1, py); // Left edge iwin->fill8(TB_OUTER_BORDER_PUSHED_TOP, 1, height-2, px, py+1); offset = 1; } else { // Bottom right corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px+width-1, py+height-1); // Bottom left corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px, py+height-1); // Top right corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px+width-1, py+height-1); // Bottom edge iwin->fill8(TB_OUTER_BORDER, width-2, 1, px+1, py+height-1); // Right edge iwin->fill8(TB_OUTER_BORDER, 1, height-2, px+width-1, py+1); } // 'Outer' Top and Left Edges // Top left corner iwin->fill8(TB_OUTER_BORDER_CORNER, 1, 1, px+offset, py+offset); // Top edge iwin->fill8(TB_OUTER_BORDER, width-2, 1, px+1+offset, py+offset); // Left edge iwin->fill8(TB_OUTER_BORDER, 1, height-2, px+offset, py+1+offset); // 'Inner' Edges // Top left corner iwin->fill8(TB_INNER_BORDER_CORNER, 1, 1, px+offset+1, py+offset+1); // Top Right corner iwin->fill8(TB_INNER_BORDER_TR_CORNER, 1, 1, px+width+offset-2, py+offset+1); // Top Right Highlight 1 iwin->fill8(TB_INNER_BORDER_TR_HIGH, 1, 1, px+width+offset-3, py+offset+1); // Top Right Highlight 1 iwin->fill8(TB_INNER_BORDER_TR_HIGH, 1, 1, px+width+offset-2, py+offset+2); // Bottom left corner iwin->fill8(TB_INNER_BORDER_BL_CORNER, 1, 1, px+offset+1, py+height+offset-2); // Top edge iwin->fill8(TB_INNER_BORDER_HIGHLIGHT, width-5, 1, px+2+offset, py+offset+1); // Left edge iwin->fill8(TB_INNER_BORDER_LOWLIGHT, 1, height-4, px+offset+1, py+2+offset); // Right edge iwin->fill8(TB_INNER_BORDER_HIGHLIGHT, 1, height-5, px+width+offset-2, py+3+offset); // Bottom edge iwin->fill8(TB_INNER_BORDER_LOWLIGHT, width-4, 1, px+2+offset, py+height+offset-2); // Background Fill iwin->fill8(TB_BACKGROUND, width-4, height-4, px+2+offset, py+2+offset); // Top Right Highligh on Background iwin->fill8(TB_RT_HIGHLIGHT, 1, 1, px+width+offset-3, py+offset+2); sman->paint_text(TB_FONTNUM, text.c_str(), px+text_x+offset, py+text_y+offset); } int Text_button::on_widget(int mx, int my) { int px = x; int py = y; if (parent) { px += parent->get_x(); py += parent->get_y(); } if (mx < px || mx >= px + width) return 0; if (my < py || my >= py + height) return 0; return 1; } exult-1.2/gumps/File_gump.cc0000755000175000001440000003447610054030560011555 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "SDL_events.h" #include "Audio.h" #include "Configuration.h" #include "File_gump.h" #include "exult.h" #include "game.h" #include "gamewin.h" #include "Gump_button.h" #include "mouse.h" #include "Yesno_gump.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::memmove; using std::string; using std::strlen; using std::strncpy; #endif /* * Statics: */ short File_gump::btn_rows[2] = {143, 156}; short File_gump::btn_cols[3] = {94, 163, 232}; short File_gump::textx = 237, File_gump::texty = 14, File_gump::texth = 13; /* * Load or save button. */ class Load_save_button : public Gump_button { public: Load_save_button(Gump *par, int px, int py, int shapenum) : Gump_button(par, shapenum, px, py) { } // What to do when 'clicked': virtual void activate(); }; /* * Quit button. */ class Quit_button : public Gump_button { public: Quit_button(Gump *par, int px, int py) : Gump_button(par, game->get_shape("gumps/quitbtn"), px, py) { } // What to do when 'clicked': virtual void activate(); }; /* * Sound 'toggle' buttons. */ class Sound_button : public Gump_button { public: Sound_button(Gump *par, int px, int py, int shapenum, bool enabled) : Gump_button(par, shapenum, px, py) { pushed = enabled; } // What to do when 'clicked': virtual void activate(); }; /* * Clicked a 'load' or 'save' button. */ void Load_save_button::activate ( ) { if (get_shapenum() == game->get_shape("gumps/loadbtn")) ((File_gump *) parent)->load(); else ((File_gump *) parent)->save(); } /* * Clicked on 'quit'. */ void Quit_button::activate ( ) { ((File_gump *) parent)->quit(); } /* * Clicked on one of the sound options. */ void Sound_button::activate ( ) { pushed = ((File_gump *) parent)->toggle_option(this); parent->paint(); } /* * An editable text field: */ class Gump_text : public Gump_widget { char *text; // Holds text, 0-delimited. int max_size; // Size (max) of text. int length; // Current # chars. int textx, texty; // Where to show text rel. to parent. int cursor; // Index of char. cursor is before. public: Gump_text(Gump *par, int shnum, int px, int py, int maxsz, int tx, int ty) : Gump_widget(par, shnum, px, py), text(new char[maxsz + 1]), max_size(maxsz), length(0), textx(x + tx), texty(y + ty), cursor(0) { text[0] = text[maxsz] = 0; Shape_frame *shape = ShapeID(shnum, 0, SF_GUMPS_VGA).get_shape(); // Want text coords. rel. to parent. textx -= shape->get_xleft(); texty -= shape->get_yabove(); } ~Gump_text() { delete [] text; } int get_length() { return length; } char *get_text() { return text; } void set_text(char *newtxt) // Set text. { strncpy(text, newtxt ? newtxt : "", max_size); length = strlen(text); } int get_cursor() { return cursor; } void set_cursor(int pos) // Set cursor (safely). { if (pos >= 0 && pos <= length) { cursor = pos; refresh(); } } void paint(); // Paint. // Handle mouse click. int mouse_clicked(int mx, int my); void insert(int chr); // Insert a character. int delete_left(); // Delete char. to left of cursor. int delete_right(); // Delete char. to right of cursor. void lose_focus(); protected: void refresh() { paint(); } }; /* * Paint text field. */ void Gump_text::paint ( ) { paint_shape(parent->get_x() + x, parent->get_y() + y); // Show text. sman->paint_text(2, text, parent->get_x() + textx, parent->get_y() + texty); if (get_framenum()) // Focused? Show cursor. gwin->get_win()->fill8(0, 1, sman->get_text_height(2), parent->get_x() + textx + sman->get_text_width(2, text, cursor), parent->get_y() + texty + 1); gwin->set_painted(); } /* * Handle click on text object. * * Output: 1 if point is within text object, else 0. */ int Gump_text::mouse_clicked ( int mx, int my // Mouse position on screen. ) { if (!on_widget(mx, my)) // Not in our area? return (0); mx -= textx + parent->get_x(); // Get pt. rel. to text area. if (!get_framenum()) // Gaining focus? { set_frame(1); // We have focus now. cursor = 0; // Put cursor at start. } else { for (cursor = 0; cursor <= length; cursor++) if (sman->get_text_width(2, text, cursor) > mx) { if (cursor > 0) cursor--; break; } if (cursor > length) cursor--; // Passed the end. } return (1); } /* * Insert a character at the cursor. */ void Gump_text::insert ( int chr ) { if (!get_framenum() || length == max_size) return; // Can't. if (cursor < length) // Open up space. memmove(text + cursor + 1, text + cursor, length - cursor); text[cursor++] = chr; // Store, and increment cursor. length++; text[length] = 0; refresh(); } /* * Delete the character to the left of the cursor. * * Output: 1 if successful. */ int Gump_text::delete_left ( ) { if (!get_framenum() || !cursor) // Can't do it. return (0); if (cursor < length) // Shift text left. memmove(text + cursor - 1, text + cursor, length - cursor); text[--length] = 0; // 0-delimit. cursor--; refresh(); return (1); } /* * Delete char. to right of cursor. * * Output: 1 if successful. */ int Gump_text::delete_right ( ) { if (!get_framenum() || cursor == length) return (0); // Past end of text. cursor++; // Move right. return (delete_left()); // Delete what was passed. } /* * Lose focus. */ void Gump_text::lose_focus ( ) { set_frame(0); refresh(); } /* * Create the load/save box. */ File_gump::File_gump ( ) : Modal_gump(0, game->get_shape("gumps/fileio")), pushed_text(0), focus(0), restored(0) { set_object_area(Rectangle(0,0,0,0), 8, 150); size_t i; int ty = texty; for (i = 0; i < sizeof(names)/sizeof(names[0]); i++, ty += texth) { names[i] = new Gump_text(this, game->get_shape("gumps/fntext"), textx, ty, 30, 12, 2); names[i]->set_text(gwin->get_save_name(i)); } // First row of buttons: buttons[0] = buttons[1] = 0; // No load/save until name chosen. buttons[2] = new Quit_button(this, btn_cols[2], btn_rows[0]); // 2nd row. buttons[3] = new Sound_button(this, btn_cols[0], btn_rows[1], game->get_shape("gumps/musicbtn"), Audio::get_ptr()->is_music_enabled()); buttons[4] = new Sound_button(this, btn_cols[1], btn_rows[1], game->get_shape("gumps/speechbtn"), Audio::get_ptr()->is_speech_enabled()); buttons[5] = new Sound_button(this, btn_cols[2], btn_rows[1], game->get_shape("gumps/soundbtn"), Audio::get_ptr()->are_effects_enabled()); } /* * Delete the load/save box. */ File_gump::~File_gump ( ) { size_t i; for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) delete names[i]; for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) delete buttons[i]; } /* * Get the index of one of the text fields (savegame #). * * Output: Index, or -1 if not found. */ int File_gump::get_save_index ( Gump_text *txt ) { for (size_t i = 0; i < sizeof(names)/sizeof(names[0]); i++) if (names[i] == txt) return (i); return (-1); } /* * Remove text focus. */ void File_gump::remove_focus ( ) { if (!focus) return; focus->lose_focus(); focus = 0; delete buttons[0]; // Remove load/save buttons. buttons[0] = 0; delete buttons[1]; buttons[1] = 0; paint(); } /* * 'Load' clicked. */ void File_gump::load ( ) { if (!focus || // This would contain the name. !focus->get_length()) return; int num = get_save_index(focus);// Which one is it? if (num == -1) return; // Shouldn't ever happen. if (!Yesno_gump::ask( "Okay to load over your current game?")) return; gwin->restore_gamedat(num); // Aborts if unsuccessful. gwin->read(); // And read the files in. done = 1; restored = 1; } /* * 'Save' clicked. */ void File_gump::save ( ) { if (!focus || // This would contain the name. !focus->get_length()) return; int num = get_save_index(focus);// Which one is it? if (num == -1) return; // Shouldn't ever happen. if (*gwin->get_save_name(num)) // Already a game in this slot? if (!Yesno_gump::ask( "Okay to write over existing saved game?")) return; gwin->write(); // First flush to 'gamedat'. gwin->save_gamedat(num, focus->get_text()); cout << "Saved game #" << num << " successfully." << endl; remove_focus(); } /* * 'Quit' clicked. */ void File_gump::quit ( ) { if (!Yesno_gump::ask("Do you really want to quit?")) return; quitting_time = QUIT_TIME_YES; done = 1; } /* * One of the option toggle buttons was pressed. * * Output: New state of option (0 or 1). */ int File_gump::toggle_option ( Gump_button *btn // Button that was clicked. ) { if (btn == buttons[3]) // Music? { bool music = !Audio::get_ptr()->is_music_enabled(); Audio::get_ptr()->set_music_enabled(music); if (!music) // Stop what's playing. Audio::get_ptr()->stop_music(); string s = music ? "yes" : "no"; // Write option out. config->set("config/audio/midi/enabled", s, true); return music ? 1 : 0; } if (btn == buttons[4]) // Speech? { bool speech = !Audio::get_ptr()->is_speech_enabled(); Audio::get_ptr()->set_speech_enabled(speech); string s = speech ? "yes" : "no"; // Write option out. config->set("config/audio/speech/enabled", s, true); return speech ? 1 : 0; } if (btn == buttons[5]) // Sound effects? { bool effects = !Audio::get_ptr()->are_effects_enabled(); Audio::get_ptr()->set_effects_enabled(effects); if (!effects) // Off? Stop what's playing. Audio::get_ptr()->stop_sound_effects(); string s = effects ? "yes" : "no"; // Write option out. config->set("config/audio/effects/enabled", s, true); return effects ? 1 : 0; } return false; // Shouldn't get here. } /* * Paint on screen. */ void File_gump::paint ( ) { Gump::paint(); // Paint background // Paint text objects. size_t i; for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) if (names[i]) names[i]->paint(); for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i]) buttons[i]->paint(); } /* * Handle mouse-down events. */ void File_gump::mouse_down ( int mx, int my // Position in window. ) { pushed = 0; pushed_text = 0; // First try checkmark. Gump_button *btn = Gump::on_button(mx, my); if (btn) pushed = btn; else // Try buttons at bottom. for (size_t i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } // See if on text field. for (size_t i = 0; i < sizeof(names)/sizeof(names[0]); i++) if (names[i]->on_widget(mx, my)) { pushed_text = names[i]; break; } } /* * Handle mouse-up events. */ void File_gump::mouse_up ( int mx, int my // Position in window. ) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) pushed->activate(); pushed = 0; } if (!pushed_text) return; // Let text field handle it. if (!pushed_text->mouse_clicked(mx, my) || pushed_text == focus) // Same field already selected? { pushed_text->paint(); pushed_text = 0; return; } if (focus) // Another had focus. { focus->set_text(gwin->get_save_name(get_save_index(focus))); focus->lose_focus(); } focus = pushed_text; // Switch focus to new field. pushed_text = 0; if (focus->get_length()) // Need load/save buttons? { if (!buttons[0]) buttons[0] = new Load_save_button(this, btn_cols[0], btn_rows[0], game->get_shape("gumps/loadbtn")); if (!buttons[1]) buttons[1] = new Load_save_button(this, btn_cols[1], btn_rows[0], game->get_shape("gumps/savebtn")); } else if (!focus->get_length()) { // No name yet. delete buttons[0]; delete buttons[1]; buttons[0] = buttons[1] = 0; } paint(); // Repaint. gwin->set_painted(); } /* * Handle character that was typed. */ void File_gump::text_input(int chr, int unicode) { if (!focus) // Text field? return; switch (chr) { case SDLK_RETURN: // If only 'Save', do it. if (!buttons[0] && buttons[1]) { buttons[1]->push(); gwin->show(1); buttons[1]->unpush(); gwin->show(1); buttons[1]->activate(); } break; case SDLK_BACKSPACE: if (focus->delete_left()) { // Can't restore now. delete buttons[0]; buttons[0] = 0; } if (!focus->get_length()) { // Last char.? delete buttons[0]; delete buttons[1]; buttons[0] = buttons[1] = 0; paint(); } return; case SDLK_DELETE: if (focus->delete_right()) { // Can't restore now. delete buttons[0]; buttons[0] = 0; } if (!focus->get_length()) { // Last char.? delete buttons[0]; delete buttons[1]; buttons[0] = buttons[1] = 0; paint(); } return; case SDLK_LEFT: focus->set_cursor(focus->get_cursor() - 1); return; case SDLK_RIGHT: focus->set_cursor(focus->get_cursor() + 1); return; case SDLK_HOME: focus->set_cursor(0); return; case SDLK_END: focus->set_cursor(focus->get_length()); return; } if ((unicode & 0xFF80) == 0 ) chr = unicode & 0x7F; else chr = 0; if (chr < ' ') return; // Ignore other special chars. if (chr < 256 && isascii(chr)) { int old_length = focus->get_length(); focus->insert(chr); // Added first character? Need // 'Save' button. if (!old_length && focus->get_length() && !buttons[1]) { buttons[1] = new Load_save_button(this, btn_cols[1], btn_rows[0], game->get_shape("gumps/savebtn")); buttons[1]->paint(); } if (buttons[0]) // Can't load now. { delete buttons[0]; buttons[0] = 0; paint(); } gwin->set_painted(); } } exult-1.2/gumps/CombatOptions_gump.cc0000644000175000001440000001401210002553605013437 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "SDL_events.h" #include "Gump_manager.h" #include "Configuration.h" #include "Gump_button.h" #include "Gump_ToggleButton.h" #include "CombatOptions_gump.h" #include "exult.h" #include "exult_flx.h" #include "gamewin.h" #include "combat_opts.h" #include "Text_button.h" #include "Enabled_button.h" using std::cerr; using std::endl; using std::string; static const int rowy[] = { 17, 43, 69, 130 }; static const int colx[] = { 35, 50, 120, 170, 192 }; static const char* oktext = "OK"; static const char* canceltext = "CANCEL"; static int framerates[] = { 2, 4, 6, 8, 10, -1 }; // -1 is placeholder for custom framerate static int num_default_rates = sizeof(framerates)/sizeof(framerates[0]) - 1; class CombatOptions_button : public Text_button { public: CombatOptions_button(Gump *par, string text, int px, int py) : Text_button(par, text, px, py, 59, 11) { } // What to do when 'clicked': virtual void activate(); }; void CombatOptions_button::activate() { if (text == canceltext) { ((CombatOptions_gump*)parent)->cancel(); } else if (text == oktext) { ((CombatOptions_gump*)parent)->close(); } } class CombatTextToggle : public Gump_ToggleTextButton { public: CombatTextToggle(Gump* par, std::string *s, int px, int py, int width, int selectionnum, int numsel) : Gump_ToggleTextButton(par, s, selectionnum, numsel, px, py, width) { } friend class CombatOptions_gump; virtual void toggle(int state) { ((CombatOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; class CombatEnabledToggle : public Enabled_button { public: CombatEnabledToggle(Gump* par, int px, int py, int width, int selectionnum) : Enabled_button(par, selectionnum, px, py, width) { } friend class CombatOptions_gump; virtual void toggle(int state) { ((CombatOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; void CombatOptions_gump::close() { save_settings(); done = 1; } void CombatOptions_gump::cancel() { done = 1; } void CombatOptions_gump::toggle(Gump_button* btn, int state) { if (btn == buttons[0]) difficulty = state; else if (btn == buttons[1]) show_hits = state; else if (btn == buttons[2]) mode = state; } void CombatOptions_gump::build_buttons() { std::string *diffs = new std::string[7]; diffs[0] = "Easiest (-3)"; diffs[1] = "Easier (-2)"; diffs[2] = "Easier (-1)"; diffs[3] = "Normal"; diffs[4] = "Harder (+1)"; diffs[5] = "Harder (+2)"; diffs[6] = "Hardest (+3)"; buttons[0] = new CombatTextToggle (this, diffs, colx[3], rowy[0], 85, difficulty, 7); buttons[1] = new CombatEnabledToggle(this, colx[3], rowy[1], 85, show_hits); std::string *modes = new std::string[2]; modes[0] = "Original"; modes[1] = "Space pauses"; buttons[2] = new CombatTextToggle (this, modes, colx[3], rowy[2], 85, mode, 2); } void CombatOptions_gump::load_settings() { difficulty = Combat::difficulty; if (difficulty < -3) difficulty = -3; else if (difficulty > 3) difficulty = 3; difficulty += 3; // Scale to choices (0-6). show_hits = Combat::show_hits ? 1 : 0; mode = (int) Combat::mode; if (mode < 0 || mode > 1) mode = 0; } CombatOptions_gump::CombatOptions_gump() : Modal_gump(0, EXULT_FLX_GAMEPLAYOPTIONS_SHP, SF_EXULT_FLX) { set_object_area(Rectangle(0, 0, 0, 0), 8, 162);//++++++ ??? const int nbuttons = sizeof(buttons)/sizeof(buttons[0]); for (int i = 0; i < nbuttons; i++) buttons[i] = 0; load_settings(); build_buttons(); // Ok buttons[nbuttons - 2] = new CombatOptions_button(this, oktext, colx[0], rowy[3]); // Cancel buttons[nbuttons - 1] = new CombatOptions_button(this, canceltext, colx[4], rowy[3]); } CombatOptions_gump::~CombatOptions_gump() { for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i]) delete buttons[i]; } void CombatOptions_gump::save_settings() { Combat::difficulty = difficulty - 3; config->set("config/gameplay/combat/difficulty", Combat::difficulty, true); Combat::show_hits = (show_hits != 0); config->set("config/gameplay/combat/show_hits", show_hits ? "yes" : "no", true); Combat::mode = (Combat::Mode) mode; std::string str = Combat::mode == Combat::keypause ? "keypause" : "original"; config->set("config/gameplay/combat/mode", str, true); } void CombatOptions_gump::paint() { Gump::paint(); for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i]) buttons[i]->paint(); sman->paint_text(2, "Difficulty:", x + colx[0], y + rowy[0] + 1); sman->paint_text(2, "Show Hits:", x + colx[0], y + rowy[1] + 1); sman->paint_text(2, "Mode:", x + colx[0], y + rowy[2] + 1); gwin->set_painted(); } void CombatOptions_gump::mouse_down(int mx, int my) { pushed = Gump::on_button(mx, my); // First try checkmark. // Try buttons at bottom. if (!pushed) for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } } void CombatOptions_gump::mouse_up(int mx, int my) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) ((Gump_button*)pushed)->activate(); pushed = 0; } } exult-1.2/gumps/Gump_widget.h0000755000175000001440000000316307506445352011771 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_WIDGET_H_ #define _GUMP_WIDGET_H_ #include "exceptions.h" #include "gump_types.h" #include "shapeid.h" #include "rect.h" class Gump; class Game_window; /* * A gump widget, such as a button or text field: */ class Gump_widget : public ShapeID { UNREPLICATABLE_CLASS(Gump_widget); protected: Gump_widget() : parent(0) { } Gump *parent; // Who this is in. short x, y; // Coords. relative to parent. public: friend class Gump; friend class Spellbook_gump; friend class Spellscroll_gump; Gump_widget(Gump *par, int shnum, int px, int py, ShapeFile shfile = SF_GUMPS_VGA) : ShapeID(shnum, 0, shfile), parent(par), x(px), y(py) { } // Is a given point on the widget? virtual int on_widget(int mx, int my); virtual void paint(); virtual Rectangle get_rect(); // update the widget, if required virtual void update_widget() { } virtual bool is_draggable() { return true; } }; #endif exult-1.2/gumps/Gump_widget.cc0000755000175000001440000000321107506445352012121 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gamewin.h" #include "Gump.h" #include "Gump_widget.h" /* * Is a given screen point on this widget? */ int Gump_widget::on_widget ( int mx, int my // Point in window. ) { mx -= parent->get_x() + x; // Get point rel. to gump. my -= parent->get_y() + y; Shape_frame *cshape = get_shape(); return (cshape!=0)?cshape->has_point(mx, my):false; } /* * Repaint checkmark, etc. */ void Gump_widget::paint ( ) { int px = 0; int py = 0; if (parent) { px = parent->get_x(); py = parent->get_y(); } paint_shape(x+px, y+py); } /* * Get screen area used by a gump. */ Rectangle Gump_widget::get_rect() { int px = x; int py = y; if (parent) { px += parent->get_x(); py += parent->get_y(); } Shape_frame *s = get_shape(); if (!s) return Rectangle(0,0,0,0); return Rectangle(px - s->get_xleft(), py - s->get_yabove(), s->get_width(), s->get_height()); } exult-1.2/gumps/Spellbook_gump.h0000755000175000001440000000601207575215735012502 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SPELLBOOK_GUMP_H_ #define _SPELLBOOK_GUMP_H_ #include "Gump.h" class Spellbook_object; class Bookmark_button; /* * Abstract base class for spellbook, spell-scrolls: */ class Spelltype_gump : public Gump { public: Spelltype_gump(int shnum) : Gump(0, shnum) { } virtual ~Spelltype_gump() { } // Perform spell. virtual void do_spell(int spell) = 0; // Set bookmark. virtual void select_spell(int spell) = 0; }; /* * Open spellbook. The spells are drawn in the object area. */ class Spellbook_gump : public Spelltype_gump { int page; // Starting with 0 (= circle #). int turning_page; // 1 if turning forward, -1 backward, // 0 if not turning. int turning_frame; // Next frame to show. short avail[9*8]; // For each spell, # which the // available reagents make possible. Spellbook_object *book; // Book this shows. Game_object *book_owner; // Top-owner of book. // Page turners: Gump_button *leftpage, *rightpage; Bookmark_button *bookmark; Gump_button *spells[9*8]; // ->spell 'buttons'. int spwidth, spheight; // Dimensions of a spell shape. void set_avail(); // Set up counts. public: friend class Bookmark_button; Spellbook_gump(Spellbook_object *b); ~Spellbook_gump(); virtual void do_spell(int spell); // Perform spell. void change_page(int delta); // Page forward/backward. virtual void select_spell(int spell); // Set bookmark. virtual Game_object *get_owner();// Get object this belongs to. // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); // Paint button. virtual void paint_button(Gump_button *btn); // Paint it and its contents. virtual void paint(); }; /* * Open spell-scroll in Serpent Isle. */ class Spellscroll_gump : public Spelltype_gump { Game_object *scroll; // Scroll clicked on. Gump_button *spell; int spwidth, spheight; // Dimensions of a spell shape. public: Spellscroll_gump(Game_object *s); ~Spellscroll_gump(); virtual void do_spell(int spell); // Perform spell. virtual void select_spell(int) { } virtual Game_object *get_owner();// Get object this belongs to. // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); // Paint button. virtual void paint_button(Gump_button *btn); // Paint it and its contents. virtual void paint(); }; #endif exult-1.2/gumps/Scroll_gump.h0000755000175000001440000000176607506441032012002 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SCROLL_GUMP_H_ #define _SCROLL_GUMP_H_ #include "Text_gump.h" /* * A scroll: */ class Scroll_gump : public Text_gump { UNREPLICATABLE_CLASS_I(Scroll_gump,Text_gump(0)); public: Scroll_gump(bool serp = false); // Paint it and its contents. virtual void paint(); }; #endif exult-1.2/gumps/Face_button.cc0000644000175000001440000000376610003025430012064 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Face_button.h" #include "Paperdoll_gump.h" #include "actors.h" #include "gamewin.h" Face_button::Face_button(Gump *par, int px, int py, Actor *a) : Gump_button(par, 0, px, py), actor(a) { Paperdoll_gump::Paperdoll_npc *npcinfo = Paperdoll_gump::GetCharacterInfo(a->get_shapenum()); if (!npcinfo) npcinfo = Paperdoll_gump::GetCharacterInfoSafe(a->get_sexed_coloured_shape()); if (!npcinfo) npcinfo = Paperdoll_gump::GetCharacterInfoSafe(a->get_shape_real()); set_shape(npcinfo->head_shape); set_frame(npcinfo->head_frame); set_file(npcinfo->file); } void Face_button::double_clicked(int x, int y) { actor->show_inventory(); } void Face_button::update_widget() { Paperdoll_gump::Paperdoll_npc *npcinfo = Paperdoll_gump::GetCharacterInfo(actor->get_shapenum()); if (!npcinfo) npcinfo = Paperdoll_gump::GetCharacterInfoSafe(actor->get_sexed_coloured_shape()); if (!npcinfo) npcinfo = Paperdoll_gump::GetCharacterInfoSafe(actor->get_shape_real()); if (get_shapenum() != npcinfo->head_shape || get_framenum() != npcinfo->head_frame || get_shapefile() != npcinfo->file) { gwin->add_dirty(get_rect()); set_shape(npcinfo->head_shape); set_frame(npcinfo->head_frame); set_file(npcinfo->file); gwin->add_dirty(get_rect()); } } exult-1.2/gumps/Face_stats.cc0000644000175000001440000002375610054034346011724 /* Copyright (C) 2001-2004 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Face_stats.h" #include "Face_button.h" #include "Paperdoll_gump.h" #include "actors.h" #include "party.h" #include "exult_flx.h" #include "gamewin.h" #include "game.h" #include "Gump_manager.h" #define PALETTE_INDEX_RED 22 #define PALETTE_INDEX_GREEN 64 #define PALETTE_INDEX_BLUE 79 #define PORTRAIT_NUM_MODES 3 #define PORTRAIT_WIDTH 40 class Stat_bar : public Gump_button { Actor *actor; int prop; int prop_max; unsigned char colour; int val; int max_val; public: Stat_bar(Gump *par, int px, int py, Actor *a, int s, int m, unsigned char c); virtual void double_clicked(int x, int y); virtual void paint(); virtual void activate() {} virtual void push() {} virtual void unpush() {} // update dirty region, if required virtual void update_widget(); virtual bool is_draggable() { return false; } }; Stat_bar::Stat_bar (Gump *par, int px, int py, Actor *a, int s, int m, unsigned char c) : Gump_button(par, EXULT_FLX_HP_BAR_SHP, px, py, SF_EXULT_FLX), actor(a), prop(s), prop_max(m), colour(c), val(-256), max_val(-256) { gwin->add_dirty(get_rect()); val = actor->get_effective_prop(prop); max_val = actor->get_effective_prop(prop_max); } void Stat_bar::double_clicked(int x, int y) { gumpman->add_gump(actor, game->get_shape("gumps/statsdisplay")); } /* * Paint on screen. */ void Stat_bar::paint ( ) { Gump_button::paint(); int width = (val * 32) / (max_val ? max_val : 1); if (width > 0) { if (width > 32) width = 32; int px = x; int py = y; if (parent) { px += parent->get_x(); py += parent->get_y(); } gwin->get_win()->fill8(colour, width, 3, px, py); } } /* * Update Dirty Region */ void Stat_bar::update_widget() { if (val != actor->get_effective_prop(prop) || max_val != actor->get_effective_prop(prop_max)) gwin->add_dirty(get_rect()); val = actor->get_effective_prop(prop); max_val = actor->get_effective_prop(prop_max); } /* * Portrait_button */ class Portrait_button : public Face_button { protected: Stat_bar *hp; // Bar for HP Stat_bar *mana; // Bar for MANA bool hit; int pois; int prot; public: Portrait_button(Gump *par, int px, int py, Actor *a); virtual ~Portrait_button(); virtual void double_clicked(int x, int y); virtual void paint(); // update dirty region, if required virtual void update_widget(); virtual int on_button(int mx, int my); virtual Rectangle get_rect(); virtual bool is_draggable() { return false; } }; Portrait_button::Portrait_button(Gump *par, int px, int py, Actor *a) : Face_button(par, px+14, py-20, a), hp(0), mana(0) { hp = new Stat_bar(par, px+4, py - 10, a, Actor::health, Actor::strength, PALETTE_INDEX_RED); if (actor->get_npc_num() == 0) mana = new Stat_bar(par, px+4, py - 5, a, Actor::mana, Actor::magic, PALETTE_INDEX_BLUE); hit = actor->was_hit(); pois = actor->get_flag(Obj_flags::poisoned); prot = actor->get_flag(Obj_flags::protection); gwin->add_dirty(get_rect()); } Portrait_button::~Portrait_button() { if (hp) delete hp; if (mana) delete mana; } void Portrait_button::double_clicked(int x, int y) { if (hp && hp->on_button(x, y)) hp->double_clicked(x, y); else if (mana && mana->on_button(x, y)) mana->double_clicked(x, y); else actor->show_inventory(); } int Portrait_button::on_button(int x, int y) { if (hp && hp->on_button(x, y)) return true; else if (mana && mana->on_button(x, y)) return true; else if (Face_button::on_button(x, y)) return true; return false; } void Portrait_button::update_widget() { Face_button::update_widget(); if (hp) hp->update_widget(); if (mana) mana->update_widget(); if (hit != actor->was_hit() || pois != actor->get_flag(Obj_flags::poisoned) || prot != actor->get_flag(Obj_flags::protection)) { Rectangle r = get_rect(); gwin->add_dirty(r); hit = actor->was_hit(); pois = actor->get_flag(Obj_flags::poisoned); prot = actor->get_flag(Obj_flags::protection); r = get_rect(); gwin->add_dirty(r); } } /* * Paint on screen. */ void Portrait_button::paint() { Face_button::paint(); Shape_frame *s = get_shape(); if (s) { int px = x; int py = y; if (parent) { px += parent->get_x(); py += parent->get_y(); } if (hit) { sman->paint_outline(px, py, s, HIT_PIXEL); } else if (pois) { sman->paint_outline(px, py, s, POISON_PIXEL); } else if (prot) { sman->paint_outline(px, py, s, PROTECT_PIXEL); } } if (hp) hp->paint(); if (mana) mana->paint(); } Rectangle Portrait_button::get_rect() { Rectangle rect = Face_button::get_rect(); if (hit || pois || prot) rect.enlarge(2); if (hp) { Rectangle r = hp->get_rect(); rect.add(r); } if (mana) { Rectangle r = mana->get_rect(); rect.add(r); } return rect; } /* * Face_stats */ Face_stats::Face_stats() : Gump(0, 0, 0, 0, SF_GUMPS_VGA) { if (self) throw exult_exception("Only 1 Set of Party Portraits Allowed!"); for (int i = 1; i < 8; i++) { npc_nums[i] = -1; party[i] = 0; } create_buttons(); self = this; } Face_stats::~Face_stats() { delete_buttons(); gwin->set_all_dirty(); self = 0; } /* * Paint on screen. */ void Face_stats::paint ( ) { for (int i = 0; i < 8; i++) if (party[i]) party[i]->paint(); } /* * On a Button? */ Gump_button *Face_stats::on_button(int mx, int my) { for (int i = 0; i < 8; i++) if (party[i] && party[i]->on_button(mx, my)) return party[i]; return 0; } // add dirty region, if dirty void Face_stats::update_gump() { if (has_changed()) { delete_buttons(); create_buttons(); } else { for (int i = 0; i < 8; i++) if (party[i]) party[i]->update_widget(); } } // Has this changed? bool Face_stats::has_changed() { if (resx != gwin->get_width() || resy != gwin->get_height()) return true; if (party_size != partyman->get_count()) return true; for (int i = 0; i < party_size; i++) if (npc_nums[i+1] != partyman->get_member(i)) return true; return false; } // Delete all the buttons void Face_stats::delete_buttons() { gwin->add_dirty(get_rect()); for (int i = 0; i < 8; i++) { if (party[i]) { delete party[i]; party[i] = 0; } npc_nums[i] = -1; } resx = 0; resy = 0; } void Face_stats::create_buttons() { int i; int pos = 0; int width = PORTRAIT_WIDTH; resx = gwin->get_width(); resy = gwin->get_height(); x = 0; y = resy; party_size = partyman->get_count(); int num_to_paint = 0; // In BG only Npc's 0 to 10 have paperdolls/gumps for (i = 0; i < party_size; i++) { int num = partyman->get_member(i); if (GAME_SI || (num >= 0 && num <=10)) ++num_to_paint; } if (mode == 0) pos = 0; else if (mode == 1) pos = (resx - (num_to_paint+1)*PORTRAIT_WIDTH)/2; else if (mode == 2) { pos = resx - PORTRAIT_WIDTH; width = - PORTRAIT_WIDTH; } std::memset (party, 0, sizeof(party)); party[0] = new Portrait_button(this, pos, 0, gwin->get_main_actor()); for (i = 0; i < party_size; i++) { npc_nums[i+1] = partyman->get_member(i); // In BG only Npc's 0 to 10 have paperdolls/gumps if (GAME_SI || (npc_nums[i+1] >= 0 && npc_nums[i+1] <=10)) { pos += width; party[i+1] = new Portrait_button(this, pos, 0, gwin->get_npc(npc_nums[i+1])); } else { party[i+1] = 0; } } region.x = region.y = region.w = region.h = 0; for (i = 0; i < 8; i++) if (party[i]) { Rectangle r = party[i]->get_rect(); region.add(r); } } bool Face_stats::has_point(int x, int y) { for (int i = 0; i < 8; i++) if (party[i] && party[i]->on_button(x, y)) return true; return false; } /* * Add an object. If mx, my, sx, sy are all -1, the object's position * is calculated by 'paint()'. If they're all -2, it's assumed that * obj->cx, obj->cy are already correct. * * Output: 0 if cannot add it. */ int Face_stats::add ( Game_object *obj, int mx, int my, // Mouse location. int sx, int sy, // Screen location of obj's hotspot. bool dont_check, // Skip volume check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { if (sx < 0 && sy < 0 && my < 0 && mx < 0) return 0; for (int i = 0; i < 8; i++) if (party[i] && party[i]->on_button(mx, my)) return party[i]->get_actor()->add(obj, dont_check, combine); return (0); } Container_game_object *Face_stats::find_actor(int mx, int my) { for (int i = 0; i < 8; i++) if (party[i] && party[i]->on_button(mx, my)) return party[i]->get_actor(); return 0; } // Statics int Face_stats::mode = 0; Face_stats *Face_stats::self = 0; // Creates if doesn't already exist void Face_stats::CreateGump() { if (!self) { new Face_stats(); gumpman->add_gump(self); } } // Removes is exists void Face_stats::RemoveGump() { if (self) gumpman->close_gump(self); //delete self; } // Increments the state of the gump void Face_stats::AdvanceState() { if (!self) CreateGump(); else { RemoveGump(); mode++; mode %=PORTRAIT_NUM_MODES; if (mode) CreateGump(); } } void Face_stats::save_config(Configuration *config) { if(self) config->set("config/gameplay/facestats",mode,true); else config->set("config/gameplay/facestats",-1,true); } void Face_stats::load_config(Configuration *config) { int nmode; if (Game::get_game_type() == EXULT_DEVEL_GAME) return; // FOR NOW, skip if new game. config->value("config/gameplay/facestats",nmode,-1); if(self) RemoveGump(); if(nmode>=0) { mode = nmode%PORTRAIT_NUM_MODES; CreateGump(); } } exult-1.2/gumps/Gump_manager.cc0000644000175000001440000003502410007505760012242 /* * Gump_manager.cc - Object that manages all available gumps * * Copyright (C) 2001-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "SDL_keyboard.h" #include "Configuration.h" #include "exult.h" #include "Gump.h" #include "Gump_manager.h" #include "gamewin.h" #include "Actor_gump.h" #include "Paperdoll_gump.h" #include "Spellbook_gump.h" #include "Stats_gump.h" #include "CombatStats_gump.h" #include "Jawbone_gump.h" #include "npcnear.h" #include "actors.h" #include "game.h" #include "Audio.h" #include "Yesno_gump.h" #include "gump_utils.h" #include "Slider_gump.h" using std::cout; using std::endl; Gump_manager::Gump_manager() : open_gumps(0), non_persistent_count(0), modal_gump_count(0), right_click_close(true), dont_pause_game(false) { std::string str; config->value("config/gameplay/right_click_closes_gumps", str, "yes"); if (str == "no") right_click_close = false; config->set("config/gameplay/right_click_closes_gumps", str, true); config->value("config/gameplay/gumps_dont_pause_game", str, "no"); dont_pause_game = str == "yes"; config->set("config/gameplay/gumps_dont_pause_game", dont_pause_game?"yes":"no", true); } /* * Showing gumps. */ bool Gump_manager::showing_gumps(bool no_pers) const { // If no gumps, or we do want to check for persistent, just check to see if any exist if (!no_pers || !open_gumps) return open_gumps != 0; // If we don't want to check for persistend for (Gump_list *gump = open_gumps; gump; gump = gump->next) if (!gump->gump->is_persistent()) return true; return false; } /* * Find the highest gump that the mouse cursor is on. * * Output: ->gump, or null if none. */ Gump *Gump_manager::find_gump ( int x, int y, // Pos. on screen. bool pers // Persistent? ) { Gump_list *gmp; Gump *found = 0; // We want last found in chain. for (gmp = open_gumps; gmp; gmp = gmp->next) { Gump *gump = gmp->gump; if (gump->has_point(x,y) && (pers || !gump->is_persistent())) found = gump; } return (found); } /* * Find gump containing a given object. */ Gump *Gump_manager::find_gump ( Game_object *obj ) { // Get container object is in. Game_object *owner = obj->get_owner(); if (!owner) return (0); // Look for container's gump. for (Gump_list *gmp = open_gumps; gmp; gmp = gmp->next) if (gmp->gump->get_container() == owner) return (gmp->gump); return (0); } /* * Find gump with a given owner & shapenum. */ Gump *Gump_manager::find_gump ( Game_object *owner, int shapenum ) { Gump_list *gmp; // See if already open. for (gmp = open_gumps; gmp; gmp = gmp->next) if (gmp->gump->get_owner() == owner && gmp->gump->get_shapenum() == shapenum) return gmp->gump; return (0); } /* * Add a gump to the end of a chain. */ void Gump_manager::add_gump(Gump *gump) { Gump_list *g = new Gump_list(gump); if (!open_gumps) open_gumps = g; // First one. else { Gump_list *last = open_gumps; while (last->next) last = last->next; last->next = g; } if (!gump->is_persistent()) // Count 'gump mode' gumps. { // And pause the game, if we want it non_persistent_count++; if (!dont_pause_game) gwin->get_tqueue()->pause(Game::get_ticks()); } } /* * Close a gump and delete it */ bool Gump_manager::close_gump(Gump *gump) { bool ret = remove_gump(gump); delete gump; return ret; } /* * Remove a gump from the chain */ bool Gump_manager::remove_gump(Gump *gump) { if (open_gumps) { if (open_gumps->gump == gump) { Gump_list *p = open_gumps->next; delete open_gumps; open_gumps = p; } else { Gump_list *p = open_gumps; // Find prev. to this. while (p->next != 0 && p->next->gump != gump) p = p->next; if (p->next) { Gump_list *g = p->next->next; delete p->next; p->next = g; } else return true; } if (!gump->is_persistent()) // Count 'gump mode' gumps. { // And resume queue if last. // Gets messed up upon 'load'. if (non_persistent_count > 0) non_persistent_count--; if (!dont_pause_game) gwin->get_tqueue()->resume(Game::get_ticks()); } } return false; } /* * Show a gump. */ void Gump_manager::add_gump ( Game_object *obj, // Object gump represents. int shapenum // Shape # in 'gumps.vga'. ) { int paperdoll = 0; if (shapenum >= ACTOR_FIRST_GUMP && shapenum <= ACTOR_LAST_GUMP && Game::get_game_type() == BLACK_GATE) paperdoll = 1; // overide for paperdolls if (shapenum == 123 && (Game::get_game_type() == SERPENT_ISLE || (sman->can_use_paperdolls() && sman->get_bg_paperdolls()))) paperdoll=2; Gump *dragged = gwin->get_dragging_gump(); // If we are dragging the same, just return if (dragged && dragged->get_owner() == obj && dragged->get_shapenum() == shapenum) return; static int cnt = 0; // For staggering them. Gump_list *gmp; // See if already open. for (gmp = open_gumps; gmp; gmp = gmp->next) if (gmp->gump->get_owner() == obj && gmp->gump->get_shapenum() == shapenum) break; if (gmp) // Found it? { // Move it to end. if (gmp->next) { Gump *gump = gmp->gump; remove_gump(gump); add_gump(gump); } gwin->paint(); return; } int x = (1 + cnt)*gwin->get_width()/10, y = (1 + cnt)*gwin->get_height()/10; ShapeID s_id(shapenum, 0, paperdoll == 2 ? SF_PAPERDOL_VGA : SF_GUMPS_VGA); Shape_frame *shape = s_id.get_shape(); if (x + shape->get_xright() > gwin->get_width() || y + shape->get_ybelow() > gwin->get_height()) { cnt = 0; x = gwin->get_width()/10; y = gwin->get_width()/10; } Gump *new_gump = 0; Actor *npc = 0; if (obj) npc = obj->as_actor(); if (npc && paperdoll == 2) new_gump = new Paperdoll_gump(npc, x, y, npc->get_npc_num()); else if (npc && paperdoll) new_gump = new Actor_gump(npc, x, y, shapenum); else if (shapenum == game->get_shape("gumps/statsdisplay")) new_gump = new Stats_gump((Container_game_object *) obj, x, y); else if (shapenum == game->get_shape("gumps/spellbook")) new_gump = new Spellbook_gump((Spellbook_object *) obj); else if (Game::get_game_type() == SERPENT_ISLE) { if (shapenum == game->get_shape("gumps/spell_scroll")) new_gump = new Spellscroll_gump(obj); else if (shapenum >= game->get_shape("gumps/cstats/1")&& shapenum <= game->get_shape("gumps/cstats/6")) new_gump = new CombatStats_gump(x, y); else if (shapenum == game->get_shape("gumps/jawbone")) new_gump = new Jawbone_gump( (Jawbone_object*) obj, x, y); } if (!new_gump) new_gump = new Container_gump((Container_game_object *) obj, x, y, shapenum); // Paint new one last. add_gump(new_gump); if (++cnt == 8) cnt = 0; int sfx = Audio::game_sfx(14); Audio::get_ptr()->play_sound_effect(sfx); // The weird noise. gwin->paint(); // Show everything. } /* * End gump mode. */ void Gump_manager::close_all_gumps ( bool pers ) { bool removed = false; Gump_list *prev = 0; Gump_list *next = open_gumps; while (next) // Remove all gumps. { Gump_list *gump = next; next = gump->next; // Don't delete if persistant or modal. if ((!gump->gump->is_persistent() || pers) && !gump->gump->is_modal()) { if (!gump->gump->is_persistent()) gwin->get_tqueue()->resume(Game::get_ticks()); if (prev) prev->next = gump->next; else open_gumps = gump->next; delete gump->gump; delete gump; removed = true; } else prev = gump; } non_persistent_count = 0; gwin->get_npc_prox()->wait(4); // Delay "barking" for 4 secs. if (removed) gwin->paint(); } /* * Handle a double-click. */ bool Gump_manager::double_clicked ( int x, int y, // Coords in window. Game_object *&obj ) { Gump *gump = find_gump(x, y); if (gump) { // Find object in gump. obj = gump->find_object(x, y); if (!obj) // Maybe it's a spell. { Gump_button *btn = gump->on_button(x, y); if (btn) btn->double_clicked(x, y); else if (gwin->get_double_click_closes_gumps()) { gump->close(); gwin->paint(); } } return true; } return false; } /* * Update the gumps */ void Gump_manager::update_gumps() { for (Gump_list *gmp = open_gumps; gmp; gmp = gmp->next) gmp->gump->update_gump(); } /* * Paint the gumps */ void Gump_manager::paint() { for (Gump_list *gmp = open_gumps; gmp; gmp = gmp->next) gmp->gump->paint(); } /* * Verify user wants to quit. * * Output: 1 to quit. */ int Gump_manager::okay_to_quit() { if (Yesno_gump::ask("Do you really want to quit?")) quitting_time = QUIT_TIME_YES; return quitting_time; } int Gump_manager::handle_modal_gump_event ( Modal_gump *gump, SDL_Event& event ) { // Game_window *gwin = Game_window::get_instance(); int scale_factor = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); static bool rightclick; switch (event.type) { case SDL_MOUSEBUTTONDOWN: #ifdef DEBUG cout << "(x,y) rel. to gump is (" << ((event.button.x / scale_factor) - gump->get_x()) << ", " << ((event.button.y / scale_factor) - gump->get_y()) << ")"<mouse_down(event.button.x / scale_factor, event.button.y / scale_factor); else if (event.button.button == 2 && gwin->get_mouse3rd()) { gump->key_down(SDLK_RETURN); gump->text_input(SDLK_RETURN, SDLK_RETURN); } else if (event.button.button == 3) rightclick = true; else if (event.button.button == 4) // mousewheel up gump->mousewheel_up(); else if (event.button.button == 5) // mousewheel down gump->mousewheel_down(); break; case SDL_MOUSEBUTTONUP: if (event.button.button == 1) gump->mouse_up(event.button.x / scale_factor, event.button.y / scale_factor); else if (event.button.button == 3 && gwin->get_mouse3rd() && rightclick) { rightclick = false; if (gumpman->can_right_click_close()) return 0; } break; case SDL_MOUSEMOTION: Mouse::mouse->move(event.motion.x / scale_factor, event.motion.y / scale_factor); Mouse::mouse_update = true; // Dragging with left button? if (event.motion.state & SDL_BUTTON(1)) gump->mouse_drag(event.motion.x / scale_factor, event.motion.y / scale_factor); break; case SDL_QUIT: if (okay_to_quit()) return (0); case SDL_KEYDOWN: { if (event.key.keysym.sym == SDLK_ESCAPE) return (0); if ((event.key.keysym.sym == SDLK_s) && (event.key.keysym.mod & KMOD_ALT) && (event.key.keysym.mod & KMOD_CTRL)) { make_screenshot(true); return 1; } int chr = event.key.keysym.sym; #if 0 gump->key_down((event.key.keysym.mod & KMOD_SHIFT) ? toupper(chr) : chr, event); #else gump->key_down(event.key.keysym.sym); gump->text_input(event.key.keysym.sym, event.key.keysym.unicode); #endif break; } } return (1); } /* * Handle a modal gump, like the range slider or the save box, until * the gump self-destructs. * * Output: 0 if user hit ESC. */ int Gump_manager::do_modal_gump ( Modal_gump *gump, // What the user interacts with. Mouse::Mouse_shapes shape, // Mouse shape to use. Paintable *paint // Paint this over everything else. ) { if (!modal_gump_count) SDL_EnableUNICODE(1); // enable unicode translation for text input modal_gump_count++; // Game_window *gwin = Game_window::get_instance(); // maybe make this selective? it's nice for menus, but annoying for sliders // gwin->end_gump_mode(); // Pause the game gwin->get_tqueue()->pause(SDL_GetTicks()); Mouse::Mouse_shapes saveshape = Mouse::mouse->get_shape(); if (shape != Mouse::dontchange) Mouse::mouse->set_shape(shape); int escaped = 0; add_gump(gump); gwin->paint(); // Show everything now. if (paint) paint->paint(); Mouse::mouse->show(); gwin->show(); do { Delay(); // Wait a fraction of a second. Mouse::mouse->hide(); // Turn off mouse. Mouse::mouse_update = false; SDL_Event event; while (!escaped && !gump->is_done() && SDL_PollEvent(&event)) escaped = !handle_modal_gump_event(gump, event); if (GL_manager::get_instance()) { gwin->paint(); // OpenGL? Paint each cycle. if (paint) paint->paint(); } Mouse::mouse->show(); // Re-display mouse. if (!gwin->show() && // Blit to screen if necessary. Mouse::mouse_update) // If not, did mouse change? Mouse::mouse->blit_dirty(); } while (!gump->is_done() && !escaped); Mouse::mouse->hide(); remove_gump(gump); Mouse::mouse->set_shape(saveshape); // Leave mouse off. gwin->paint(); gwin->show(true); // Resume the game gwin->get_tqueue()->resume(SDL_GetTicks()); modal_gump_count--; if (!modal_gump_count) SDL_EnableUNICODE(0); return (!escaped); } /* * Prompt for a numeric value using a slider. * * Output: Value, or 0 if user hit ESC. */ int Gump_manager::prompt_for_number ( int minval, int maxval, // Range. int step, int defval, // Default to start with. Paintable *paint // Should be the conversation. ) { Slider_gump *slider = new Slider_gump(minval, maxval, step, defval); int ok = do_modal_gump(slider, Mouse::hand, paint); int ret = !ok ? 0 : slider->get_val(); delete slider; return (ret); } /* * Show a number. */ void Gump_manager::paint_num ( int num, int x, // Coord. of right edge of #. int y // Coord. of top of #. ) { // Shape_manager *sman = Shape_manager::get_instance(); const int font = 2; char buf[20]; snprintf(buf, 20, "%d", num); sman->paint_text(font, buf, x - sman->get_text_width(font, buf), y); } /* * */ void Gump_manager::set_gumps_dont_pause_game(bool p) { // Don't do anything if they are the same if (dont_pause_game == p) return; dont_pause_game = p; // If pausing enabled, we need to go through and pause each gump if (!dont_pause_game) { for (Gump_list *gump = open_gumps; gump; gump = gump->next) if (!gump->gump->is_persistent()) gwin->get_tqueue()->pause(Game::get_ticks()); } // Otherwise we need to go through and resume each gump :-) else { for (Gump_list *gump = open_gumps; gump; gump = gump->next) if (!gump->gump->is_persistent()) gwin->get_tqueue()->resume(Game::get_ticks()); } } exult-1.2/gumps/Spellbook_gump.cc0000755000175000001440000003212007724430451012625 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "actors.h" #include "cheat.h" #include "gamewin.h" #include "Gump_button.h" #include "items.h" #include "mouse.h" #include "Spellbook_gump.h" #include "spellbook.h" #include "game.h" #include "Gump_manager.h" #ifndef ALPHA_LINUX_CXX # include #endif const int REAGENTS = 842; // Shape #. /* * Defines in 'gumps.vga': */ #define SPELLBOOK (GAME_BG ? 43 : 38) #define SPELLS (GAME_BG ? 33 : 28) // First group of 9 spells. #define TURNINGPAGE (GAME_BG ? 41 : 36) // Animation?? (4 frames). #define BOOKMARK (GAME_BG ? 42 : 37) // Red ribbon, 5 frames. #define LEFTPAGE (GAME_BG ? 44 : 39) // At top-left of left page. #define RIGHTPAGE (GAME_BG ? 45 : 40) // At top-right of right page. #define SCROLLSPELLS 66 // First group of scroll spells (SI). /* * And in 'text.flx': */ #define CIRCLE (GAME_BG ? 0x545 : 0x551) #define CIRCLENUM (GAME_BG ? 0x545 : 0x552) /* * Get circle, given a spell #. */ inline int Get_circle(int spell) { return spell/8; } /* * Get shape, frame for a given spell #. There are 8 shapes, each * containing 9 frames, where frame # = spell circle #. */ inline int Get_spell_gump_shape ( int spell, // Spell # (as used in Usecode). int& shape, // Shape returned (gumps.vga). int& frame // Frame returned. ) { if (spell < 0 || spell >= 0x48) return 0; shape = spell%8; frame = spell/8; return (1); } /* * A 'page-turner' button. */ class Page_button : public Gump_button { int leftright; // 0=left, 1=right. public: Page_button(Gump *par, int px, int py, int lr) : Gump_button(par, lr ? RIGHTPAGE : LEFTPAGE, px, py), leftright(lr) { } // What to do when 'clicked': virtual void activate(); virtual void push() {} virtual void unpush() {} }; /* * Handle click. */ void Page_button::activate ( ) { ((Spellbook_gump *) parent)->change_page(leftright ? 1 : -1); } /* * The bookmark. */ class Bookmark_button : public Gump_button { public: Bookmark_button(Gump *par) : Gump_button(par, BOOKMARK, 0, 0) { } void set(); // Call this to set properly. // What to do when 'clicked': virtual void activate(); virtual void push() {} virtual void unpush() {} }; /* * Set position and frame. */ void Bookmark_button::set ( ) { Spellbook_gump *sgump = (Spellbook_gump *) parent; Rectangle& object_area = sgump->object_area; int spwidth = sgump->spwidth; // Spell width. Spellbook_object *book = sgump->book; int page = sgump->page; // Page (circle) we're on. int bmpage = book->bookmark/8; // Bookmark's page. int s = book->bookmark%8; // Get # within circle. // Which side for bookmark? bool left = bmpage == page ? (s < 4) : bmpage < page; // Figure coords. x = left ? object_area.x + spwidth/2 : object_area.x + object_area.w - spwidth/2 - 2; Shape_frame *bshape = get_shape(); x += bshape->get_xleft(); y = object_area.y - 14 + bshape->get_yabove(); set_frame(bmpage == page ? (1 + s%4) : 0); } /* * Handle click. */ void Bookmark_button::activate ( ) { Spellbook_gump *sgump = (Spellbook_gump *) parent; int bmpage = sgump->book->bookmark/8; // Bookmark's page. // On a different, valid page? if (bmpage >= 0 && bmpage != sgump->page) sgump->change_page(bmpage - sgump->page); } /* * A spell button. */ class Spell_button : public Gump_button { int spell; // Spell # (0 - 71). public: Spell_button(Gump *par, int px, int py, int sp, int shnum, int frnum) : Gump_button(par, shnum, px, py), spell(sp) { set_frame(frnum); // Frame # is circle. } // What to do when 'clicked': virtual void activate(); virtual void double_clicked(int x, int y); virtual void push() { } virtual void unpush() { } }; /* * Handle click. */ void Spell_button::activate ( ) { ((Spelltype_gump *) parent)->select_spell(spell); } /* * Method for double-click. */ void Spell_button::double_clicked ( int x, int y ) { ((Spelltype_gump *) parent)->do_spell(spell); } /* * Figure the availability of the spells. */ void Spellbook_gump::set_avail ( ) { int i; // Init. for (i = 0; i < 9*8; i++) avail[i] = 0; if (book_owner == book) return; // Nobody owns it. int reagent_counts[NREAGENTS]; // Count reagents. int r; for (r = 0; r < NREAGENTS; r++) // Count, by frame (frame==bit#). reagent_counts[r] = book_owner->count_objects( REAGENTS, c_any_qual, r); bool has_ring = book->has_ring(gwin->get_main_actor()); for (i = 0; i < 9*8; i++) // Now figure what's available. { if (has_ring) { avail[i] = 10000; continue; } avail[i] = 10000; // 'infinite'. unsigned short flags = book->reagents[i]; // Go through bits. for (r = 0; flags; r++, flags = flags >> 1) // Take min. of req. reagent counts. if ((flags&1) && reagent_counts[r] < avail[i]) avail[i] = reagent_counts[r]; } } /* * Create spellbook display. */ Spellbook_gump::Spellbook_gump ( Spellbook_object *b ) : Spelltype_gump(SPELLBOOK), page(0), book(b), turning_page(0) { set_object_area(Rectangle(36, 28, 102, 66), 7, 54); // Where to paint page marks: const int lpagex = 38, rpagex = 142, lrpagey = 25; // Get book's top owner. book_owner = book->get_outermost(); set_avail(); // Figure spell counts. if (book->bookmark >= 0) // Set to bookmarked page. page = Get_circle(book->bookmark); leftpage = new Page_button(this, lpagex, lrpagey, 0); rightpage = new Page_button(this, rpagex, lrpagey, 1); bookmark = new Bookmark_button(this); // Get dims. of a spell. Shape_frame *spshape = ShapeID(SPELLS, 0, SF_GUMPS_VGA).get_shape(); spwidth = spshape->get_width(); spheight = spshape->get_height(); bookmark->set(); // Set to correct position, frame. int vertspace = (object_area.h - 4*spheight)/4; int spells0 = SPELLS; for (int c = 0; c < 9; c++) // Add each spell. { int spindex = c*8; unsigned char cflags = book->circles[c]; for (int s = 0; s < 8; s++) if ((cflags & (1<get_xleft() + 1 : object_area.x + object_area.w - spshape->get_xright() - 2, object_area.y + spshape->get_yabove() + (spheight + vertspace)*(s%4), spnum, spells0 + spnum%8, spnum/8); } else spells[spindex + s] = 0; } } /* * Delete. */ Spellbook_gump::~Spellbook_gump ( ) { delete leftpage; delete rightpage; delete bookmark; for (int i = 0; i < 9*8; i++) delete spells[i]; } /* * Perform a spell. */ void Spellbook_gump::do_spell ( int spell ) { if (!book->can_do_spell(gwin->get_main_actor(), spell)) Mouse::mouse->flash_shape(Mouse::redx); else { Spellbook_object *save_book = book; close(); // We've just been deleted! gwin->paint(); gwin->show(); // Don't need to check again. save_book->do_spell(gwin->get_main_actor(), spell, true); // Close all gumps so animations can // start. gumpman->close_all_gumps(); } } /* * Change page. */ void Spellbook_gump::change_page ( int delta ) { if (delta > 0) { if (page == 8) return; turning_page = -1; } else if (delta < 0) { if (page == 0) return; turning_page = 1; } ShapeID shape(TURNINGPAGE, 0, SF_GUMPS_VGA); int nframes = shape.get_num_frames(); int i; turning_frame = turning_page == 1 ? 0 : nframes - 1; for (i = 0; i < nframes; i++) // Animate. { if (i == nframes/2) { page += delta; // Change page halfway through. bookmark->set();// Update bookmark for new page. } gwin->add_dirty(get_rect()); gwin->paint_dirty(); gwin->show(); SDL_Delay(50); // 1/20 sec. } paint(); } /* * Set bookmark. */ void Spellbook_gump::select_spell ( int spell ) { if (spells[spell]) { book->bookmark = spell; bookmark->set(); // Update bookmark's position/frame. paint(); } } /* * Get object that 'owns' this. */ Game_object *Spellbook_gump::get_owner() { return book; } /* * Is a given screen point on one of our buttons? * * Output: ->button if so. */ Gump_button *Spellbook_gump::on_button ( int mx, int my // Point in window. ) { Gump_button *btn = Gump::on_button(mx, my); if (btn) return btn; else if (leftpage->on_button(mx, my)) return leftpage; else if (rightpage->on_button(mx, my)) return rightpage; int spindex = page*8; // Index into list. for (int s = 0; s < 8; s++) // Check spells. { Gump_button *spell = spells[spindex + s]; if (spell && spell->on_button(mx, my)) return spell; } if (bookmark->on_button(mx, my)) return bookmark; return 0; } /* * Our buttons are never drawn 'pushed'. */ void Spellbook_gump::paint_button ( Gump_button *btn ) { btn->paint(); } /* * Render. */ void Spellbook_gump::paint ( ) { const int numx = 1, numy = -4;// Where to draw numbers on spells, // with numx being the right edge. Gump::paint(); // Paint outside & checkmark. if (page > 0) // Not the first? paint_button(leftpage); if (page < 8) // Not the last? paint_button(rightpage); int spindex = page*8; // Index into list. for (int s = 0; s < 8; s++) // Paint spells. if (spells[spindex + s]) { Gump_button *spell = spells[spindex + s]; paint_button(spell); if (page == 0) // No quantities for 1st circle. continue; int num = avail[spindex + s]; char text[6]; if (num > 0 && num < 1000) { snprintf(text, 6, "%d", num < 100 ? num : 99); sman->paint_text(5, text, x + spell->x + numx - sman->get_text_width(4, text), y + spell->y + numy); } else if (num >= 1000) // Fake an 'infinity'. { std::strcpy(text, "oo"); int px = x + spell->x + numx + 2 - sman->get_text_width(4, text); sman->paint_text(5, text + 1, px, y + spell->y + numy); sman->paint_text(5, text + 1, px + 3, y + spell->y + numy); } } if (page > 0 || // Paint circle. Game::get_game_type() == SERPENT_ISLE) { char *circ = item_names[CIRCLE]; char *cnum = item_names[CIRCLENUM + page]; sman->paint_text(5, cnum, x + 40 + (44 - sman->get_text_width(4, cnum))/2, y + 20); sman->paint_text(5, circ, x + 92 + (44 - sman->get_text_width(4, circ))/2, y + 20); } if (book->bookmark >= 0) // Bookmark? paint_button(bookmark); if (turning_page) // Animate turning page. { const int TPXOFF = 5, TPYOFF = 3; ShapeID shape(TURNINGPAGE, turning_frame, SF_GUMPS_VGA); Shape_frame *fr = shape.get_shape(); int spritex = x + object_area.x + fr->get_xleft() + TPXOFF; int spritey = y + fr->get_yabove() + TPYOFF; shape.paint_shape(spritex, spritey); turning_frame += turning_page; if (turning_frame < 0 || turning_frame >= shape.get_num_frames()) turning_page = 0; // Last one. } gwin->set_painted(); } /* * Create spellscroll display. */ Spellscroll_gump::Spellscroll_gump ( Game_object *s ) : Spelltype_gump(65), scroll(s), spell(0) { set_object_area(Rectangle(30, 29, 50, 29), 8, 68); // Get dims. of a spell. Shape_frame *spshape = ShapeID(SCROLLSPELLS, 0, SF_GUMPS_VGA).get_shape(); spwidth = spshape->get_width(); spheight = spshape->get_height(); int spellnum = scroll->get_quality(); if (spellnum >= 0 && spellnum < 8*9) spell = new Spell_button(this, object_area.x + 4 + spshape->get_xleft(), object_area.y + 4 + spshape->get_yabove(), spellnum, SCROLLSPELLS + spellnum/8, spellnum%8); } /* * Delete. */ Spellscroll_gump::~Spellscroll_gump ( ) { delete spell; } /* * Perform the spell. */ void Spellscroll_gump::do_spell ( int spellnum ) { scroll->remove_this(); // Scroll is gone. scroll = 0; close(); // We've just been deleted! gwin->paint(); gwin->show(); Spellbook_object::execute_spell(gwin->get_main_actor(), spellnum); } /* * Return scroll. */ Game_object *Spellscroll_gump::get_owner ( ) { return scroll; } /* * Is a given screen point on one of our buttons? * * Output: ->button if so. */ Gump_button *Spellscroll_gump::on_button ( int mx, int my // Point in window. ) { Gump_button *btn = Gump::on_button(mx, my); if (btn) return btn; else if (spell && spell->on_button(mx, my)) return spell; return 0; } /* * Our buttons are never drawn 'pushed'. */ void Spellscroll_gump::paint_button ( Gump_button *btn ) { btn->paint(); } /* * Render. */ void Spellscroll_gump::paint ( ) { Gump::paint(); // Paint outside & checkmark. if (spell) paint_button(spell); gwin->set_painted(); } exult-1.2/gumps/Gump_ToggleButton.h0000644000175000001440000000366207506445352013124 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_TOGGLEBUTTON_H #define _GUMP_TOGGLEBUTTON_H #include "Gump_button.h" #include "Text_button.h" /* * A button that toggles shape when pushed */ class Gump_ToggleButton : public Gump_button { public: Gump_ToggleButton(Gump *par, int px, int py, int shapenum, int selectionnum, int numsel) : Gump_button(par, shapenum, px, py, SF_EXULT_FLX), numselections(numsel) { set_frame(2 * selectionnum); } virtual void activate(); int getselection() const { return get_framenum()/2; } virtual void toggle(int state) = 0; private: int numselections; }; /* * A text button that toggles shape when pushed */ class Gump_ToggleTextButton : public Text_button { public: Gump_ToggleTextButton(Gump *par, std::string *s, int selectionnum, int numsel, int px, int py, int width, int height = 0) : Text_button(par, "", px, py, width, height), selections(s), numselections(numsel) { set_frame(selectionnum); text = selections[selectionnum]; init(); } virtual ~Gump_ToggleTextButton() { delete [] selections; } virtual void activate(); int getselection() const { return get_framenum(); } virtual void toggle(int state) = 0; private: int numselections; std::string *selections; }; #endif exult-1.2/gumps/Book_gump.cc0000755000175000001440000000234507506776204011602 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Book_gump.h" #include "gamewin.h" #include "game.h" /* * Create book display. */ Book_gump::Book_gump ( bool serp ) : Text_gump(game->get_shape("gumps/book"), serp) { } /* * Paint book. Updates curend. */ void Book_gump::paint ( ) { // Paint the gump itself. paint_shape(x, y); // Paint left page. curend = paint_page(Rectangle(36, 10, 122, 130), curtop); // Paint right page. curend = paint_page(Rectangle(174, 10, 122, 130), curend); } exult-1.2/gumps/Book_gump.h0000755000175000001440000000200207506441032011416 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BOOK_GUMP_H_ #define _BOOK_GUMP_H_ #include "Text_gump.h" /* * A book shows text side-by-side. */ class Book_gump : public Text_gump { UNREPLICATABLE_CLASS_I(Book_gump,Text_gump(0)); public: Book_gump(bool serp = false); // Paint it and its contents. virtual void paint(); }; #endif exult-1.2/gumps/Enabled_button.cc0000644000175000001440000000211707506445352012574 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Enabled_button.h" #include "gamewin.h" const char* Enabled_button::selections[] = { "Disabled", "Enabled" }; void Enabled_button::activate() { set_frame(get_framenum() + 1); if (get_framenum() >= 2) set_frame(0); text = selections[get_framenum()]; init(); toggle(get_framenum()); paint(); gwin->set_painted(); } exult-1.2/gumps/Actor_gump.cc0000755000175000001440000001724607550423657011766 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Actor_gump.h" #include "actors.h" #include "gamewin.h" #include "misc_buttons.h" #ifndef ALPHA_LINUX_CXX # include #endif using std::size_t; #define TWO_HANDED_BROWN_SHAPE 48 #define TWO_HANDED_BROWN_FRAME 0 #define TWO_FINGER_BROWN_SHAPE 48 #define TWO_FINGER_BROWN_FRAME 1 /* * Statics: */ short Actor_gump::diskx = 124, Actor_gump::disky = 115; short Actor_gump::heartx = 124, Actor_gump::hearty = 132; short Actor_gump::combatx = 52, Actor_gump::combaty = 103; short Actor_gump::halox = 47, Actor_gump::haloy = 110; short Actor_gump::cmodex = 48, Actor_gump::cmodey = 132; short Actor_gump::coords[24] = { 114, 10, /* head */ 115, 24, /* back */ 115, 37, /* belt */ 115, 55, /* lhand */ 115, 71, /* lfinger */ 114, 85, /* legs */ 76, 98, /* feet */ 35, 70, /* rfinger */ 37, 56, /* rhand */ 37, 37, /* torso */ 37, 24, /* neck */ 37, 11 /* ammo */ }; /* * Find the index of the closest 'spot' to a mouse point. * * Output: Index, or -1 if unsuccessful. */ int Actor_gump::find_closest ( int mx, int my, // Mouse point in window. int only_empty // Only allow empty spots. ) { mx -= x; my -= y; // Get point rel. to us. long closest_squared = 1000000; // Best distance squared. int closest = -1; // Best index. for (size_t i = 0; i < sizeof(coords)/(2*sizeof(coords[0])); i++) { int dx = mx - spotx(i), dy = my - spoty(i); long dsquared = dx*dx + dy*dy; // Better than prev.? if (dsquared < closest_squared && (!only_empty || !container->get_readied(i))) { closest_squared = dsquared; closest = i; } } return (closest); } /* * Create the gump display for an actor. */ Actor_gump::Actor_gump ( Container_game_object *cont, // Container it represents. MUST // be an Actor. int initx, int inity, // Coords. on screen. int shnum // Shape #. ) : Gump(cont, initx, inity, shnum) { set_object_area(Rectangle(26, 0, 104, 132), 6, 136); Actor *npc = cont->as_actor(); heart_button = new Heart_button(this, heartx, hearty); if (npc->get_npc_num() == 0) disk_button = new Disk_button(this, diskx, disky); else disk_button = NULL; if (npc->get_npc_num() == 0) combat_button = new Combat_button(this, combatx, combaty); else combat_button = NULL; halo_button = new Halo_button(this, halox, haloy, npc); cmode_button = new Combat_mode_button(this, cmodex, cmodey, npc); for (size_t i = 0; i < sizeof(coords)/2*sizeof(coords[0]); i++) { // Set object coords. Game_object *obj = container->get_readied(i); if (obj) set_to_spot(obj, i); } } /* * Delete actor display. */ Actor_gump::~Actor_gump ( ) { if (heart_button) delete heart_button; if (disk_button) delete disk_button; if (combat_button) delete combat_button; if (halo_button) delete halo_button; if (cmode_button) delete cmode_button; } /* * Is a given screen point on one of our buttons? * * Output: ->button if so. */ Gump_button *Actor_gump::on_button ( int mx, int my // Point in window. ) { Gump_button *btn = Gump::on_button(mx, my); if (btn) return btn; else if (heart_button && heart_button->on_button(mx, my)) return heart_button; else if (disk_button && disk_button->on_button(mx, my)) return disk_button; else if (combat_button && combat_button->on_button(mx, my)) return combat_button; else if (halo_button && halo_button->on_button(mx, my)) return halo_button; else if (cmode_button && cmode_button->on_button(mx, my)) return cmode_button; return 0; } /* * Add an object. * * Output: 0 if cannot add it. */ int Actor_gump::add ( Game_object *obj, int mx, int my, // Screen location of mouse. int sx, int sy, // Screen location of obj's hotspot. bool dont_check, // Skip volume check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) #if 1 { Game_object *cont = find_object(mx, my); if (cont && cont->add(obj, false, combine)) return (1); int index = find_closest(mx, my, 1); if (index != -1 && container->add_readied(obj, index)) return (1); if (container->add(obj, dont_check, combine)) return (1); return (0); } #else { // Find index of closest spot. int index = find_closest(mx, my); if (!container->add_readied(obj, index)) { // Can't add it there? // Try again for an empty spot. index = find_closest(mx, my, 1); if (index < 0 || !container->add_readied(obj, index)) // Just try to add it. if (!container->add(obj)) return (0); } // In case it went in another obj: index = container->find_readied(obj); if (index >= 0) set_to_spot(obj, index);// Set obj. coords. return (1); } #endif /* * Set object's coords. to given spot. */ void Actor_gump::set_to_spot ( Game_object *obj, int index // Spot index. ) { // Get shape info. Shape_frame *shape = obj->get_shape(); if (!shape) return; // Not much we can do. int w = shape->get_width(), h = shape->get_height(); // Set object's position. obj->set_chunk(spotx(index) + shape->get_xleft() - w/2 - object_area.x, spoty(index) + shape->get_yabove() - h/2 - object_area.y); // Shift if necessary. int x0 = obj->get_cx() - shape->get_xleft(), y0 = obj->get_cy() - shape->get_yabove(); int newcx = obj->get_cx(), newcy = obj->get_cy(); if (x0 < 0) newcx -= x0; if (y0 < 0) newcy -= y0; int x1 = x0 + w, y1 = y0 + h; if (x1 > object_area.w) newcx -= x1 - object_area.w; if (y1 > object_area.h) newcy -= y1 - object_area.h; obj->set_chunk(newcx, newcy); } /* * Paint on screen. */ void Actor_gump::paint ( ) { // Watch for any newly added objs. for (size_t i = 0; i < sizeof(coords)/2*sizeof(coords[0]); i++) { // Set object coords. Game_object *obj = container->get_readied(i); if (obj)//&& !obj->get_cx() && !obj->get_cy()) set_to_spot(obj, i); } Gump::paint(); // Paint gump & objects. // Paint over blue lines for 2 handed Actor *actor = container->as_actor(); if (actor) { if (actor->is_two_fingered()) { int sx = x + 36, // Note this is the right finger slot shifted slightly sy = y + 70; ShapeID sid(TWO_FINGER_BROWN_SHAPE, TWO_FINGER_BROWN_FRAME, SF_GUMPS_VGA); sid.paint_shape (sx,sy); } if (actor->is_two_handed()) { int sx = x + 36, // Note this is the right hand slot shifted slightly sy = y + 55; ShapeID sid(TWO_HANDED_BROWN_SHAPE, TWO_HANDED_BROWN_FRAME, SF_GUMPS_VGA); sid.paint_shape (sx,sy); } } // Paint buttons. if (heart_button) heart_button->paint(); if (disk_button) disk_button->paint(); if (combat_button) combat_button->paint(); if (halo_button) halo_button->paint(); if (cmode_button) cmode_button->paint(); // Show weight. int max_weight = container->get_max_weight(); int weight = container->get_weight()/10; char text[20]; snprintf(text, 20, "%d/%d", weight, max_weight); int twidth = sman->get_text_width(2, text); const int boxw = 102; sman->paint_text(2, text, x + 28 + (boxw - twidth)/2, y + 120); } Container_game_object * Actor_gump::find_actor(int mx, int my) { return container; } exult-1.2/gumps/Text_button.h0000644000175000001440000000224707550423657012037 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TEXT_BUTTON_H #define TEXT_BUTTON_H #include "Gump_button.h" #include class Text_button : public Gump_button { protected: std::string text; int text_x; int text_y; int width; int height; void init(); public: Text_button(Gump *p, const std::string &str, int x, int y, int w = 0, int h = 0); virtual void paint(); virtual int on_widget(int mx, int my); virtual int on_button(int mx, int my) { return on_widget (mx, my); } }; #endif exult-1.2/gumps/Face_button.h0000644000175000001440000000235407506445352011745 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _FACE_BUTTON_H_ #define _FACE_BUTTON_H_ #include "Gump_button.h" class Actor; class Game_window; /* * A character's face, that will open inventory when clicked. */ class Face_button : public Gump_button { protected: Actor *actor; // Who this represents. public: Face_button(Gump *par, int px, int py, Actor *a); virtual Actor *get_actor() { return actor; } virtual void double_clicked(int x, int y); virtual void activate() {} virtual void push() {} virtual void unpush() {} virtual void update_widget(); }; #endif exult-1.2/gumps/Paperdoll_gump.cc0000755000175000001440000007450510012231303012605 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "game.h" #include "gamewin.h" #include "Gump_button.h" #include "misc_buttons.h" #include "Paperdoll_gump.h" #include "contain.h" #include "actors.h" #include "objiter.h" #include "cheat.h" #ifndef ALPHA_LINUX_CXX # include #endif using std::cerr; using std::endl; using std::size_t; //#define SHOW_USECODE_CONTAINER //#define SHOW_NONREADIED_OBJECTS /* * * SERPENT ISLE PAPERDOLL GUMP * */ /* * Statics: */ // Paperdoll is completely different to Actor short Paperdoll_gump::diskx = 123, Paperdoll_gump::disky = 137; short Paperdoll_gump::heartx = 97, Paperdoll_gump::hearty = 137; short Paperdoll_gump::combatx = 51, Paperdoll_gump::combaty = 142; short Paperdoll_gump::cstatx = 72, Paperdoll_gump::cstaty = 137; short Paperdoll_gump::cmodex = 75, Paperdoll_gump::cmodey = 140; short Paperdoll_gump::halox = 123, Paperdoll_gump::haloy = 120; short Paperdoll_gump::coords[36] = { 76, 20, /* head */ 115, 27, /* back */ 105, 65, /* belt */ 38, 55, /* lhand */ 55, 62, /* lfinger */ 80, 80, /* legs */ 84, 105, /* feet */ 90, 50, /* rfinger */ 117, 55, /* rhand */ 45, 35, /* torso */ 44, 26, /* neck */ 69, 59, /* ammo */ 59, 19, /* back2 */ 94, 20, /* back 3 (shield) */ 76, 26, /* ears */ 76, 33, /* cloak */ 73, 53, /* gloves */ 0, 0 /* usecode container */ }; short Paperdoll_gump::coords_blue[36] = { 76, 20, /* head */ 64, 27, /* back */ 54, 56, /* belt */ 30, 58, /* lhand */ 55, 62, /* lfinger */ 80, 80, /* legs */ 84, 105, /* feet */ 90, 50, /* rfinger */ 68, 50, /* rhand */ 45, 37, /* torso */ 22, 26, /* neck */ 69, 59, /* ammo */ 59, 19, /* back2 */ 94, 20, /* back 3 (shield) */ 76, 26, /* ears */ 76, 33, /* cloak */ 73, 53, /* gloves */ 0, 0 /* usecode container */ }; short Paperdoll_gump::shapes_blue[36] = { 54, 0, /* head */ 54, 0, /* back */ 54, 0, /* belt */ 55, 0, /* lhand */ 55, 0, /* lfinger */ 54, 0, /* legs */ 54, 0, /* feet */ 54, 0, /* rfinger */ 54, 0, /* rhand */ 55, 0, /* torso */ 54, 0, /* neck */ 54, 0, /* ammo */ 55, 0, /* back2 */ 54, 0, /* back 3 (shield) */ 54, 0, /* ears */ 54, 0, /* cloak */ 54, 0, /* gloves */ 54, 0 /* usecode container */ }; short Paperdoll_gump::coords_hot[36] = { 76, 20, /* head */ 94, 27, /* back */ 92, 61, /* belt */ 38, 55, /* lhand */ 55, 62, /* lfinger */ 80, 80, /* legs */ 84, 105, /* feet */ 90, 50, /* rfinger */ 117, 55, /* rhand */ 83, 43, /* torso */ 76, 41, /* neck */ 69, 59, /* ammo */ 59, 19, /* back2 */ 94, 20, /* back 3 (shield) */ 76, 26, /* ears */ 76, 33, /* cloak */ 73, 53, /* gloves */ 0, 0 /* usecode container */ }; // // Paperdoll Coords // short Paperdoll_gump::bodyx = 46, Paperdoll_gump::bodyy = 33; short Paperdoll_gump::headx = 46, Paperdoll_gump::heady = 22; short Paperdoll_gump::beltfx = 58, Paperdoll_gump::beltfy = 52; short Paperdoll_gump::neckfx = 46, Paperdoll_gump::neckfy = 47; short Paperdoll_gump::beltmx = 57, Paperdoll_gump::beltmy = 55; short Paperdoll_gump::neckmx = 46, Paperdoll_gump::neckmy = 44; short Paperdoll_gump::legsx = 57, Paperdoll_gump::legsy = 66; short Paperdoll_gump::feetx = 46, Paperdoll_gump::feety = 99; short Paperdoll_gump::handsx = 68, Paperdoll_gump::handsy = 44; short Paperdoll_gump::rhandx = 68, Paperdoll_gump::rhandy = 44; short Paperdoll_gump::lhandx = 34, Paperdoll_gump::lhandy = 65; short Paperdoll_gump::ahandx = 28, Paperdoll_gump::ahandy = 59; short Paperdoll_gump::ammox = 28, Paperdoll_gump::ammoy = 59; short Paperdoll_gump::backfx = 68, Paperdoll_gump::backfy = 28; short Paperdoll_gump::back2fx = 34, Paperdoll_gump::back2fy = 22; short Paperdoll_gump::backmx = 68, Paperdoll_gump::backmy = 22; short Paperdoll_gump::back2mx = 35, Paperdoll_gump::back2my = 22; short Paperdoll_gump::shieldfx = 56, Paperdoll_gump::shieldfy = 25; short Paperdoll_gump::shieldmx = 57, Paperdoll_gump::shieldmy = 22; /* * Find the index of the closest 'spot' to a mouse point. * * Output: Index, or -1 if unsuccessful. */ int Paperdoll_gump::find_closest ( int mx, int my, // Mouse point in window. int only_empty // Only allow empty spots. ) { mx -= x; my -= y; // Get point rel. to us. long closest_squared = 1000000; // Best distance squared. int closest = -1; // Best index. int spot; for (size_t i = 0; i < sizeof(coords_hot)/(2*sizeof(coords_hot[0])); i++) { if (Game::get_game_type() == BLACK_GATE && i > Actor::shield_spot) continue; spot = i; int dx = mx - coords_hot[spot*2], dy = my - coords_hot[spot*2+1]; long dsquared = dx*dx + dy*dy; // map some SI spots to the BG belt if (GAME_BG && i == Actor::shield_spot) spot = Actor::belt; else if (GAME_BG && i == Actor::back2h_spot) spot = Actor::belt; // Better than prev and free if required.? if (dsquared < closest_squared && !(only_empty && container->get_readied(spot))) { closest_squared = dsquared; closest = spot; } } return (closest); } /* * Create the gump display for an actor. */ Paperdoll_gump::Paperdoll_gump ( Container_game_object *cont, // Container it represents. int initx, int inity, // Coords. on screen. int shnum // Shape #. ) : Gump(cont, initx, inity, 123, SF_PAPERDOL_VGA) { set_object_area(Rectangle(26, 0, 104, 140), 6, 145); // Create Heart button heart_button = new Heart_button(this, heartx, hearty); Actor *actor = (Actor *) cont; // Create Cstats button or Halo and Cmode if (Game::get_game_type() == BLACK_GATE) { if (actor->get_npc_num() == 0) halo_button = new Halo_button(this, halox, haloy, actor); else halo_button = new Halo_button(this, diskx, disky, actor); cmode_button = new Combat_mode_button(this, cmodex, cmodey, actor); cstats_button = NULL; } else { cstats_button = new Cstats_button(this, cstatx, cstaty); halo_button = NULL; cmode_button = NULL; } // If Avatar create Disk Button if (actor->get_npc_num() == 0) disk_button = new Disk_button(this, diskx, disky); else disk_button = NULL; // If Avtar create Combat Button if (actor->get_npc_num() == 0) combat_button = new Combat_button(this, combatx, combaty); else combat_button = NULL; // Put all the objects in the right place for (size_t i = 0; i < sizeof(coords)/2*sizeof(coords[0]); i++) { Game_object *obj = container->get_readied(i); if (obj) set_to_spot(obj, i); } } /* * Delete actor display. */ Paperdoll_gump::~Paperdoll_gump ( ) { if (heart_button) delete heart_button; if (disk_button) delete disk_button; if (combat_button) delete combat_button; if (cstats_button) delete cstats_button; if (halo_button) delete halo_button; if (cmode_button) delete cmode_button; } /* * Is a given screen point on one of our buttons? * * Output: ->button if so. */ Gump_button *Paperdoll_gump::on_button ( int mx, int my // Point in window. ) { Gump_button *btn = Gump::on_button(mx, my); if (btn) return btn; else if (heart_button && heart_button->on_button(mx, my)) return heart_button; else if (disk_button && disk_button->on_button(mx, my)) return disk_button; else if (combat_button && combat_button->on_button(mx, my)) return combat_button; else if (cstats_button && cstats_button->on_button(mx, my)) return cstats_button; else if (halo_button && halo_button->on_button(mx, my)) return halo_button; else if (cmode_button && cmode_button->on_button(mx, my)) return cmode_button; return 0; } /* * Add an object. * * Output: 0 if cannot add it. */ int Paperdoll_gump::add ( Game_object *obj, int mx, int my, // Screen location of mouse. int sx, int sy, // Screen location of obj's hotspot. bool dont_check, // Skip volume check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { Game_object *cont = find_object(mx, my); if (cont && cont->add(obj, false, combine)) return (1); int index = find_closest(mx, my, 1); if (index != -1 && container->add_readied(obj, index)) return (1); if (container->add(obj, dont_check, combine)) return (1); return (0); } /* * Set object's coords. to given spot. */ void Paperdoll_gump::set_to_spot ( Game_object *obj, int index // Spot index. ) { // Get shape. Shape_frame *shape = obj->get_shape(); //if (!shape) // Funny? Try frame 0. // shape = gwin->get_shape(obj->get_shapenum(), 0); if (!shape) return; // Height and width int w = shape->get_width(), h = shape->get_height(); // Set object's position. obj->set_chunk(spotx(index) + shape->get_xleft() - w/2 - object_area.x, spoty(index) + shape->get_yabove() - h/2 - object_area.y); } /* * Paint on screen. */ void Paperdoll_gump::paint ( ) { Game_object *obj; // Paint Objects Rectangle box = object_area; // Paint objects inside. box.shift(x, y); // Set box to screen location. paint_shape(x, y); // Paint red "checkmark". check_button->paint(); // Get the information required about ourself Actor *actor = container->as_actor(); Paperdoll_npc *info = GetCharacterInfo (container->get_shapenum()); if (!info) info = GetCharacterInfo (actor->get_sexed_coloured_shape()); if (!info) info = GetCharacterInfo (actor->get_shape_real()); if (!info && Game::get_game_type() != BLACK_GATE) info = Characters; else if (!info) info = Characters_BG; // Spots that are female/male specific int shieldx, shieldy, back2x, back2y, backx, backy, neckx, necky, beltx, belty; if (info->is_female) // Set the female spots { shieldx = shieldfx; shieldy = shieldfy; back2x = back2fx; back2y = back2fy; backx = backfx; backy = backfy; neckx = neckfx; necky = neckfy; beltx = beltfx; belty = beltfy; } else // Set the male spots { shieldx = shieldmx; shieldy = shieldmy; back2x = back2mx; back2y = back2my; backx = backmx; backy = backmy; neckx = neckmx; necky = neckmy; beltx = beltmx; belty = beltmy; } // Now paint. Order is very specific if (Game::get_game_type() != BLACK_GATE) { paint_object (box, info, Actor::shield_spot,shieldx,shieldy); paint_object (box, info, Actor::back2h_spot, back2x, back2y); paint_object (box, info, Actor::back, backx, backy); paint_object (box, info, Actor::cloak_spot, bodyx, bodyy); paint_body (box, info); paint_object (box, info, Actor::legs, legsx, legsy); paint_object (box, info, Actor::feet, feetx, feety); paint_object (box, info, Actor::ammo, ammox, ammoy); paint_object (box, info, Actor::torso, bodyx, bodyy); paint_belt (box, info); paint_head (box, info); paint_object (box, info, Actor::neck, neckx, necky); paint_object (box, info, Actor::belt, beltx, belty); paint_arms (box, info); paint_object_arms (box, info, Actor::torso, bodyx, bodyy, 1, Actor::torso); paint_object (box, info, Actor::ears_spot, headx, heady); paint_object (box, info, Actor::head, headx, heady); paint_object (box, info, Actor::cloak_spot, bodyx, bodyy, 0, Actor::special_spot); paint_object_arms (box, info, Actor::rfinger, lhandx, lhandy, 0); paint_object_arms (box, info, Actor::lfinger, rhandx, rhandy, 0); paint_object_arms (box, info, Actor::hands2_spot, handsx, handsy, 0); paint_object (box, info, Actor::lhand, lhandx, lhandy); paint_object (box, info, Actor::ammo, ahandx, ahandy, 2, -1, Actor::lhand); paint_object (box, info, Actor::rhand, rhandx, rhandy); // if debugging show usecode container #ifdef SHOW_USECODE_CONTAINER paint_object (box, info, Actor::ucont_spot, 20, 20 ); #endif } else { Paperdoll_item *item1, *item2; paint_object (box, info, Actor::belt, shieldx,shieldy, 0, Actor::shield_spot); paint_object (box, info, Actor::belt, back2x, back2y, 0, Actor::back2h_spot); paint_object (box, info, Actor::back, backx, backy); paint_object (box, info, Actor::neck, bodyx, bodyy, 0, Actor::cloak_spot); paint_body (box, info); paint_object (box, info, Actor::legs, legsx, legsy); paint_object (box, info, Actor::feet, feetx, feety); paint_object (box, info, Actor::ammo, ammox, ammoy); paint_object (box, info, Actor::torso, bodyx, bodyy); paint_belt (box, info); paint_head (box, info); obj = container->get_readied(Actor::neck); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::cloak_spot); item2 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::special_spot); if (!item1 && !item2) paint_object (box, info, Actor::neck, neckx, necky); obj = container->get_readied(Actor::belt); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::shield_spot); item2 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::back2h_spot); if (!item1 && !item2) paint_object (box, info, Actor::belt, beltx, belty); paint_arms (box, info); paint_object_arms (box, info, Actor::torso, bodyx, bodyy, 1, Actor::torso); paint_object (box, info, Actor::head, headx, heady); paint_object (box, info, Actor::neck, bodyx, bodyy, 0, Actor::special_spot); paint_object_arms (box, info, Actor::rfinger, lhandx, lhandy, 0); obj = container->get_readied(Actor::lfinger); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::hands2_spot); if (!item1) paint_object_arms (box, info, Actor::lfinger, rhandx, rhandy, 0); else paint_object_arms (box, info, Actor::lfinger, handsx, handsy, 0, Actor::hands2_spot); paint_object (box, info, Actor::lhand, lhandx, lhandy); paint_object (box, info, Actor::ammo, ahandx, ahandy, 2, -1, Actor::lhand); paint_object (box, info, Actor::rhand, rhandx, rhandy); } #ifdef SHOW_NONREADIED_OBJECTS Object_iterator iter(container->get_objects()); while ((obj = iter.get_next()) != 0) if (actor->find_readied(obj) == -1) obj->paint(box.x, box.y); #endif // Paint buttons. if (heart_button) heart_button->paint(); if (disk_button) disk_button->paint(); if (combat_button) combat_button->paint(); if (cstats_button) cstats_button->paint(); if (halo_button) halo_button->paint(); if (cmode_button) cmode_button->paint(); // Show weight. int max_weight = container->get_max_weight(); int weight = container->get_weight()/10; char text[20]; snprintf(text, 20, "%d/%d", weight, max_weight); int twidth = sman->get_text_width(2, text); const int boxw = 102; sman->paint_text(2, text, x + 84 - (twidth/2), y + 114); } /* * Paint a generic object on screen */ void Paperdoll_gump::paint_object ( const Rectangle &box, // box Paperdoll_npc *info, // info int spot, // Actor::belt int sx, int sy, // back2x, back2y int frame, // 0 int itemtype, // Actor::back2h_spot int checkspot, // -1 int checktype // -1 ) { Game_object *obj = container->get_readied(spot); if (!obj) return; int old_it = itemtype; if (itemtype == -1) itemtype = spot; Paperdoll_item *item = GetItemInfo (obj->get_shapenum(), obj->get_framenum(), itemtype); if (!item || item->frame == -1 || item->shape == -1) { if ((old_it != -1 && !item)|| checkspot != -1) return; //if (!obj->get_cx() && !obj->get_cy()) return; set_to_spot(obj, spot); ShapeID s(shapes_blue[spot*2], shapes_blue[spot*2+1], SF_GUMPS_VGA); if (Game::get_game_type() == BLACK_GATE) s.set_file(SF_BG_SIGUMP_FLX); s.paint_shape(box.x + coords_blue[spot*2], box.y + coords_blue[spot*2+1]); int ox = box.x + obj->get_cx(), oy = box.y + obj->get_cy(); obj->paint_shape(ox, oy); if (cheat.is_selected(obj)) // Outline selected obj. obj->ShapeID::paint_outline(ox, oy, HIT_PIXEL); return; } else if (checkspot != -1) { Game_object *check = container->get_readied(checkspot); if (!check) return; if (checktype == -1) checktype = checkspot; Paperdoll_item *item_check = GetItemInfo (check->get_shapenum(), check->get_framenum(), checktype); if (!item_check || item_check->type != item->type) return; } int f = item->frame; if (frame == 1) f = item->frame2; else if (frame == 2) f = item->frame3; else if (frame == 3) f = item->frame4; if (item->gender && !info->is_female) f++; ShapeID s(item->shape, f, item->file); s.paint_shape(box.x + sx, box.y + sy, 1); if (cheat.is_selected(obj)) // Outline selected obj. s.paint_outline(box.x + sx, box.y + sy, HIT_PIXEL); } /* * Paint with arms frame */ void Paperdoll_gump::paint_object_arms ( const Rectangle &box, Paperdoll_npc *info, int spot, int sx, int sy, int start, int itemtype ) { switch (get_arm_type()) { default: paint_object (box, info, spot, sx, sy, start, itemtype); break; case OT_Double: paint_object (box, info, spot, sx, sy, start+1, itemtype); break; case OT_Staff: paint_object (box, info, spot, sx, sy, start+2, itemtype); break; } } /* * Paint the body */ void Paperdoll_gump::paint_body ( const Rectangle &box, Paperdoll_npc *info ) { ShapeID s(info->body_shape, info->body_frame, SF_PAPERDOL_VGA); s.paint_shape(box.x + bodyx, box.y + bodyy); } /* * Paint the belt */ void Paperdoll_gump::paint_belt ( const Rectangle &box, Paperdoll_npc *info ) { ShapeID s(10, 0, SF_PAPERDOL_VGA); if (!info->is_female) s.set_frame(1); s.paint_shape (box.x + beltmx, box.y + beltmy); } /* * Paint the head */ void Paperdoll_gump::paint_head ( const Rectangle &box, Paperdoll_npc *info ) { Game_object *obj = container->get_readied(Actor::head); Paperdoll_item *item = NULL; if (obj) item = GetItemInfo (obj->get_shapenum(), obj->get_framenum()); int f = info->head_frame; if (item && item->type == OT_Helm) f = info->head_frame_helm; ShapeID s(info->head_shape, f, info->file); s.paint_shape(box.x + headx, box.y + heady); } /* * Paint the arms */ void Paperdoll_gump::paint_arms ( const Rectangle &box, Paperdoll_npc *info ) { Game_object *obj = container->get_readied(Actor::rhand); Paperdoll_item *item = NULL; if (obj) item = GetItemInfo (obj->get_shapenum(), obj->get_framenum()); ShapeID s(info->arms_shape, info->arms_frame, SF_PAPERDOL_VGA); switch (get_arm_type()) { case OT_Double: s.set_frame(info->arms_frame_2h); break; case OT_Staff: s.set_frame(info->arms_frame_staff); break; default: break; } s.paint_shape (box.x + bodyx, box.y + bodyy); } /* * Gets which arm frame to use */ Paperdoll_gump::Object_type Paperdoll_gump::get_arm_type(void) { Game_object *obj = container->get_readied(Actor::lhand); if (!obj) return OT_Normal; Paperdoll_item *item = GetItemInfo (obj->get_shapenum(), obj->get_framenum()); if (item) return item->type; return OT_Normal; } /* * Find object a screen point is on. * * Output: Object found, or null. */ Game_object * Paperdoll_gump::find_object ( int mx, int my // Mouse pos. on screen. ) { // Check Objects Rectangle box = object_area; // Paint objects inside. box.shift(x, y); // Set box to screen location. mx -= box.x; my -= box.y; // Get the information required about ourself Actor *actor = container->as_actor(); Paperdoll_npc *info = GetCharacterInfo (container->get_shapenum()); if (!info) info = GetCharacterInfo (actor->get_sexed_coloured_shape()); if (!info) info = GetCharacterInfo (actor->get_shape_real()); if (!info && Game::get_game_type() != BLACK_GATE) info = Characters; else if (!info) info = Characters_BG; int shieldx, shieldy, back2x, back2y, backx, backy, neckx, necky, beltx, belty; if (info->is_female) { shieldx = shieldfx; shieldy = shieldfy; back2x = back2fx; back2y = back2fy; backx = backfx; backy = backfy; neckx = neckfx; necky = neckfy; beltx = beltfx; belty = beltfy; } else { shieldx = shieldmx; shieldy = shieldmy; back2x = back2mx; back2y = back2my; backx = backmx; backy = backmy; neckx = neckmx; necky = neckmy; beltx = beltmx; belty = beltmy; } Game_object *obj; // Must be done in this order (reverse of rendering) if (Game::get_game_type() != BLACK_GATE) { // if debugging show usecode container #ifdef SHOW_USECODE_CONTAINER if (obj = check_object (mx, my, info, Actor::ucont_spot, 20, 20 )) return obj; #endif if ((obj = check_object (mx, my, info, Actor::rhand, rhandx, rhandy))) return obj; if ((obj = check_object (mx, my, info, Actor::ammo, ahandx, ahandy, 2, -1, Actor::lhand))) return obj; if ((obj = check_object (mx, my, info, Actor::lhand, lhandx, lhandy))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::hands2_spot, handsx, handsy, 0))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::rfinger, lhandx, lhandy, 0))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::lfinger, rhandx, rhandy, 0))) return obj; if ((obj = check_object (mx, my, info, Actor::cloak_spot, bodyx, bodyy, 0, Actor::special_spot))) return obj; if ((obj = check_object (mx, my, info, Actor::head, headx, heady))) return obj; if ((obj = check_object (mx, my, info, Actor::ears_spot, headx, heady))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::torso, bodyx, bodyy, 1, Actor::torso))) return obj; if (check_arms (mx, my, info)) return NULL; if ((obj = check_object (mx, my, info, Actor::belt, beltx, belty))) return obj; if ((obj = check_object (mx, my, info, Actor::neck, neckx, necky))) return obj; if (check_head (mx, my, info)) return NULL; if (check_belt (mx, my, info)) return NULL; if ((obj = check_object (mx, my, info, Actor::torso, bodyx, bodyy))) return obj; if ((obj = check_object (mx, my, info, Actor::ammo, ammox, ammoy))) return obj; if ((obj = check_object (mx, my, info, Actor::feet, feetx, feety))) return obj; if ((obj = check_object (mx, my, info, Actor::legs, legsx, legsy))) return obj; if (check_body (mx, my, info)) return NULL; if ((obj = check_object (mx, my, info, Actor::cloak_spot, bodyx, bodyy))) return obj; if ((obj = check_object (mx, my, info, Actor::back, backx, backy))) return obj; if ((obj = check_object (mx, my, info, Actor::back2h_spot, back2x, back2y))) return obj; if ((obj = check_object (mx, my, info, Actor::shield_spot,shieldx,shieldy))) return obj; } else { Paperdoll_item *item1, *item2; if ((obj = check_object (mx, my, info, Actor::rhand, rhandx, rhandy))) return obj; if ((obj = check_object (mx, my, info, Actor::ammo, ahandx, ahandy, 2, -1, Actor::lhand))) return obj; if ((obj = check_object (mx, my, info, Actor::lhand, lhandx, lhandy))) return obj; obj = container->get_readied(Actor::lfinger); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::hands2_spot); if (!item1 && (obj = check_object_arms (mx, my, info, Actor::lfinger, rhandx, rhandy, 0))) return obj; else if ((obj = check_object_arms (mx, my, info, Actor::lfinger, rhandx, rhandy, 0, Actor::hands2_spot))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::rfinger, lhandx, lhandy, 0))) return obj; if ((obj = check_object (mx, my, info, Actor::neck, bodyx, bodyy, 0, Actor::special_spot))) return obj; if ((obj = check_object (mx, my, info, Actor::head, headx, heady))) return obj; if ((obj = check_object_arms (mx, my, info, Actor::torso, bodyx, bodyy, 1, Actor::torso))) return obj; if (check_arms (mx, my, info)) return NULL; obj = container->get_readied(Actor::belt); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::shield_spot); item2 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::back2h_spot); if (!item1 && !item2 && (obj = check_object (mx, my, info, Actor::belt, beltx, belty))) return obj; obj = container->get_readied(Actor::neck); item1 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::cloak_spot); item2 = !obj?NULL:GetItemInfo (obj->get_shapenum(), obj->get_framenum(), Actor::special_spot); if (!item1 && !item2 && (obj = check_object (mx, my, info, Actor::neck, neckx, necky))) return obj; if (check_head (mx, my, info)) return NULL; if (check_belt (mx, my, info)) return NULL; if ((obj = check_object (mx, my, info, Actor::torso, bodyx, bodyy))) return obj; if ((obj = check_object (mx, my, info, Actor::ammo, ammox, ammoy))) return obj; if ((obj = check_object (mx, my, info, Actor::feet, feetx, feety))) return obj; if ((obj = check_object (mx, my, info, Actor::legs, legsx, legsy))) return obj; if (check_body (mx, my, info)) return NULL; if ((obj = check_object (mx, my, info, Actor::neck, bodyx, bodyy, 0, Actor::cloak_spot))) return obj; if ((obj = check_object (mx, my, info, Actor::back, backx, backy))) return obj; if ((obj = check_object (mx, my, info, Actor::belt, back2x, back2y, 0, Actor::back2h_spot))) return obj; if ((obj = check_object (mx, my, info, Actor::belt, shieldx,shieldy, 0, Actor::shield_spot))) return obj; } return NULL; } /* * Checks for a generic object on screen */ Game_object * Paperdoll_gump::check_object ( int mx, int my, Paperdoll_npc *info, int spot, int sx, int sy, int frame, int itemtype, int checkspot, int checktype ) { Game_object *obj = container->get_readied(spot); if (!obj) return NULL; int old_it = itemtype; if (itemtype == -1) itemtype = spot; Paperdoll_item *item = GetItemInfo (obj->get_shapenum(), obj->get_framenum(), itemtype); if (!item || item->frame == -1 || item->shape == -1) { if ((old_it != -1 &&!item) || checkspot != -1) return 0; if (!obj->get_cx() && !obj->get_cy()) set_to_spot(obj, spot); if (check_shape (mx - obj->get_cx(), my - obj->get_cy(), obj->get_shapenum(), obj->get_framenum(), obj->get_shapefile())) { return obj; } return NULL; } else if (checkspot != -1) { Game_object *check = container->get_readied(checkspot); if (!check) return NULL; if (checktype == -1) checktype = checkspot; Paperdoll_item *item_check = GetItemInfo (check->get_shapenum(), check->get_framenum(), checktype); if (!item_check || item_check->type != item->type) return NULL; } int f = item->frame; if (frame == 1) f = item->frame2; else if (frame == 2) f = item->frame3; else if (frame == 3) f = item->frame4; if (item->gender && !info->is_female) f++; if (check_shape (mx - sx, my - sy, item->shape, f, item->file)) { Shape_frame *shape = obj->get_shape(); int w = shape->get_width(), h = shape->get_height(); // Set object's position. obj->set_chunk(mx + shape->get_xleft() - w/2, my + shape->get_yabove() - h/2); return obj; } return NULL; } /* * Checks for object with arms frame */ Game_object * Paperdoll_gump::check_object_arms ( int mx, int my, Paperdoll_npc *info, int spot, int sx, int sy, int start, int itemtype ) { switch (get_arm_type()) { default: return check_object (mx, my, info, spot, sx, sy, start, itemtype); case OT_Double: return check_object (mx, my, info, spot, sx, sy, start+1, itemtype); case OT_Staff: return check_object (mx, my, info, spot, sx, sy, start+2, itemtype); } return NULL; } /* * Checks for the body */ bool Paperdoll_gump::check_body ( int mx, int my, Paperdoll_npc *info ) { return check_shape (mx - bodyx, my - bodyy, info->body_shape, info->body_frame, SF_PAPERDOL_VGA); } /* * Checks for the belt */ bool Paperdoll_gump::check_belt ( int mx, int my, Paperdoll_npc *info ) { if (info->is_female) return check_shape (mx - beltfx, my - beltfy, 10, 0, SF_PAPERDOL_VGA); else return check_shape (mx - beltmx, my - beltmy, 10, 1, SF_PAPERDOL_VGA); return false; } /* * Checks for the head */ bool Paperdoll_gump::check_head ( int mx, int my, Paperdoll_npc *info ) { Game_object *obj = container->get_readied(Actor::head); Paperdoll_item *item = NULL; if (obj) item = GetItemInfo (obj->get_shapenum(), obj->get_framenum()); int f = info->head_frame; if (item && item->type == OT_Helm) f = info->head_frame_helm; return check_shape (mx - headx, my - heady, info->head_shape, f, info->file); } /* * Checks for the arms */ bool Paperdoll_gump::check_arms ( int mx, int my, Paperdoll_npc *info ) { Game_object *obj = container->get_readied(Actor::rhand); Paperdoll_item *item = NULL; if (obj) item = GetItemInfo (obj->get_shapenum(), obj->get_framenum()); switch (get_arm_type()) { default: return check_shape (mx - bodyx, my - bodyy, info->arms_shape, info->arms_frame, SF_PAPERDOL_VGA); case OT_Double: return check_shape (mx - bodyx, my - bodyy, info->arms_shape, info->arms_frame_2h, SF_PAPERDOL_VGA); case OT_Staff: return check_shape (mx - bodyx, my - bodyy, info->arms_shape, info->arms_frame_staff, SF_PAPERDOL_VGA); } return false; } /* * Generic Shaper checking */ bool Paperdoll_gump::check_shape ( int px, int py, int shape, int frame, ShapeFile file ) { ShapeID sid(shape, frame, file); Shape_frame *s = sid.get_shape(); // If no shape, return if (!s) return false; Rectangle r = gwin->get_shape_rect (s, 0, 0); // If point not in rectangle, return if (!r.has_point (px, py)) return false; // If point not in shape, return if (!s->has_point (px, py)) return false; return true; } Container_game_object *Paperdoll_gump::find_actor(int mx, int my) { return container; } exult-1.2/gumps/AudioOptions_gump.h0000644000175000001440000000316110012472623013141 /* Copyright (C) 2003-2004 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _AUDIOOPTIONS_GUMP_H #define _AUDIOOPTIONS_GUMP_H #include "Modal_gump.h" class Gump_button; class AudioOptions_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(AudioOptions_gump,Modal_gump(0,0,0,0)); private: Gump_button* buttons[12]; int audio_enabled; int midi_enabled; int midi_conversion; int midi_driver; int midi_reverb_chorus; int midi_looping; int sfx_enabled; int sfx_conversion; int speech_enabled; public: AudioOptions_gump(); ~AudioOptions_gump(); // Paint it and its contents. virtual void paint(); virtual void close(); // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); void toggle(Gump_button* btn, int state); void rebuild_buttons(); void rebuild_midi_buttons(); void rebuild_mididriveroption_buttons(); void rebuild_sfx_buttons(); void load_settings(); void save_settings(); void cancel(); }; #endif exult-1.2/gumps/VideoOptions_gump.cc0000644000175000001440000001563107724430451013322 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "SDL_events.h" #include "Configuration.h" #include "Gump_button.h" #include "Gump_ToggleButton.h" #include "VideoOptions_gump.h" #include "exult.h" #include "exult_flx.h" #include "gamewin.h" #include "gameclk.h" #include "mouse.h" #include "Text_button.h" #include "palette.h" using std::cerr; using std::endl; using std::string; static const int rowy[] = { 5, 20, 35, 50, 80 }; static const int colx[] = { 35, 50, 115, 127, 130 }; static const char* oktext = "OK"; static const char* canceltext = "CANCEL"; static int resolutions[] = { 320, 200, 320, 240, 400, 300, 512, 384, 640, 480, 800, 600, -1, -1 }; // These -1's are placeholders for a custom resolution static int num_default_res = sizeof(resolutions)/(2*sizeof(resolutions[0])) -1; static string resolutionstring(int w, int h) { char buf[100]; sprintf(buf, "%ix%i", w, h); return buf; } class VideoOptions_button : public Text_button { public: VideoOptions_button(Gump *par, string text, int px, int py) : Text_button(par, text, px, py, 59, 11) { } // What to do when 'clicked': virtual void activate(); }; void VideoOptions_button::activate() { if (text == canceltext) { ((VideoOptions_gump*)parent)->cancel(); } else if (text == oktext) { ((VideoOptions_gump*)parent)->close(); } } class VideoTextToggle : public Gump_ToggleTextButton { public: VideoTextToggle(Gump* par, std::string *s, int px, int py, int width, int selectionnum, int numsel) : Gump_ToggleTextButton(par, s, selectionnum, numsel, px, py, width) {} friend class VideoOptions_gump; virtual void toggle(int state) { ((VideoOptions_gump*)parent)->toggle((Gump_button*)this, state); } }; void VideoOptions_gump::close() { save_settings(); // have to repaint everything in case resolution changed gwin->set_all_dirty(); done = 1; } void VideoOptions_gump::cancel() { done = 1; } void VideoOptions_gump::toggle(Gump_button* btn, int state) { if(btn==buttons[0]) resolution = state; else if(btn==buttons[1]) scaling = state; else if(btn==buttons[2]) scaler = state; else if(btn==buttons[3]) fullscreen = state; } void VideoOptions_gump::build_buttons() { // the text arrays are freed by the destructors of the buttons buttons[0] = new VideoTextToggle (this, restext, colx[4], rowy[0], 59, resolution, num_resolutions); std::string *scalingtext = new std::string[2]; scalingtext[0] = "x1"; scalingtext[1] = "x2"; buttons[1] = new VideoTextToggle (this, scalingtext, colx[4], rowy[1], 59, scaling, 2); std::string *enabledtext = new std::string[2]; enabledtext[0] = "Disabled"; enabledtext[1] = "Enabled"; buttons[3] = new VideoTextToggle (this, enabledtext, colx[4], rowy[3], 59, fullscreen, 2); std::string *scalers = new std::string[Image_window::NumScalers]; for (int i = 0; i < Image_window::NumScalers; i++) scalers[i] = Image_window::get_name_for_scaler(i); buttons[2] = new VideoTextToggle (this, scalers, colx[2], rowy[2], 74, scaler, Image_window::NumScalers); } void VideoOptions_gump::load_settings() { int w = gwin->get_width(); int h = gwin->get_height(); resolutions[2*num_default_res] = w; resolutions[2*num_default_res+1] = h; num_resolutions = num_default_res; resolution = -1; int i; for (i = 0; i < num_default_res; i++) { if (resolutions[2*i] == w && resolutions[2*i+1] == h) { resolution = i; break; } } if (resolution == -1) { num_resolutions++; resolution = num_default_res; } restext = new std::string[num_resolutions]; for (i = 0; i < num_resolutions; i++) { restext[i] = resolutionstring(resolutions[2*i], resolutions[2*i+1]); } old_resolution = resolution; scaling = gwin->get_win()->get_scale()-1; scaler = gwin->get_win()->get_scaler(); fullscreen = gwin->get_win()->is_fullscreen()?1:0; gclock->set_palette(); } VideoOptions_gump::VideoOptions_gump() : Modal_gump(0, EXULT_FLX_VIDEOOPTIONS_SHP, SF_EXULT_FLX) { set_object_area(Rectangle(0,0,0,0), 8, 95);//++++++ ??? for (int i=0; i<10; i++) buttons[i] = 0; load_settings(); build_buttons(); // Ok buttons[8] = new VideoOptions_button(this, oktext, colx[0], rowy[4]); // Cancel buttons[9] = new VideoOptions_button(this, canceltext, colx[4], rowy[4]); } VideoOptions_gump::~VideoOptions_gump() { for (int i=0; i<10; i++) if (buttons[i]) delete buttons[i]; } void VideoOptions_gump::save_settings() { int resx = resolutions[2*resolution]; int resy = resolutions[2*resolution+1]; config->set("config/video/width", resx, true); config->set("config/video/height", resy, true); config->set("config/video/scale", scaling+1, true); if (scaler > Image_window::NoScaler && scaler < Image_window::NumScalers) config->set("config/video/scale_method",Image_window::get_name_for_scaler(scaler),true); config->set("config/video/fullscreen", fullscreen ? "yes" : "no", true); gwin->resized(resx,resy,scaling+1,scaler); if(((fullscreen==0)&&(gwin->get_win()->is_fullscreen()))|| ((fullscreen==1)&&(!gwin->get_win()->is_fullscreen()))) { gwin->get_win()->toggle_fullscreen(); gwin->get_pal()->apply(false); gwin->paint(); } gwin->set_painted(); } void VideoOptions_gump::paint() { Gump::paint(); for (int i=0; i<10; i++) if (buttons[i]) buttons[i]->paint(); sman->paint_text(2, "Resolution:", x + colx[0], y + rowy[0] + 1); sman->paint_text(2, "Scaling:", x + colx[0], y + rowy[1] + 1); sman->paint_text(2, "Scaler:", x + colx[0], y + rowy[2] + 1); sman->paint_text(2, "Full Screen:", x + colx[0], y + rowy[3] + 1); gwin->set_painted(); } void VideoOptions_gump::mouse_down(int mx, int my) { pushed = Gump::on_button(mx, my); // First try checkmark. // Try buttons at bottom. if (!pushed) for (int i=0; i<10; i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } } void VideoOptions_gump::mouse_up(int mx, int my) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) ((Gump_button*)pushed)->activate(); pushed = 0; } } exult-1.2/gumps/Sign_gump.h0000755000175000001440000000225407506441032011435 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SIGN_GUMP_H_ #define _SIGN_GUMP_H_ #include #include "Gump.h" /* * A sign showing runes. */ class Sign_gump : public Gump { UNREPLICATABLE_CLASS(Sign_gump); protected: std::string *lines; // Lines of text. int num_lines; bool serpentine; public: Sign_gump(int shapenum, int nlines); ~Sign_gump(); // Set a line of text. void add_text(int line, const std::string &txt); // Paint it and its contents. virtual void paint(); }; #endif exult-1.2/gumps/Scroll_gump.cc0000755000175000001440000000220507506441032012125 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "game.h" #include "gamewin.h" #include "Scroll_gump.h" /* * Create scroll display. */ Scroll_gump::Scroll_gump ( bool serp ) : Text_gump(game->get_shape("gumps/scroll"), serp) { } /* * Paint scroll. Updates curend. */ void Scroll_gump::paint ( ) { // Paint the gump itself. paint_shape(x, y); curend = paint_page(Rectangle(52, 30, 142, 118), curtop); } exult-1.2/gumps/GameplayOptions_gump.h0000644000175000001440000000313307524010427013642 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GAMEPLAYOPTIONS_GUMP_H #define _GAMEPLAYOPTIONS_GUMP_H #include "Modal_gump.h" #include class Gump_button; class GameplayOptions_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(GameplayOptions_gump,Modal_gump(0,0,0,0)); private: Gump_button* buttons[14]; int facestats; int fastmouse; int mouse3rd; int doubleclick; int rightclick_close; int cheats; int paperdolls; int text_bg; int frames; int doubleright_move; int gumps_pause; std::string* frametext; int num_framerates; public: GameplayOptions_gump(); ~GameplayOptions_gump(); // Paint it and its contents. virtual void paint(); virtual void close(); // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); void toggle(Gump_button* btn, int state); void build_buttons(); void load_settings(); void save_settings(); void cancel(); }; #endif exult-1.2/gumps/File_gump.h0000755000175000001440000000424107724430451011417 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _FILE_GUMP_H_ #define _FILE_GUMP_H_ #include "Modal_gump.h" class Gump_text; /* * The file save/load box: */ class File_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(File_gump,Modal_gump(0,0,0,0)); protected: static short textx, texty; // Where to draw first text field. static short texth; // Distance down to next text field. static short btn_rows[2]; // y-coord of each button row. static short btn_cols[3]; // x-coord of each button column. Gump_text *names[10]; // 10 filename slots. Gump_button *buttons[6]; // 2 rows, 3 cols of buttons. Gump_text *pushed_text; // Text mouse is down on. Gump_text *focus; // Text line that has focus. unsigned char restored; // Set to 1 if we restored a game. public: File_gump(); ~File_gump(); // Find savegame index of text field. int get_save_index(Gump_text *txt); void remove_focus(); // Unfocus text. void load(); // 'Load' was clicked. void save(); // 'Save' was clicked. void quit(); // 'Quit' was clicked. // Handle one of the toggles. int toggle_option(Gump_button *btn); int restored_game() // 1 if user restored. { return restored; } // Paint it and its contents. virtual void paint(); virtual void close() { done = 1; } // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); virtual void text_input(int chr, int unicode); // Character typed. }; #endif exult-1.2/gumps/Gamemenu_gump.cc0000644000175000001440000001173507654663710012447 /* Copyright (C) 2001-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "Gamemenu_gump.h" #include "AudioOptions_gump.h" #include "VideoOptions_gump.h" #include "GameplayOptions_gump.h" #include "CombatOptions_gump.h" #include "Gump_button.h" #include "Yesno_gump.h" #include "gamewin.h" #include "Newfile_gump.h" #include "File_gump.h" #include "mouse.h" #include "exult.h" #include "exult_flx.h" #include "Text_button.h" #include "gameclk.h" #include "Gump_manager.h" #include using std::string; static const int rowy[6] = { 4, 17, 30, 43, 56, 69 }; static const int colx = 31; static const char* loadsavetext = "Load/Save Game"; static const char* videoopttext = "Video Options"; static const char* audioopttext = "Audio Options"; static const char* gameopttext = "Gameplay Options"; static const char *combattext = "Combat Options"; static const char* quitmenutext = "Quit to Menu"; static const char* quittext = "Quit"; class Gamemenu_button : public Text_button { public: Gamemenu_button(Gump *par, string text, int px, int py) : Text_button(par, text, px, py, 108, 11) { } // What to do when 'clicked': virtual void activate(); }; void Gamemenu_button::activate() { if (text == loadsavetext) { ((Gamemenu_gump*)parent)->loadsave(); } else if (text == videoopttext) { ((Gamemenu_gump*)parent)->video_options(); } else if (text == audioopttext) { ((Gamemenu_gump*)parent)->audio_options(); } else if (text == gameopttext) { ((Gamemenu_gump*)parent)->gameplay_options(); } else if (text == combattext) { ((Gamemenu_gump*)parent)->combat_options(); } else if (text == quitmenutext) { ((Gamemenu_gump*)parent)->quit(true); } else if (text == quittext) { ((Gamemenu_gump*)parent)->quit(false); } } Gamemenu_gump::Gamemenu_gump() : Modal_gump(0, EXULT_FLX_GAMEMENU_SHP, SF_EXULT_FLX) { set_object_area(Rectangle(0,0,0,0), 8, 82); //+++++ ??? buttons[0] = new Gamemenu_button(this, loadsavetext, colx, rowy[0]); buttons[1] = new Gamemenu_button(this, videoopttext, colx, rowy[1]); buttons[2] = new Gamemenu_button(this, audioopttext, colx, rowy[2]); buttons[3] = new Gamemenu_button(this, gameopttext, colx, rowy[3]); buttons[4] = new Gamemenu_button(this, combattext, colx, rowy[4]); buttons[5] = new Gamemenu_button(this, quittext, colx, rowy[5]); } Gamemenu_gump::~Gamemenu_gump() { for (int i=0; i<6; i++) delete buttons[i]; } //++++++ IMPLEMENT RETURN_TO_MENU! void Gamemenu_gump::quit(bool return_to_menu) { if (!Yesno_gump::ask("Do you really want to quit?")) return; quitting_time = QUIT_TIME_YES; done = 1; } //+++++ implement actual functionality and option screens void Gamemenu_gump::loadsave() { //File_gump *fileio = new File_gump(); Newfile_gump *fileio = new Newfile_gump(); gumpman->do_modal_gump(fileio, Mouse::hand); if (fileio->restored_game()) done = true; delete fileio; } void Gamemenu_gump::video_options() { VideoOptions_gump *vid_opts = new VideoOptions_gump(); gumpman->do_modal_gump(vid_opts, Mouse::hand); // resolution could have changed, so recenter & repaint menu. set_pos(); gwin->paint(); gwin->show(); delete vid_opts; gclock->set_palette(); } void Gamemenu_gump::audio_options() { AudioOptions_gump *aud_opts = new AudioOptions_gump(); gumpman->do_modal_gump(aud_opts, Mouse::hand); delete aud_opts; } void Gamemenu_gump::gameplay_options() { GameplayOptions_gump *gp_opts = new GameplayOptions_gump(); gumpman->do_modal_gump(gp_opts, Mouse::hand); delete gp_opts; } void Gamemenu_gump::combat_options() { CombatOptions_gump *cbt_opts = new CombatOptions_gump(); gumpman->do_modal_gump(cbt_opts, Mouse::hand); delete cbt_opts; } void Gamemenu_gump::paint() { Gump::paint(); for (int i=0; i<6; i++) if (buttons[i]) buttons[i]->paint(); gwin->set_painted(); } void Gamemenu_gump::mouse_down(int mx, int my) { pushed = Gump::on_button(mx, my); // First try checkmark. // Try buttons at bottom. if (!pushed) for (int i=0; i<6; i++) if (buttons[i] && buttons[i]->on_button(mx, my)) { pushed = buttons[i]; break; } if (pushed) // On a button? { pushed->push(); return; } } void Gamemenu_gump::mouse_up(int mx, int my) { if (pushed) // Pushing a button? { pushed->unpush(); if (pushed->on_button(mx, my)) ((Gamemenu_button*)pushed)->activate(); pushed = 0; } } exult-1.2/gumps/Paperdoll_gump.h0000755000175000001440000001730107506445352012467 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PAPERDOLL_GUMP_H_ #define _PAPERDOLL_GUMP_H_ #include "Gump.h" class Heart_button; class Disk_button; class Combat_button; class Halo_button; class Cstats_button; class Combat_mode_button; // // For best viewing use Tab size = 4 // class Paperdoll_gump : public Gump { public: enum Object_type { OT_Normal = 0, OT_Single = 1, OT_Double = 2, OT_Staff = 3, OT_Bow = 4, OT_Crossbow = 5, OT_Shield = 6, OT_Helm = 7, OT_Musket = 8 }; // This contains info on how to render an item when it's in a certain spot struct Paperdoll_item { int world_shape; // Shape in the world int world_frame; // Frame in the world (-1 for all) int spot; // Spot placed in Object_type type; // What type of object is this bool gender; // Is this object gender specific ShapeFile file; // Which VGA file is the shape in int shape; // The shape (if -1 use world shape and frame) int frame; // The frame int frame2; // Second Frame (if used) int frame3; // Second Frame (if used) int frame4; // Second Frame (if used) }; // This contain Information about NPC rendering struct Paperdoll_npc { int npc_shape; // Choose the NPC based on shape, not NPC number bool is_female; // Is the NPC Female (or more specifically not male) ShapeFile file; // Which VGA file the head shape is in // Body info int body_shape; // Body Shape int body_frame; // Body Frame int head_shape; // Head Shape int head_frame; // Normal Head Frame int head_frame_helm; // Frame when wearing a helm int arms_shape; // Shape for Arms int arms_frame; // Normal Arms Frame int arms_frame_2h; // Frame when holding a two handed weapon int arms_frame_staff; // Frame when holding staff style weapon }; private: UNREPLICATABLE_CLASS(Paperdoll_gump); protected: // Statics // Serpent Isle static Paperdoll_npc Characters[]; // NPC information static Paperdoll_item Items[]; // Item Information // Black Gate (it's a hack I tell you) static Paperdoll_npc Characters_BG[]; // NPC information static Paperdoll_item Items_BG[]; // Item Information static short coords[36]; // Coords. of where to draw things, static short coords_blue[36]; // indexed by spot # (0-17). static short shapes_blue[36]; static short coords_hot[36]; // Hot spots static short diskx, disky; // Where to show 'diskette' button. static short heartx, hearty; // Where to show 'stats' button. static short combatx, combaty; // Combat button. static short cstatx, cstaty; // Combat mode. static short halox, haloy; // "Protected" halo. static short cmodex, cmodey; // Combat mode. static short bodyx, bodyy; // Body static short headx, heady; // Head static short beltfx, beltfy; // Female Belt static short neckfx, neckfy; // Female Neck static short beltmx, beltmy; // Male Belt static short neckmx, neckmy; // Male Neck static short legsx, legsy; // Legs static short feetx, feety; // Feet static short handsx, handsy; // Hands static short lhandx, lhandy; // Left Hand static short rhandx, rhandy; // Right Hand static short ahandx, ahandy; // Ammo in Left Hand static short ammox, ammoy; // Quiver static short backfx, backfy; // Female Back static short backmx, backmy; // Male Back static short back2fx, back2fy; // Female Back Weapon static short back2mx, back2my; // Male Back Weapon static short shieldfx, shieldfy; // Female Back Shield static short shieldmx, shieldmy; // Male Back Shield // Non Statics Heart_button *heart_button; // For bringing up stats. Disk_button *disk_button; // For bringing up 'save' box. (Avatar Only) Combat_button *combat_button; // Combat Toggle (Avatar Only) Cstats_button *cstats_button; // Combat Stats (Not BG) Halo_button *halo_button; // Halo (protection) (BG Only) Combat_mode_button *cmode_button; // Combat Modes (BG Only) // Statics // Get the X and Y from a spot static int spotx(int i) { return coords[2*i]; } static int spoty(int i) { return coords[2*i + 1]; } // Non Statics // Find index of closest spot to the mouse pointer int find_closest(int mx, int my, int only_empty = 0); // Set to location of an object a spot void set_to_spot(Game_object *obj, int index); public: // Statics inline static bool IsObjectAllowed(int shape, int frame, int spot) { return GetItemInfo(shape, frame, spot)!=NULL?true:false; } inline static int GetFaceShape(int shape, int frame, int spot) { return GetItemInfo(shape, frame, spot)!=NULL?true:false; } inline static bool IsNPCFemale(int shape) { return GetCharacterInfo(shape)?GetCharacterInfoSafe(shape)->is_female:true; } // Retrieve info about an item or NPC static Paperdoll_npc *GetCharacterInfoSafe(int shape); static Paperdoll_npc *GetCharacterInfo(int shape); static Paperdoll_item *GetItemInfo(int shape, int frame = -1, int spot = -1); // Non Statics Paperdoll_gump(Container_game_object *cont, int initx, int inity, int shnum); ~Paperdoll_gump(); // Is a given point on a button? virtual Gump_button *on_button(int mx, int my); // Find the object the mouse is over virtual Game_object *find_object(int mx, int my); // Add object. virtual int add(Game_object *obj, int mx = -1, int my = -1, int sx = -1, int sy = -1, bool dont_check = false, bool combine = false); // Paint it and its contents. virtual void paint(); // // Painting Helpers // // Generic Paint Object Method void paint_object(const Rectangle &box, Paperdoll_npc *info, int spot, int sx, int sy, int frame = 0, int itemtype = -1, int checkspot = -1, int checktype = -1); // Generic Paint Object Method for something that is armed dependant void paint_object_arms(const Rectangle &box, Paperdoll_npc *info, int spot, int sx, int sy, int start = 0, int itemtype = -1); // Special 'Constant' Paint Methods void paint_body (const Rectangle &box, Paperdoll_npc *info); void paint_belt (const Rectangle &box, Paperdoll_npc *info); void paint_head (const Rectangle &box, Paperdoll_npc *info); void paint_arms (const Rectangle &box, Paperdoll_npc *info); // What are we holding? Object_type get_arm_type (void); // // Finding Helpers // // Generic Check Object Method Game_object *check_object (int mx, int my, Paperdoll_npc *info, int spot, int sx, int sy, int frame = 0, int itemtype = -1, int checkspot = -1, int checktype = -1); // Generic Check Object Method for something that is armed dependant Game_object *check_object_arms (int mx, int my, Paperdoll_npc *info, int spot, int sx, int sy, int start = 0, int itemtype = -1); // Special 'Constant' Check Methods bool check_body (int mx, int my, Paperdoll_npc *info); bool check_belt (int mx, int my, Paperdoll_npc *info); bool check_head (int mx, int my, Paperdoll_npc *info); bool check_arms (int mx, int my, Paperdoll_npc *info); // Generic Method to check a shape bool check_shape (int px, int py, int shape, int frame, ShapeFile file); virtual Container_game_object *find_actor(int mx, int my); }; #endif exult-1.2/gumps/Gamemenu_gump.h0000644000175000001440000000253307570777434012313 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GAMEMENU_GUMP_H #define _GAMEMENU_GUMP_H #include "Modal_gump.h" class Gump_button; class Gamemenu_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(Gamemenu_gump,Modal_gump(0,0,0,0)); private: Gump_button* buttons[6]; public: Gamemenu_gump(); ~Gamemenu_gump(); // Paint it and its contents. virtual void paint(); virtual void close() { done = 1; } // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); void quit(bool return_to_menu = false); void loadsave(); void video_options(); void audio_options(); void gameplay_options(); void combat_options(); }; #endif exult-1.2/gumps/misc_buttons.h0000755000175000001440000000453307506445352012231 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MISC_BUTTONS_H_ #define _MISC_BUTTONS_H_ #include "Gump_button.h" class Actor; /* * A checkmark for closing its parent: */ class Checkmark_button : public Gump_button { public: Checkmark_button(Gump *par, int px, int py); // What to do when 'clicked': virtual void activate(); }; /* * A 'heart' button for bringing up stats. */ class Heart_button : public Gump_button { public: Heart_button(Gump *par, int px, int py); // What to do when 'clicked': virtual void activate(); }; /* * A diskette for bringing up the 'save' box. */ class Disk_button : public Gump_button { public: Disk_button(Gump *par, int px, int py); // What to do when 'clicked': virtual void activate(); }; /* * The combat toggle button. */ class Combat_button : public Gump_button { public: Combat_button(Gump *par, int px, int py); // What to do when 'clicked': virtual void activate(); virtual void paint(); }; /* * The halo button. */ class Halo_button : public Gump_button { Actor *actor; // Who this represents. public: Halo_button(Gump *par, int px, int py, Actor *a); // What to do when 'clicked': virtual void activate(); }; /* * Combat mode. Has 10 frames corresponding to Actor::Attack_mode. */ class Combat_mode_button : public Gump_button { Actor *actor; // Who this represents. public: Combat_mode_button(Gump *par, int px, int py, Actor *a); // What to do when 'clicked': virtual void activate(); }; /* * The Serpent Isle Combat Stats Button */ class Cstats_button : public Gump_button { public: Cstats_button(Gump *par, int px, int py); // What to do when 'clicked': virtual void activate(); }; #endif exult-1.2/gumps/Gump_button.h0000755000175000001440000000274207506445352012023 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GUMP_BUTTON_H_ #define _GUMP_BUTTON_H_ #include "Gump_widget.h" /* * A pushable button on a gump: */ class Gump_button : public Gump_widget { UNREPLICATABLE_CLASS(Gump_button); protected: unsigned char pushed; // 1 if in pushed state. public: friend class Gump; Gump_button(Gump *par, int shnum, int px, int py, ShapeFile shfile = SF_GUMPS_VGA) : Gump_widget(par, shnum, px, py, shfile), pushed(0) { } // Is a given point on the checkmark? virtual int on_button(int mx, int my) { return on_widget(mx, my); } // What to do when 'clicked': virtual void activate() = 0; // Or double-clicked. virtual void double_clicked(int x, int y); virtual void push(); // Redisplay as pushed. virtual void unpush(); virtual void paint(); }; #endif exult-1.2/gumps/VideoOptions_gump.h0000644000175000001440000000274107506445352013166 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VIDEOOPTIONS_GUMP_H #define _VIDEOOPTIONS_GUMP_H #include "Modal_gump.h" #include class Gump_button; class VideoOptions_gump : public Modal_gump { UNREPLICATABLE_CLASS_I(VideoOptions_gump,Modal_gump(0,0,0,0)); private: Gump_button* buttons[10]; int resolution; int scaling; int scaler; int fullscreen; int old_resolution; std::string *restext; int num_resolutions; public: VideoOptions_gump(); ~VideoOptions_gump(); // Paint it and its contents. virtual void paint(); virtual void close(); // Handle events: virtual void mouse_down(int mx, int my); virtual void mouse_up(int mx, int my); void toggle(Gump_button* btn, int state); void build_buttons(); void load_settings(); void save_settings(); void cancel(); }; #endif exult-1.2/tools/0000777000175000001440000000000010062225326007414 5exult-1.2/tools/ipack.cc0000644000175000001440000005573307743652340010757 /** ** Ipack.cc - Create/extract image Flex files using the .png format. ** ** Written: 2/19/2002 - JSF, with lots of code borrowed from Tristan's * Gimp Plugin. **/ /* * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include #endif #include #include #include #include "Flex.h" #include "utils.h" #include "exceptions.h" #include "vgafile.h" #include "pngio.h" #include "ibuf8.h" using std::atoi; using std::cerr; using std::cout; using std::endl; using std::exit; using std::ifstream; using std::ofstream; using std::istream; using std::ostream; using std::setw; using std::size_t; using std::strlen; using std::strncmp; using std::strcpy; using std::strcat; using std::vector; /* * A shape specification: */ class Shape_spec { public: char *filename; // Should be allocated. int nframes; // # frames in shape. bool flat; // A 'flat' shape. bool bycol; // If dim0_tiles > 0, go down first. int dim0_tiles; // File consists of 8x8 (flat) tiles. public: Shape_spec() : filename(0), nframes(0), flat(false), bycol(false), dim0_tiles(0) { } ~Shape_spec() { delete filename; } }; typedef vector Shape_specs; /* * Skip white space. */ static char *Skip_space ( char *ptr ) { while (isspace(*ptr)) ptr++; return ptr; } /* * Find white space (or null). */ static char *Find_space ( char *ptr ) { while (*ptr && !isspace(*ptr)) ptr++; return ptr; } /* * Pass a filename spec. which can have a "(nnn xxx)" at its end. */ static char *Pass_file_spec ( char *ptr ) { int paren_depth = 0; while (*ptr && (paren_depth > 0 || !isspace(*ptr))) { if (*ptr == '(') paren_depth++; else if (*ptr == ')') paren_depth--; ptr++; } return ptr; } /* * Parse a number, and quit with an error msg. if not found. */ static long Get_number ( int linenum, // For printing errors. char *errmsg, char *ptr, char *& endptr // ->past number and spaces returned. ) { long num = strtol(ptr, &endptr, 0); if (endptr == ptr) // No #? { cerr << "Line " << linenum << ": " << errmsg << endl; exit(1); } endptr = Skip_space(endptr); return num; } /* * Return the next token, or quit with an error. * * Output: ->copy of token. */ static char *Get_token ( int linenum, // For printing errors. char *ptr, // Where to start looking. char *& endptr // ->past token returned. ) { ptr = Skip_space(ptr + 7); endptr = Find_space(ptr); if (endptr == ptr) { cerr << "Line #" << linenum << ": Expecting a name" << endl; exit(1); } char sav = *endptr; *endptr = 0; char *token = newstrdup(ptr); *endptr = sav; return token; } /* * Read in script, with the following format: * Max. text length is 1024. * A line beginning with a '#' is a comment. * 'archive imgfile' specifies name of the image archive. * 'palette palfile' specifies the palette file (which, if a * Flex, contains palette in entry 0). * 'nnn/fff:filename' indicates shape #nnn will consist of fff * frames in files "filename-iii.png", where iii is the * frame #. * 'nnn/fff:filename(cc across)' indicates filename is a .png * consisting of 8x8 flat tiles, to be taken rowwise with * each row having cc columns. * 'nnn/fff:filename(rr down)' indicates filename is a .png * consisting of 8x8 flat tiles, to be taken columnwise * with each column having rr rows. * Filename may be followed by 'flat' to indicate 8x8 non-RLE * shape. */ static void Read_script ( istream& in, char *& imagename, // Archive name returned. char *& palname, // Palette name returned. Shape_specs& specs // Shape specs. returned here. ) { imagename = 0; specs.resize(0); // Initialize. specs.reserve(1200); char buf[1024]; int linenum = 0; while (!in.eof()) { ++linenum; in.get(buf, sizeof(buf)); char delim; // Check for end-of-line. in.get(delim); if (delim != '\n' && !in.eof()) { cerr << "Line #" << linenum << " is too long" << endl; exit(1); } if (!buf[0]) continue; // Empty line. char *ptr = Skip_space(&buf[0]); if (*ptr == '#') continue; // Comment. char *endptr; if (strncmp(ptr, "archive", 7) == 0) { // Archive name. imagename = Get_token(linenum, ptr, endptr); continue; } if (strncmp(ptr, "palette", 7) == 0) { palname = Get_token(linenum, ptr, endptr); continue; } // Get shape# in decimal, hex, or oct. long shnum = Get_number(linenum, "Shape # missing", ptr, endptr); if (*endptr != '/') { cerr << "Line #" << linenum << ": Missing '/' after shape number" << endl; exit(1); } ptr = endptr + 1; long nframes = Get_number(linenum, "Frame count missing", ptr, endptr); if (*endptr != ':') { cerr << "Line #" << linenum << ": Missing ':' after frame count" << endl; exit(1); } ptr = Skip_space(endptr + 1); endptr = Pass_file_spec(ptr); if (endptr == ptr) { cerr << "Line #" << linenum << ": Missing filename" << endl; exit(1); } // Get ->past filename. char *past_end = *endptr ? Skip_space(endptr + 1) : endptr; *endptr = 0; if (shnum >= specs.size()) specs.resize(shnum + 1); specs[shnum].flat = (strncmp(past_end, "flat", 4) == 0); specs[shnum].nframes = nframes; char fname[300], dir[300]; int dim0_cnt; // See if it's a tiles spec. if (sscanf(ptr, "%[^(](%d %s)", &fname[0], &dim0_cnt, &dir[0]) == 3) { if (!specs[shnum].flat) { cerr << "Line #" << linenum << ": Tiled file not specified 'flat'" << endl; exit(1); } specs[shnum].dim0_tiles = dim0_cnt; specs[shnum].bycol = strncmp(dir, "down", 4) == 0; specs[shnum].filename = strdup(fname); } else specs[shnum].filename = strdup(ptr); } } /* * Modify a palette by fixed amounts and/or percentages. */ static void Modify_palette ( unsigned char *from, // Rgb values to start with, // each range 0-255. unsigned char *to, // Result stored here. int palsize, // 0-256. int roff, int goff, int boff, // Add these offsets first. int r256, int g256, int b256 // Modify by x/256. ) { int cnt = 3*palsize; for (int i = 0; i < 3*palsize; ) { int r = from[i] + roff; // First the offsets. // Then percentage. r += (r*r256)/256; if (r < 0) r = 0; if (r > 255) r = 255; to[i++] = r; int g = from[i] + goff; g += (g*g256)/256; if (g < 0) g = 0; if (g > 255) g = 255; to[i++] = g; int b = from[i] + boff; b += (b*b256)/256; if (b < 0) b = 0; if (b > 255) b = 255; to[i++] = b; } } /* * Modify a palette by removing all color. */ static void Greyify_palette ( unsigned char *from, // Rgb values to start with, // each range 0-255. unsigned char *to, // Result stored here. int palsize // 0-256. ) { for (int i = 0; i < palsize; i++) { int ind = i*3; // Take average. int ave = (from[ind] + from[ind + 1] + from[ind + 2])/3; to[ind] = to[ind + 1] = to[ind + 2] = ave; } } /* * Convert a palette to values 0-63. */ static void Convert_palette63 ( unsigned char *from, // 3*palsize, values 0-255. unsigned char *to, // 3*256. Values 0-63 returned, with // colors > palsize 0-filled. int palsize // # entries. ) { int i; // Convert 0-255 to 0-63 for Exult. for (i = 0; i < 3*palsize; i++) to[i] = from[i]/4; memset(to + i, 0, 3*256 - i); // 0-fill the rest. } /* * Write out a palette as text. */ static void Write_text_palette ( char *palname, // Base name. '.txt' is appended. unsigned char *palette, // RGB's, 0-255. int palsize // # colors in palette ) { // Write out as (Gimp) text. char *txtpal = new char[strlen(palname) + 10]; strcpy(txtpal, palname); strcat(txtpal, ".txt"); cout << "Creating text (Gimp) palette '" << txtpal << "'" << endl; ofstream pout(txtpal); // OKAY that it's a 'text' file. pout << "GIMP palette" << endl; // MUST be this for Gimp to use. pout << "Palette from Exult's Ipack" << endl; int i; // Skip 0's at end. for (i = palsize - 1; i > 0; i--) if (palette[3*i] != 0 || palette[3*i+1] != 0 || palette[3*i+2] != 0) break; int last_color = i; for (i = 0; i <= last_color; i++) { int r = palette[3*i], g = palette[3*i + 1], b = palette[3*i + 2]; pout << setw(3) << r << ' ' << setw(3) << g << ' ' << setw(3) << b << endl; } pout.close(); delete txtpal; } const unsigned char transp = 255; // Transparent pixel. /* * Write out one frame as a .png. */ static void Write_frame ( char *basename, // Base filename to write. int frnum, // Frame #. Shape_frame *frame, // What to write. unsigned char *palette // 3*256 bytes. ) { assert(frame != 0); char *fullname = new char[strlen(basename) + 30]; sprintf(fullname, "%s%02d.png", basename, frnum); cout << "Writing " << fullname << endl; int w = frame->get_width(), h = frame->get_height(); Image_buffer8 img(w, h); // Render into a buffer. img.fill8(transp); // Fill with transparent pixel. frame->paint(&img, frame->get_xleft(), frame->get_yabove()); int xoff = 0, yoff = 0; if (frame->is_rle()) { xoff = -frame->get_xright(); yoff = -frame->get_ybelow(); } // Write out to the .png. if (!Export_png8(fullname, transp, w, h, w, xoff, yoff, img.get_bits(), palette, 256, true)) throw file_write_exception(fullname); delete fullname; } /* * Write out all (8x8 flat) frames by tiling them into one file. */ static void Write_tiled_frames ( char *filename, // Filename to write. Shape *shape, // What to write. int shnum, // For printing errors. bool bycol, // If true, go down each column first, // else go across each row first. int dim0_cnt, // If bycol, #rows; else #cols. unsigned char *palette // 3*256 bytes. ) { assert(shape != 0); cout << "Writing " << filename << " tiled" << (bycol ? ", by cols" : ", by rows") << " first" << endl; int nframes = shape->get_num_frames(); // Figure #tiles in other dim. int dim1_cnt = (nframes + dim0_cnt - 1)/dim0_cnt; int w, h; if (bycol) { h = dim0_cnt*8; w = dim1_cnt*8; } else { w = dim0_cnt*8; h = dim1_cnt*8; } Image_buffer8 img(w, h); img.fill8(transp); // Fill with transparent pixel. for (int f = 0; f < nframes; f++) { Shape_frame *frame = shape->get_frame(f); if (!frame) continue; // We'll just leave empty ones blank. if (!frame->is_rle() || frame->get_width() != 8 || frame->get_height() != 8) { cerr << "Can only tile 8x8 flat shapes, but shape " << shnum << " doesn't qualify" << endl; exit(1); } int x, y; if (bycol) { y = f%dim0_cnt; x = f/dim0_cnt; } else { x = f%dim0_cnt; y = f/dim0_cnt; } frame->paint(&img, x*8 + frame->get_xleft(), y*8 + frame->get_yabove()); } // Write out to the .png. if (!Export_png8(filename, transp, w, h, w, 0, 0, img.get_bits(), palette, 256)) throw file_write_exception(filename); } /* * Write out palettes. The first is the one given, and the rest are * automatically generated to work with the Exult engine (see * palettes.h for definitions). */ void Write_palettes ( char *palname, unsigned char *palette, // 3 bytes for each color. int palsize // # entries. ) { cout << "Creating new palette file '" << palname << "' using first file's palette" << endl; unsigned char palbuf[3*256]; // We always write 256 colors. if (palsize > 256) // Shouldn't happen. palsize = 256; ofstream out; U7open(out, palname); // May throw exception. Flex_writer writer(out, "Exult palette by Ipack", 11); // Entry 0 (DAY): Convert_palette63(palette, &palbuf[0], palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 1 (DUSK): Modify_palette(palette, palbuf, palsize, 0, 0, 0, -64, -64, -64); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 2 (NIGHT): Modify_palette(palette, palbuf, palsize, 0, 0, 0, -128, -128, -128); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 3 (INVISIBLE): Greyify_palette(palette, palbuf, palsize); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 4 (unknown): Convert_palette63(palette, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 5 (HAZE): Modify_palette(palette, palbuf, palsize, 184, 184, 184, -32, -32, -32); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 6 (a bit brighter than 2): Modify_palette(palette, palbuf, palsize, 0, 0, 0, -96, -96, -96); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 7 (a bit warmer): Modify_palette(palette, palbuf, palsize, 30, 0, 0, -96, -96, -96); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 8 (hit in combat): Modify_palette(palette, palbuf, palsize, 64, 0, 0, 384, -20, -20); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 9 (unknown): Convert_palette63(palette, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); // Entry 10 (LIGHTNING): Modify_palette(palette, palbuf, palsize, 32, 32, 0, 256, 256, -20); Convert_palette63(palbuf, palbuf, palsize); out.write((const char*)&palbuf[0], sizeof(palbuf)); writer.mark_section_done(); if (!writer.close()) throw file_write_exception(palname); // Write out in Gimp format. Write_text_palette(palname, palette, palsize); } /* * Write tiles from a single input file to and Exult image file. */ static void Write_exult_from_tiles ( ostream& out, // What to write to. char *filename, // Filename to read. int nframes, // # frames. bool bycol, // If true, go down each column first, // else go across each row first. int dim0_cnt, // If bycol, #rows; else #cols. char *palname // Store palette here if !0. ) { cout << "Reading " << filename << " tiled" << (bycol ? ", by cols" : ", by rows") << " first" << endl; // Figure #tiles in other dim. int dim1_cnt = (nframes + dim0_cnt - 1)/dim0_cnt; int needw, needh; // Figure min. image dims. if (bycol) { needh = dim0_cnt*8; needw = dim1_cnt*8; } else { needw = dim0_cnt*8; needh = dim1_cnt*8; } // Save starting position. unsigned long startpos = out.tellp(); int w, h, rowsize, xoff, yoff, palsize; unsigned char *pixels, *palette; // Import, with 255 = transp. index. if (!Import_png8(filename, 255, w, h, rowsize, xoff, yoff, pixels, palette, palsize)) throw file_read_exception(filename); if (w < needw || h < needh) { cerr << "File " << filename << " image is too small. " << needw << 'x' << needh << " required" << endl; exit(1); } for (int frnum = 0; frnum < nframes; frnum++) { int x, y; if (bycol) { y = frnum%dim0_cnt; x = frnum/dim0_cnt; } else { x = frnum%dim0_cnt; y = frnum/dim0_cnt; } unsigned char *src = pixels + w*8*y + 8*x; for (int row = 0; row < 8; row++) { // Write it out. out.write(reinterpret_cast(src), 8); src += w; } } delete pixels; if (palname) Write_palettes(palname, palette, palsize); delete palette; } /* * Write a shape's frames to an Exult image file. */ static void Write_exult ( ostream& out, // What to write to. char *basename, // Base filename for files to read. int nframes, // # frames. bool flat, // Store as 8x8 flats. char *palname // Store palette with here if !0. ) { Shape shape(nframes); char *fullname = new char[strlen(basename) + 30]; int frnum; // Read in frames. for (frnum = 0; frnum < nframes; frnum++) { sprintf(fullname, "%s%02d.png", basename, frnum); cout << "Reading " << fullname << endl; int w, h, rowsize, xoff, yoff, palsize; unsigned char *pixels, *palette; // Import, with 255 = transp. index. if (!Import_png8(fullname, 255, w, h, rowsize, xoff, yoff, pixels, palette, palsize)) throw file_read_exception(fullname); int xleft, yabove; if (flat) { xleft = yabove = 8; if (w != 8 || h != 8 || rowsize != 8) { cerr << "Image in '" << fullname << "' is not flat" << endl; exit(1); } } else // RLE. xoff,yoff are neg. from bottom. { xleft = w + xoff - 1; yabove = h + yoff - 1; } shape.set_frame(new Shape_frame(pixels, w, h, xleft, yabove, !flat), frnum); delete pixels; if (palname) // Write palette for first frame. { Write_palettes(palname, palette, palsize); palname = 0; } delete palette; } shape.write(out); // Write them out. delete fullname; } /* * Create an archive from a set of image files. May throw an exception. */ static void Create ( char *imagename, // Image archive name. char *palname, // Palettes file (palettes.flx). Shape_specs& specs, // List of things to extract. const char *title // For storing in Flex file. ) { if (palname && U7exists(palname)) // Palette? { cout << "Palette file '" << palname << "' exists, so we won't overwrite it" << endl; palname = 0; } ofstream out; U7open(out, imagename); // May throw exception. Flex_writer writer(out, title, specs.size()); for (Shape_specs::const_iterator it = specs.begin(); it != specs.end(); ++it) { int shnum = it - specs.begin(); char *basename = (*it).filename; if (basename) // Not empty? { int dim0_cnt = (*it).dim0_tiles; if (dim0_cnt > 0) Write_exult_from_tiles(out, basename, (*it).nframes, (*it).bycol, (*it).dim0_tiles, palname); else Write_exult(out, basename, (*it).nframes, (*it).flat, palname); palname = 0; // Only write 1st palette. } writer.mark_section_done(); } if (!writer.close()) throw file_write_exception(imagename); } /* * Update an archive with a set of image files. May throw an exception. * The archive is rewritten with its original shapes, plus those * specified in the script. */ static void Update ( char *imagename, // Image archive name. char *palname, // Palettes file (palettes.flx). Shape_specs& specs, // List of things to extract. const char *title // For storing in Flex file. ) { if (palname && U7exists(palname)) // Palette? { cout << "Palette file '" << palname << "' exists, so we won't overwrite it" << endl; palname = 0; } Flex in(imagename); // May throw exception. int oldcnt = in.number_of_objects(); vector data(oldcnt); // Read in all the entries. vector lengths(oldcnt); int i; for (i = 0; i < oldcnt; i++) { size_t len; data[i] = in.retrieve(i, len); lengths[i] = len; if (!len) // Empty? { delete data[i]; data[i] = 0; } } ofstream out; U7open(out, imagename); // May throw exception. int newcnt = oldcnt > specs.size() ? oldcnt : specs.size(); Flex_writer writer(out, title, newcnt); for (i = 0; i < newcnt; i++) // Write out new entries. { // New entry for this shape? if (i < specs.size() && specs[i].filename != 0) { Write_exult(out, specs[i].filename, specs[i].nframes, specs[i].flat, palname); palname = 0; // Only write 1st palette. } // Write old entry. else if (i < oldcnt && data[i]) out.write(data[i], lengths[i]); writer.mark_section_done(); } if (!writer.close()) throw file_write_exception(imagename); for (i = 0; i < oldcnt; i++) // Clean up. delete data[i]; } /* * Extract from the archive. May throw an exception. */ static void Extract ( char *imagename, // Image archive name. char *palname, // Palettes file (palettes.flx). Shape_specs& specs // List of things to extract. ) { if (!palname) { cerr << "No palette name (i.e., 'palettes.flx') given" << endl; exit(1); } U7object pal(palname, 0); // Get palette 0. size_t len; unsigned char *palbuf = (unsigned char *) pal.retrieve(len); // This may throw an exception for (int i = 0; i < len; i++) // Turn into full bytes. palbuf[i] *= 4; // Exult palette vals are 0-63. Vga_file ifile(imagename); // May throw an exception. for (Shape_specs::const_iterator it = specs.begin(); it != specs.end(); ++it) { char *basename = (*it).filename; if (!basename) // Empty? continue; int shnum = it - specs.begin(); if (shnum >= ifile.get_num_shapes()) { cerr << "Shape #" << shnum << " > #shapes in file" << endl; continue; } // Read in all frames. Shape *shape = ifile.extract_shape(shnum); int nframes = shape->get_num_frames(); if (nframes != (*it).nframes) cerr << "Warning: # frames (" << (*it).nframes << ") given for shape " << shnum << " doesn't match actual count (" << nframes << ")" << endl; for (int f = 0; f < nframes; f++) Write_frame(basename, f, shape->get_frame(f), palbuf); } delete palbuf; } /* * Print usage and exit. */ static void Usage() { cerr << "Usage: ipack -[x|c|u] script" << endl; exit(1); } /* * Create or extract from Flex files consisting of shapes. */ int main ( int argc, char **argv ) { if (argc < 3 || argv[1][0] != '-') Usage(); // (Exits.) char *scriptname = argv[2]; char *imagename = 0, *palname = 0; Shape_specs specs; // Shape specs. stored here. ifstream specin; try { U7open(specin, scriptname, true); } catch (exult_exception& e) { cerr << e.what() << endl; exit(1); } Read_script(specin, imagename, palname, specs); if (!imagename) { cerr << "No archive name (i.e., 'shapes.vga') given" << endl; exit(1); } specin.close(); switch (argv[1][1]) // Which function? { case 'c': // Create. try { Create(imagename, palname, specs, "Exult image file"); } catch (exult_exception& e){ cerr << e.what() << endl; exit(1); } break; case 'x': // Extract .png files. try { Extract(imagename, palname, specs); } catch (exult_exception& e){ cerr << e.what() << endl; exit(1); } break; case 'u': try { Update(imagename, palname, specs, "Exult image file"); } catch (exult_exception& e){ cerr << e.what() << endl; exit(1); } break; default: Usage(); } return 0; } exult-1.2/tools/splitshp.cc0000644000175000001440000001455610060712066011520 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #ifndef ALPHA_LINUX_CXX # include # include # include #endif #include "exult_types.h" using std::cout; using std::endl; using std::cerr; using std::string; using std::strlen; using std::strrchr; using std::strcpy; using std::memcpy; using std::exit; struct u7frame { bool tile; uint32 datalen; uint8 *data; }; struct u7shape { int num_frames; struct u7frame *frames; }; unsigned int read1(FILE *f) { unsigned char b0; b0 = fgetc(f); return b0; } unsigned int read2(FILE *f) { unsigned char b0, b1; b0 = fgetc(f); b1 = fgetc(f); return (b0 + (b1<<8)); } signed int read2signed(FILE *f) { unsigned char b0, b1; signed int i0; b0 = fgetc(f); b1 = fgetc(f); i0 = b0 + (b1<<8); if (i0 >= 32768) { i0 -= 65536; } return (i0); } unsigned int read4(FILE *f) { unsigned char b0, b1, b2, b3; b0 = fgetc(f); b1 = fgetc(f); b2 = fgetc(f); b3 = fgetc(f); return (b0 + (b1<<8) + (b2<<16) + (b3<<24)); } void write4(FILE *f, unsigned int b) { fputc(b & 0xFF, f); fputc((b >> 8) & 0xFF, f); fputc((b >> 16) & 0xFF, f); fputc((b >> 24) & 0xFF, f); } char* framefilename(char * shapefilename, int frame) { char *fn = new char[strlen(shapefilename)+5]; //_xxx\0 char *dot = strrchr(shapefilename, '.'); #ifdef WIN32 char *slash = strrchr(shapefilename, '\\'); #else char *slash = strrchr(shapefilename, '/'); #endif int dotpos; if (dot == 0 || slash > dot) dotpos = strlen(shapefilename); else dotpos = dot - shapefilename; memcpy(fn, shapefilename, dotpos); sprintf(fn + dotpos, "_%03i", frame); strcpy(fn + dotpos + 4, shapefilename + dotpos); return fn; } void split_shape(char* filename) { FILE *shpfile, *framefile; int file_size, shape_size, hdr_size; int frame_offset, next_frame_offset; int num_frames; int datalen; uint8 *data; char *framename; int i; shpfile = fopen (filename, "rb"); if (!shpfile) { cerr << "Can't open " << filename << endl; return; } fseek(shpfile, 0, SEEK_END); file_size = ftell(shpfile); fseek(shpfile, 0, SEEK_SET); shape_size = read4(shpfile); if(file_size!=shape_size) { /* 8x8 tile */ num_frames = file_size/64; fseek(shpfile, 0, SEEK_SET); /* Return to start of file */ cout << "num_frames = " << num_frames << endl; data = new uint8[64]; for(i=0; i 0 && !tiles) { cout << "Error: can't mix 8x8 tiles and non-tile shapes!" << endl; exit(1); } tiles = true; fseek(framefile, 0, SEEK_SET); fseek(shpfile, 64*i, SEEK_SET); data = new uint8[64]; fread(data, 1, 64, framefile); fwrite(data, 1, 64, shpfile); fclose(framefile); delete [] data; } else { if (tiles) { cout << "Error: can't mix 8x8 tiles and non-tile shapes!" << endl; exit(1); } hdr_size = read4(framefile); if (hdr_size > 8) { frame_size = read4(framefile); frame_size -= hdr_size; } else { frame_size = shape_size - hdr_size; } data = new uint8[frame_size]; fseek(framefile, hdr_size, SEEK_SET); fread(data, 1, frame_size, framefile); fclose(framefile); fseek(shpfile, 4 + (i*4), SEEK_SET); write4(shpfile, total_size); fseek(shpfile, total_size, SEEK_SET); fwrite(data, 1, frame_size, shpfile); total_size += frame_size; delete [] data; } } if (!tiles) { fseek(shpfile, 0, SEEK_SET); write4(shpfile, total_size); } cout << "done" << endl; fclose(shpfile); } int main(int argc, char *argv[]) { char* shapefile; int numframefiles; char* framefiles[255]; u7shape* sh; if (argc < 2) { cout << "Usage: To split: splitshp [shape file]" << endl << " or to pack: splitshp [shape file] [frame files]" << endl; return 0; } shapefile = argv[1]; if (argc > 2) { numframefiles = argc - 2; for (int i=0; i #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include # include #endif #include #include #include #include #include "U7file.h" #include "Flex.h" #include "utils.h" #include "databuf.h" #include "crc.h" #include "exceptions.h" using std::atoi; using std::cerr; using std::cout; using std::endl; using std::exit; using std::FILE; using std::ifstream; using std::ofstream; using std::size_t; using std::strrchr; using std::strncpy; using std::strncat; using std::strlen; using std::vector; using std::string; enum Arch_mode { NONE, LIST, EXTRACT, CREATE, ADD, RESPONSE }; bool is_text_file(const char *fname) { int len = strlen(fname); // only if the filename is greater than 4 chars if (len > 4 && fname[len-4] == '.' && (fname[len-3] == 't' || fname[len-3] == 'T') && (fname[len-2] == 'x' || fname[len-2] == 'X') && (fname[len-1] == 't' || fname[len-1] == 'T')) { return true; } return false; } bool is_null_entry(const char *fname) { int len = strlen(fname); if (len >= 4 && fname[len-4] == 'N' && fname[len-3] == 'U' && fname[len-2] == 'L' && fname[len-1] == 'L') return true; return false; } void set_mode(Arch_mode &mode, Arch_mode new_mode) { if(mode!=NONE) { cerr << "Error: cannot specify multiple modes" << endl; exit(1); } else mode = new_mode; } // Converts all .'s to _'s void make_header_name(char *filename) { int i = strlen (filename); while (i--) if (filename[i] == '.') filename[i] = '_'; else if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') break; } // Makes a name uppercase void make_uppercase (char *name) { int i = strlen (name); while (i--) if (name[i] >= 'a' && name[i] <= 'z') name[i] -= 'a' - 'A'; } // strips a path from a filename void strip_path (char *filename) { int i = strlen (filename); while (i--) { if (filename[i] == '\\' || filename[i] == '/' || filename[i] == ':') break; } // Has a path if (i >= 0) { int j = 0; for (i++, j = 0; filename[j+i]; j++) filename[j] = filename[j+i]; filename[j] = 0; } } long get_file_size(const char *fname) { if (is_null_entry(fname)) return 0; // an empty entry const char *mode = "rb"; bool text = is_text_file(fname); if (text) mode = "r"; FILE *fp; try { fp = U7open (fname, mode); } catch (const file_open_exception& e) { cerr << e.what() << endl; exit(1); } long len = 0; if (!text) { fseek(fp, 0, SEEK_END); len = ftell(fp); } else while (fgetc(fp) != EOF) len++; fclose(fp); return len; } // This getline() accepts any kind of endline on any platform // (So it will accept windows linefeeds in linux, and vice versa) void getline(ifstream& file, char* buf, int size) { int i = 0; char c; file.get(c); while (i < size-1 && (c>=' ' || c=='\t') && file.good()) { buf[i++] = c; file.get(c); } buf[i] = '\0'; // terminator while (!(file.peek()>=' ' || file.peek()=='\t') && file.good()) file.get(c); } #ifdef MACOS int mac_main(int argc, char **argv); int main() { const int mac_argc = 3; char *mac_argv[mac_argc] = { "expack", "-i", "flx.in" }; mac_main( mac_argc, mac_argv ); char *mac_argv2[mac_argc] = { "expack", "-i", "bg/flx.in" }; mac_main( mac_argc, mac_argv2 ); char *mac_argv3[mac_argc] = { "expack", "-i", "si/flx.in" }; mac_main( mac_argc, mac_argv3 ); } int mac_main(int argc, char **argv) #else int main(int argc, char **argv) #endif { Arch_mode mode = NONE; char fname[1024]; char hname[1024]; char hprefix[1024]; char ext[] = "u7o"; int index; vector file_names; hname[0] = 0; if(argc>2) { strncpy(fname, argv[2], 1024); if((argv[1][0]=='-')&&(strlen(argv[1])==2)) { switch(argv[1][1]) { case 'i': { char temp[1024]; char path_prefix[1024]; ifstream respfile; char *slash = strrchr(fname, '/'); if(slash) { int len = slash-fname+1; strncpy(path_prefix, fname, len); path_prefix[len] = 0; } else path_prefix[0] = 0; set_mode(mode,RESPONSE); try { U7open(respfile, fname, true); } catch (const file_open_exception& e) { cerr << e.what() << endl; exit(1); } // Read the output file name getline(respfile, temp, 1024); strncpy(fname, path_prefix, 1024); strncat(fname, temp, 1024); // Header file name strncpy (hprefix, temp, 1024); make_header_name(hprefix); strncpy (hname, path_prefix, 1024); strncat (hname, hprefix, 1024); strncat (hname, ".h", 1024); strip_path (hprefix); make_uppercase (hprefix); while(respfile.good()) { getline(respfile, temp, 1024); if(strlen(temp)>0) { char temp2[1024]; strncpy(temp2, path_prefix,1024); strncat(temp2, temp, 1024); file_names.push_back(temp2); } } respfile.close(); } break; case 'l': set_mode(mode,LIST); break; case 'x': set_mode(mode,EXTRACT); break; case 'c': { for(int i=0;inumber_of_objects(); cout << "Archive: " << fname << endl; cout << "Type: " << f->get_archive_type() << endl; cout << "Size: " << count << endl; cout << "-------------------------" << endl; for(int i=0; iretrieve(i, len); cout << i << "\t" << len << endl; delete [] buf; } } break; case EXTRACT: { if(argc==4) { U7object f(fname,atoi(argv[3])); int nobjs = f.number_of_objects(); int n = atoi(argv[3]); if (n >= nobjs) { cerr << "Obj. #(" << n << ") is too large. "; cerr << "Flex size is " << nobjs << '.' << endl; exit(1); } char outfile[32]; snprintf(outfile,32,"%d.%s", n, ext); f.retrieve(outfile); // may throw! } else { U7FileManager fm; U7file *f = fm.get_file_object(fname); int count = f->number_of_objects(); for(index=0; index #include #include void rebuild(void) { unsigned int c; char s[10]; char filename[18]; char *pos; FILE *fi=fopen("index","r"),*fi2,*fo=fopen("usecode","wb"); if (fi==NULL) { printf("Can't open index file.\n"); exit(0); } if (fo==NULL) { printf("Can't create usecode file.\n"); exit(0); } while (!feof(fi)) { fgets(s,10,fi); strcpy(filename, s); pos = strchr(filename, '\n'); if (pos) *pos = '\0'; strcat(filename, ".uco"); if (!feof(fi)) { s[strlen(s)-1]=0; printf("Writing function: %s... ",s); if ((fi2=fopen(filename,"rb"))==NULL) { printf("Can't open file %s\n", filename); exit(0); } while(!feof(fi2)) { c=fgetc(fi2); if (!feof(fi2)) fputc(c,fo); } fclose(fi2); printf("done\n"); } } exit(0); } int main(int argc,char *argv[]) { unsigned short fn, fnc; unsigned short temp; int fs,fsc; unsigned int i,put=0; int number; int extended; char s[10]; char filename[18]; FILE *fi,*fo,*fo2; printf("Wody's Rip v0.005\nCopyright (c) 1999 Wody Dragon (a.k.a. Wouter Dijkslag)\n"); if (argc<2||(!strcasecmp(argv[1],"put")&&argc!=3)) { printf("Syntax: rip \tGets function out of usecode (and" " index)\n\trip all\t\tGets all functions out of usecode (and index)\n" "\trip glue\tRecreate usecode file (needs all functions)\n" "\trip index\tOnly get index\n\trip put \tInserts function" " into the usecode file\n"); exit(0); } if (!strcasecmp(argv[1],"all")) number=-1; else if (!strcasecmp(argv[1],"glue")) rebuild(); // note: this doesn't return else if (!strcasecmp(argv[1],"index")) number=-2; else if (!strcasecmp(argv[1],"put")) { sscanf(argv[2],"%x",&number); put=1; } else sscanf(argv[1],"%x",&number); if ((fi=fopen("usecode","rb+"))==NULL) { printf("Can't open usecode file.\n"); exit(0); } if ((fo2=fopen("index","w"))==NULL) { printf("Can't create index file.\n"); exit(0); } while (1) { if (fread(&fn,2,1,fi)!=1) break; if (fn == 0xFFFF) { extended = 1; fread(&fn,2,1,fi); fread(&fs,4,1,fi); } else { extended = 0; fread(&temp,2,1,fi); fs = temp; } if (number==-1||number==-2||number==fn) { sprintf(s,"%04X",fn); strcpy(filename, s); strcat(filename, ".uco"); fprintf(fo2,"%s\n",s); } if (number==-1||number==fn) { if (!put) { printf("Writing function: %s... ",s); if ((fo=fopen(filename,"wb"))==NULL) { printf("Can't open file %s\n", filename); exit(0); } if (extended) { temp = 0xFFFF; fwrite(&temp,2,1,fo); fwrite(&fn,2,1,fo); fwrite(&fs,4,1,fo); } else { fwrite(&fn,2,1,fo); temp = fs; fwrite(&temp,2,1,fo); } for (i=0;i #include #include #include "uctools.h" static opcode_desc push_table[]= { {"true",0,0x13}, {"false",0,0x14}, {"itemref",0,0x3e}, {"eventid",0,0x48} }; static opcode_desc pop_table[]= { {"eventid",0,0x4b} }; static const char* compiler_table[]= { ".argc", ".extern", ".externsize", ".localc" }; #define MAX_LABELS 3500 #define TOKEN_LENGTH 25600 char token[TOKEN_LENGTH],*token2,curlabel[256],indata; int byte,word,pass,offset,datasize,codesize,funcnum; int extended; char labels[MAX_LABELS][10]; int offsets[MAX_LABELS]; int lindex; FILE *fo,*fi; void emit_byte(int i) { if (pass>0) { fputc(i,fo); if (indata) datasize++; } offset++; codesize++; } void emit_word(int i) { emit_byte(i&0xff); emit_byte((i>>8)&0xff); } void emit_dword(int i) { emit_byte(i&0xff); emit_byte((i>>8)&0xff); emit_byte((i>>16)&0xff); emit_byte((i>>24)&0xff); } void add_label(void) { int i; if (token[strlen(token)-1]==':') token[strlen(token)-1]=0; if (lindex>=MAX_LABELS) { printf("Too many labels.\n"); exit(0); } for (i=0;i 32767) printf("Warning: offset too big for 16 bit at label %s!\n", curlabel); } void check_data_label_16(int label) { if (label > 65535) printf("Warning: offset too big for 16 bit at label %s!\n", curlabel); } void read_token(FILE *fi) { int i=0,c=32; while (((c==' ') || (c=='\t') || (c=='\n') || (c==',')) && (!feof(fi))) c=fgetc(fi); while (!((c==' ') || (c=='\t') || (c=='\n') || (c==',')) && (!feof(fi))) { if (i >= TOKEN_LENGTH - 1) { fprintf(stderr, "Error: token too long!\n"); exit(-1); } token[i++]=c; if (c==';') { while ((c=fgetc(fi))!='\n') /* do nothing */ ; i=0; } if (c==39) { while ((c=fgetc(fi))!='\n') { if (i >= TOKEN_LENGTH - 1) { fprintf(stderr, "Error: token too long!\n"); exit(-1); } token[i++]=c; } ungetc(c,fi); i--; } c=fgetc(fi); } if (i >= TOKEN_LENGTH - 1) { fprintf(stderr, "Error: token too long!\n"); exit(-1); } token[i]=0; } int main(int argc,char *argv[]) { int i,opsize=sizeof(opcode_table)/sizeof(opcode_desc), pushsize=sizeof(push_table)/sizeof(opcode_desc), popsize=sizeof(pop_table)/sizeof(opcode_desc), compsize=sizeof(compiler_table)/sizeof(char*); int label; const char **func_table = bg_intrinsic_table; int funsize = bg_intrinsic_size; int findex = 1; // Index in argv of 1st filename. unsigned int opcodetype; indata=codesize=datasize=0; /* printf("Wody's Usecode Compiler v0.009\nCopyright (c) 1999 Wody " "Dragon (a.k.a. Wouter Dijkslag)\n");*/ if (argc<3) { printf("syntax: %s [-s] infile outfile\n", argv[0]); exit(0); } // Serpent Isle? if (strcmp(argv[1], "-s") == 0) { findex++; func_table = si_intrinsic_table; funsize = si_intrinsic_size; } lindex=0; for (pass=0;pass<2;pass++) { // printf("Pass %d\n",pass+1); if ((fi=fopen(argv[findex],"r"))==NULL) { printf("Can't open infile for reading\n"); exit(0); } if ((fo=fopen(argv[findex + 1],"wb"))==NULL) { printf("Can't open outfile for writing\n"); exit(0); } while (!feof(fi)) { read_token(fi); if (strlen(token)>1 && token[strlen(token)-1]==':') { token[strlen(token)-1]=0; // remove trailing ':' if (pass == 0) add_label(); strcpy(curlabel, token); } else if (!strcmp(token,".code")) { indata=0; offset=0; } else if (!strcmp(token,".data")) { if (extended == 0) { emit_word(funcnum); emit_word(0); emit_word(0); codesize = 2; } else { emit_word(-1); emit_word(funcnum); emit_dword(0); emit_dword(0); codesize = 4; } indata=1; offset=0; } else if (!strcmp(token,".funcnumber")) { read_token(fi); sscanf(token,"%x",&funcnum); printf("Function %04X\n", funcnum); // codesize=2; extended = 0; } else if (!strcmp(token,".ext32")) { extended = 1; } else if (token[0]=='.') { indata=0; for (i=0;i 65535) { printf("Error: code size > 64Kb and not in ext32 mode!\n"); } emit_word(i); if (datasize > 65535) { printf("Error: data size > 64Kb and not in ext32 mode!\n"); } emit_word(datasize); } else { fseek(fo,4,SEEK_SET); indata=0; i=codesize; emit_dword(i); emit_dword(datasize); } fclose(fo); fclose(fi); } return 0; } exult-1.2/tools/wud.c0000644000175000001440000002235707472770216010322 #include #include #include #include "uctools.h" // Prints module's data segment void printdataseg(FILE* f, unsigned int ds) { long pos; unsigned int off = 0; unsigned char* p; unsigned char* pp; unsigned char* tempstr,*tempstr2; tempstr = malloc(60 + 1); pos = ftell(f); pp = p = malloc(ds); fread(p, 1, ds, f); fseek(f, pos, SEEK_SET); printf("\t\t.data\n"); while( off < ds ) { int len; unsigned int localoff = 0; while( (len = ( strlen(pp) > 60 ) ? 60 : strlen(pp)) ) { memcpy(tempstr, pp, len); tempstr[len] = '\0'; if (!localoff) printf("L%04X:",off); while (strchr(tempstr,13)) { tempstr2=strchr(tempstr,13)+2; tempstr[strchr(tempstr,13) - (char *) tempstr]=0; printf("\tdb\t\'%s\'\n\tdb\t0d\n\tdb\t0a\n", tempstr); strcpy(tempstr,tempstr2); } if (tempstr) printf("\tdb\t\'%s\'\n", tempstr); localoff += len; pp += len; } pp++; printf("L%04X:\tdb\t00\n", off+localoff); off += localoff + 1; } free(p); free(tempstr); } // Prints single opcode // Return number of bytes to advance the code pointer // Prints first characters of strings referenced unsigned int print_opcode(unsigned char* ptrc, unsigned int coffset, unsigned char* pdataseg,unsigned short* pextern, unsigned int externsize, const char **func_table, int funsize) { unsigned int nbytes; unsigned int i; // Find the description opcode_desc* pdesc = ( *ptrc >= ( sizeof(opcode_table) / sizeof( opcode_desc ) ) ) ? NULL : opcode_table + ( *ptrc ); if( pdesc && ( pdesc->mnemonic == NULL ) ) { printf("Unknown opcode: %x\n",*ptrc); // Unknown opcode pdesc = NULL; } // Number of bytes to print nbytes = pdesc ? ( pdesc->nbytes + 1 ) : 1; // Print label printf("%04X: ", coffset); // Print bytes for( i = 0; i < nbytes; i++ ) printf("%02X ", ptrc[i]); // Print mnemonic if( nbytes < 4 ) printf("\t"); if (pdesc) printf("\t%s", pdesc->mnemonic); else printf("\tdb %x\t???",ptrc[0]); // Print operands if any if( ( nbytes == 1 ) || ( pdesc == NULL && pdesc->type == 0) ) { printf("\n"); return nbytes; } switch( pdesc->type ) { case BYTE: printf("\t%x\n",*(unsigned char*)(ptrc+1)); break; case PUSH: for ( i = 1; i < nbytes; i++) printf("\n%04X:\t\t\tdb %x",coffset+i,ptrc[i]); printf("\n"); break; case IMMED: // Print immediate operand printf("\t%04XH\t\t\t; %d\n", *(unsigned short*)( ptrc + 1 ), *(short*)( ptrc + 1 )); break; case IMMED32: printf("\t%04XH\t\t\t; %d\n", *(unsigned int*)( ptrc + 1 ), *(int*)( ptrc + 1 )); break; case DATA_STRING: case DATA_STRING32: { unsigned char* pstr; int len; // Print data string operand if (pdesc->type == DATA_STRING) pstr = pdataseg + *(unsigned short*)( ptrc + 1 ); else pstr = pdataseg + *(unsigned int*)( ptrc + 1 ); len = strlen(pstr); if( len > 20 ) len = 20 - 3; if (pdesc->type == DATA_STRING) printf("\tL%04X\t\t\t; ", *(unsigned short*)( ptrc + 1 )); else printf("\tL%04X\t\t\t; ", *(unsigned int*)( ptrc + 1 )); for( i = 0; i < len; i++ ) printf("%c", pstr[i]); if( len < strlen(pstr) ) // String truncated printf("..."); printf("\n"); } break; case RELATIVE_JUMP: // Print jump desination // printf("\t%04X\n", *(short*)( ptrc + 1 ) + (short)coffset + 3); printf("\t%04X\n", *(short*)( ptrc + nbytes - 2) + coffset + nbytes); // debugging printf("nbytes=%d, coffset=%d\n", nbytes, coffset); break; case RELATIVE_JUMP32: printf("\t%04X\n", *(int*)( ptrc + nbytes - 4) + coffset + nbytes); break; case SLOOP: /* WJP */ printf("\t[%04X], [%04X], [%04X], [%04X], %04X\n", *(unsigned short*)( ptrc + nbytes - 10 ), *(unsigned short*)( ptrc + nbytes - 8 ), *(unsigned short*)( ptrc + nbytes - 6 ), *(unsigned short*)( ptrc + nbytes - 4 ), *(short*)( ptrc + nbytes - 2) + coffset + nbytes); break; case SLOOP32: /* WJP */ printf("\t[%04X], [%04X], [%04X], [%04X], %04X\n", *(unsigned short*)( ptrc + nbytes - 12 ), *(unsigned short*)( ptrc + nbytes - 10 ), *(unsigned short*)( ptrc + nbytes - 8 ), *(unsigned short*)( ptrc + nbytes - 6 ), *(int*)( ptrc + nbytes - 4) + coffset + nbytes); break; case IMMED_AND_RELATIVE_JUMP: /* JSF */ printf("\t%04XH, %04X\n", *(unsigned short*)( ptrc + 1 ), *(short*)( ptrc + 3 ) + coffset + 5); break; case IMMED_RELJUMP32: printf("\t%04XH, %04X\n", *(unsigned short*)( ptrc + 1 ), *(int*)( ptrc + 3 ) + coffset + 5); break; case CALL: { // Print call operand unsigned short func = *(unsigned short*)( ptrc + 1 ); if( ( func < funsize ) && func_table[func] ) // Known function printf("\t_%s@%d (%04X)\n", func_table[func], ptrc[3], func); else // Unknown function printf("\t%04X, %d\n", func, ptrc[3]); } break; case EXTCALL: { // Print extern call unsigned short externpos = *(unsigned short*)( ptrc + 1 ); if( externpos < externsize ) printf("\t[%04X]\t\t\t; %04XH\n", externpos, pextern[externpos]); else printf("\t[%04X]\t\t\t; ????\n", externpos); } break; case VARREF: // Print variable reference printf("\t[%04X]\n", *(unsigned short*)( ptrc + 1 )); break; case FLGREF: // Print global flag reference printf("\tflag:[%04X]\n", *(unsigned short*)( ptrc + 1 )); break; default: // Unknown type printf("\n"); break; } return nbytes; } void printcodeseg(FILE* f, unsigned int ds, unsigned int s, const char **func_table, int funsize, int extended) { long pos; unsigned int size; unsigned int externsize; unsigned int i; unsigned int offset; unsigned int nbytes; unsigned char* p; unsigned char* pp; unsigned char* pdata; unsigned short* pextern; pos = ftell(f); if (extended == 0) { size = s - ds - sizeof(unsigned short); } else { size = s - ds - sizeof(unsigned int); } pp = p = malloc(size); pdata = malloc(ds); fread(pdata, 1, ds, f); printf("\t\t.code\n"); fread(p, 1, size, f); fseek(f, pos, SEEK_SET); // Print code segment header if( size < 3 * sizeof(unsigned short) ) { printf("Code segment bad!\n"); free(p); free(pdata); return; } // Print argument counter printf("\t\t.argc %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); // Print locals counter printf("\t\t.localc %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); // Print externs section externsize = *(unsigned short*)pp; printf("\t\t.externsize %04XH\n", externsize); pp += sizeof(unsigned short); if( size < ( ( 3 + externsize ) * sizeof(unsigned short) ) ) { printf("Code segment bad!\n"); free(p); free(pdata); return; } size -= ( ( 3 + externsize ) * sizeof(unsigned short) ); pextern = (unsigned short*)pp; for( i = 0; i < externsize; i++ ) { printf("\t\t.extern %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); } offset = 0; // Print opcodes while( offset < size ) { nbytes = print_opcode(pp, offset, pdata, pextern, externsize, func_table, funsize); pp += nbytes; offset += nbytes; } free(p); free(pdata); } /* * Note: func = -1 just to print header, funcnum to print it all, or * -2 for any function. */ void printfunc(FILE* f, long func, int i, const char **func_table, int funsize) { unsigned short funcnum; unsigned int s, ds; unsigned short temp; long off, bodyoff; int extended = 0; // Save start offset off = ftell(f); // Read function header fread(&funcnum, sizeof(unsigned short), 1, f); if (funcnum == 0xFFFF) { fread(&funcnum, sizeof(unsigned short), 1, f); fread(&s, 4, 1, f); bodyoff = ftell(f); fread(&ds, 4, 1, f); extended = 1; } else { fread(&temp, sizeof(unsigned short), 1, f); s = temp; // Save body offset bodyoff = ftell(f); fread(&temp, sizeof(unsigned short), 1, f); ds = temp; } if( func == -1 ) printf("\tFunction #%d (%04XH), offset = %08lx, size = %04x, data = %04x\n", i, funcnum, off, s, ds); if( funcnum == func || func == -2) { printf("\t\t.funcnumber\t%04XH\n", funcnum); if (extended == 1) printf("\t\t.ext32\n"); // Dump function contents printdataseg(f, ds); printcodeseg(f, ds, s, func_table, funsize, extended); } // Seek back, then to next function fseek(f, bodyoff, SEEK_SET); fseek(f, s, SEEK_CUR); } int main(int argc, char** argv) { unsigned long func = -1; long sz; int i = 0; FILE* f; int findex = 1; // Argv index of file. const char **func_table = bg_intrinsic_table; int funsize = bg_intrinsic_size; if(argc<2) { fprintf(stderr, "Usage\n%s [-s] usecode_file [func_num]\n", argv[0]); return -1; } // Serpent Isle? if (strcmp(argv[1], "-s") == 0) { findex++; func_table = si_intrinsic_table; funsize = si_intrinsic_size; } f = fopen(argv[findex], "rb"); if( f == NULL ) { fprintf(stderr,"Failed to open %s\n\n", argv[findex]); return 0; } fseek(f, 0, SEEK_END); sz = ftell(f); fseek(f, 0, SEEK_SET); if( argc > findex + 1 ) { char* stopstr; if (strcmp(argv[findex + 1], "-a") == 0) func = -2; // Print ALL functions. else func = strtoul(argv[findex + 1], &stopstr, 16); } while( ftell(f) < sz ) { printfunc(f, func, i, func_table, funsize); i++; } if( func == -1 ) { if( ftell(f) != sz ) fprintf(stderr,"Problem, tell = %ld!\n", ftell(f)); printf("Functions: %d\n", i); } fclose(f); return 0; } exult-1.2/tools/README0000644000175000001440000000523407124132423010214 Hello, This .ZIP contains the following files: README This File B.EXE Decompiler by Maxim & Wody MKLINK.EXE Creates the link-dependencies U7 uses RIP.COM Rips usecode to little files, and builds usecode-file by Wody WUC.COM Usecode assembler by Wody INTRINS1.TXT List of used intrinsic functions for U7BG by Wody INTRINS2.TXT List of used intrinsic functions for U7SI by Wody U7BGFLAG.TXT Flags used with PUSHF/POPF for U7BG by Wody U7SIFLAG.TXT Flags used with PUSHF/POPF for U7SI by Wody UCFORMAT.TXT Format of Usecode-file by various people SOURCE.ZIP ZIP file of source for all programs included Maxim is Maxim S. Shatskih, Email: maxim__s@mtu-net.ru Wody is Wouter Dijkslag, Email: wody@wody.demon.nl (more credits in UCFORMAT.TXT) If you want to do anything with it, you need the usecode file from Ultima 7: The Black Gate or Ultima7: Serpent Isle. With this file, you can then create a list by running B.EXE, which shows it on your screen. To redirect it to a file, use B > FILE, where FILE is the file you want it to. This file has a lot of functions in it, in the form of: Number Function #0 (0096H), offset = 00000000, size = 00a2, data = 005d The most interesting part is number. If you run B with that number (B 0096) you will get the source of that function, as far as is known. Off course, this can be redirected too. You can then change that function, and recompile it! If you want to change a function, you first need to create compiled files and an index file for all functions. You could do this by hand, but there is a program for it, called RIP. You can rip a single function (RIP 0096), take all functions out of the usecode (RIP ALL), only create an index (RIP INDEX), or put all files and the index back together (RIP GLUE). The compile is done by the program WUC. You run this by WUC infile outfile. This means, if you have function 0096 written in file 0096.TXT, you need to run WUC 0096.TXT 0096, but you could also write FUNCTION.TXT 0096 or something to that effect. If you just change a single function, and didn't change the size, you can put it back with RIP PUT. Otherwise you have to rebuild the entire file with RIP GLUE, and run MKLINK. When the usecode file is built, copy it over the old version, and run U7. If you ran MKLINK, also copy the LINKDEP1 and LINKDEP2 files over the old versions. Then it's testing.. Don't forget to make backups! Read the decompiled usecode to see how to program for U7. If you find out anything (functions, meanings of opcodes, etc) which is unknown, or have any comments, please tell Wouter so this package can become better! Ultima & The Serpent Isle are trademarks or registered trademarks of ORIGIN Systems, Inc. exult-1.2/tools/cmanip.cc0000644000175000001440000001456707662722201011131 /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "Configuration.h" #include #include #include "exult_constants.h" #include #include const std::string c_empty_string; using std::cout; using std::cerr; using std::endl; using std::vector; using std::string; using std::pair; enum DoOps { DoAdd, DoRem, DoGet }; typedef pair > DoListPair; typedef vector DoList; DoList dolist; Configuration *config= new Configuration(); string config_file_name; bool verbose=false; // dump verbose output to cerr /* #include */ void usage(unsigned int i) { cout << "cmanip - simple commandline, conf/ file manipulator" << endl #ifdef HAVE_CONFIG_H << " compiled with " << PACKAGE << " " << VERSION << endl #endif << endl << "usage:" << endl << "\tcmanip [option [parameters]] ..." << endl << endl << "options:" << endl << "\t[-a | add | create | mk | new | modify] " << endl << "\t\t\t- adds the to the in the " << endl << "\t[-r | rem | remove | rm | del] " << endl << "\t\t\t- removes the from the " << endl << "\t[-x | get | extract | rd | see | read] " << endl << "\t\t\t- extracts the value set for from the or \"unknown\"" << endl << "\t[-v | verbose]\t- print verbose output to stderr" << endl << endl << "examples:" << endl << "\tcmanip exult.cfg add config/foo stuff rem config/bar" << endl << "\tcmanip exult.cfg new config/foo \"more stuff\" add config/bar useless" << endl << "\tcmanip exult.cfg -v -r config/foo del config/bar" << endl ; exit(i); } /* Turn the various command line parameters into operations that can be handled by process_ops */ void read_params(const int argc, char *argv[]) { config_file_name = argv[1]; // "I'd appreciate your input"... for(unsigned int i=2; i=argc) { cout << "error: insufficient parameters supplied for '" << s << "'" << endl; usage(1); } DoListPair dlp; dlp.first = DoAdd; dlp.second.push_back(argv[i+1]); dlp.second.push_back(argv[i+2]); dolist.push_back(dlp); i+=2; } /* Removes the key (argv[i+1]) from the conf file. FIXME: Currently only sets it to 'null', since there is no 'remove' ability in Configuration. */ else if((s=="rem") || (s=="remove") || (s=="rm") || (s=="mk") || (s=="del") || (s=="-r")) { if(i+1>=argc) { cout << "error: insufficient parameters supplied for '" << s << "'" << endl; usage(1); } DoListPair dlp; dlp.first = DoRem; dlp.second.push_back(argv[i+1]); dolist.push_back(dlp); i++; } /* Added by Artaxerxes. Extracts the values for a given path. Do not change anything. Just read.*/ else if((s=="extract") || (s=="read") || (s=="rd") || (s=="see") || (s=="get") || (s=="-x")) { if(i+1>=argc) { cout << "error: insufficient parameters supplied for '" << s << "'" << endl; usage(1); } DoListPair dlp; dlp.first = DoGet; dlp.second.push_back(argv[i+1]); dolist.push_back(dlp); i++; } /* Just turns on 'verbose' mode. Nothing of particular intrest. */ else if((s=="-v") || (s=="verbose")) verbose=true; else { cout << "error: unknown parameter \"" << s << "\"" << endl; } } } /* Walk over the operations list (dolist) and execute each operation in the order it was listed on the command line */ void process_ops() { for(DoList::iterator i=dolist.begin(); i!=dolist.end(); i++) { if(i->first==DoAdd) { assert(i->second.size()==2); if(verbose) { string s; assert(config!=0); config->value(i->second[0].c_str(),s,"---nil---"); cerr << "Original value of " << i->second[0] << " was " << s << endl; } assert(config!=0); config->set(i->second[0].c_str(), i->second[1].c_str(), false); if(verbose) cerr << "Added " << i->second[1] << " to " << i->second[0] << endl; } if(i->first==DoRem) { assert(i->second.size()==1); if(verbose) { string s; assert(config!=0); config->value(i->second[0].c_str(),s,"---nil---"); cerr << "Original value was " << i->second[0] << " was " << s << endl; } assert(config!=0); config->set(i->second[0].c_str(), "", false); if(verbose) cerr << "Removed " << i->second[0] << endl; } if(i->first==DoGet) { assert(i->second.size()==1); if(verbose) { string s; assert(config!=0); config->value(i->second[0].c_str(),s,"unknown"); cerr << "Return value for " << i->second[0] << " is " << s << endl; } assert(config!=0); //config->set(i->second[0].c_str(), "", false); string s; config->value(i->second[0].c_str(),s,"unknown"); cout << s << endl; } } } int main(int argc, char *argv[]) { if(argc<3) usage(0); read_params(argc, argv); if(verbose) { cerr << "Operations:" << endl; for(DoList::iterator i=dolist.begin(); i!=dolist.end(); i++) { cerr << '\t' << ((i->first==DoAdd) ? "add" : ((i->first==DoRem) ? "rem" : ((i->first==DoGet) ? "get" : "unknown"))) << '\t'; for(vector::iterator j=i->second.begin(); j!=i->second.end(); j++) cerr << *j << '\t'; cerr << endl; } } assert(config!=0); config->read_config_file(config_file_name.c_str()); process_ops(); assert(config!=0); config->write_back(); return 0; } exult-1.2/tools/shp2pcx.cc0000644000175000001440000002325407304651453011245 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_byteorder.h" #include #ifndef ALPHA_LINUX_CXX # include # include # include #endif #include "exult_types.h" #if SDL_BYTEORDER == SDL_LIL_ENDIAN #define qtohl(x) (x) #define qtohs(x) (x) #else #define qtohl(x) \ ((uint32)((((uint32)(x) & 0x000000ffU) << 24) | \ (((uint32)(x) & 0x0000ff00U) << 8) | \ (((uint32)(x) & 0x00ff0000U) >> 8) | \ (((uint32)(x) & 0xff000000U) >> 24))) #define qtohs(x) \ ((uint16)((((uint16)(x) & 0x00ff) << 8) | \ (((uint16)(x) & 0xff00) >> 8))) #endif #define htoql(x) qtohl(x) #define htoqs(x) qtohs(x) using std::cout; using std::endl; using std::cerr; using std::string; using std::strlen; using std::memset; using std::memcpy; typedef struct PCX_Header { uint8 manufacturer; uint8 version; uint8 compression; uint8 bpp; sint16 x1, y1; sint16 x2, y2; sint16 hdpi; sint16 vdpi; uint8 colormap[48]; uint8 reserved; uint8 planes; sint16 bytesperline; sint16 color; uint8 filler[58]; } PCX_Header; struct u7frame { sint16 leftX; sint16 leftY; sint16 rightX; sint16 rightY; uint16 width; uint16 height; uint32 datalen; uint8 *pixels; }; struct u7shape { int num_frames; struct u7frame *frames; int width, height; }; unsigned int read1(FILE *f) { unsigned char b0; b0 = fgetc(f); return b0; } unsigned int read2(FILE *f) { unsigned char b0, b1; b0 = fgetc(f); b1 = fgetc(f); return (b0 + (b1<<8)); } /* Flauschepelz */ signed int read2signed(FILE *f) { unsigned char b0, b1; signed int i0; b0 = fgetc(f); b1 = fgetc(f); i0 = b0 + (b1<<8); if (i0 >= 32768) { i0 = i0 - 65536; } return (i0); } unsigned int read4(FILE *f) { unsigned char b0, b1, b2, b3; b0 = fgetc(f); b1 = fgetc(f); b2 = fgetc(f); b3 = fgetc(f); return (b0 + (b1<<8) + (b2<<16) + (b3<<24)); } u7shape* load_shape(char* filename) { FILE *fp; int file_size, shape_size, hdr_size; uint8 *pixptr, *eod; int frame_offset; int slice; int image_ID = -1, layer_ID = -1; int slice_type, slice_length; int block_type, block_length; int max_leftX = -1, max_rightX = -1; int max_leftY = -1, max_rightY = -1; int offsetX, offsetY; char *framename; uint8 block; uint8 pix; int i, j; int temp_int; u7shape *shape = new u7shape; u7frame *frame; fp = fopen (filename, "rb"); if (!fp) { cerr << "Can't open " << filename << endl; return 0; } fseek(fp, 0, SEEK_END); file_size = ftell(fp); fseek(fp, 0, SEEK_SET); shape_size = read4(fp); if(file_size!=shape_size) { /* 8x8 tile */ shape->num_frames = file_size/64; fseek(fp, 0, SEEK_SET); /* Return to start of file */ cout << "num_frames = " << shape->num_frames << endl; shape->frames = new u7frame[shape->num_frames]; max_leftX = 0; max_leftY = 0; max_rightX = 7; max_rightY = 7; for(i=0; inum_frames; i++) { frame = &shape->frames[i]; frame->width = 8; frame->height = 8; frame->leftX = 0; frame->leftY = 0; frame->pixels = new uint8[64]; fread(frame->pixels, 1, 64, fp); } } else { hdr_size = read4(fp); shape->num_frames = (hdr_size-4)/4; cout << "num_frames = "<< shape->num_frames << endl; shape->frames = new u7frame[shape->num_frames]; for(i=0; inum_frames; i++) { frame = &shape->frames[i]; // Go to where frame offset is stored fseek(fp, (i+1)*4, SEEK_SET); frame_offset = read4(fp); fseek(fp, frame_offset, SEEK_SET); frame->rightX = read2(fp); frame->leftX = read2(fp); frame->leftY = read2(fp); frame->rightY = read2(fp); if (frame->leftX > max_leftX) max_leftX = frame->leftX; if (frame->rightX > max_rightX) max_rightX = frame->rightX; if (frame->leftY > max_leftY) max_leftY = frame->leftY; if (frame->rightY > max_rightY) max_rightY = frame->rightY; frame->width = frame->leftX+frame->rightX+1; frame->height = frame->leftY+frame->rightY+1; pixptr = new uint8[frame->width*frame->height]; frame->pixels = pixptr; memset(pixptr, 0, frame->width*frame->height); eod = frame->pixels+frame->width*frame->height; while((slice=read2(fp))!=0) { slice_type = slice & 0x1; slice_length = slice >> 1; offsetX = read2signed(fp); offsetY = read2signed(fp); temp_int = (frame->leftY + offsetY)*frame->width + (frame->leftX + offsetX); pixptr = frame->pixels; pixptr = pixptr + temp_int; if(pixptrpixels) pixptr = frame->pixels; if(slice_type) { // Compressed while(slice_length>0) { block = read1(fp); block_type = block & 0x1; block_length = block >> 1; if(block_type) { pix = read1(fp); for(j=0;j 128) { cerr << "Output file prefix too long!" << endl; return -1; } sh = load_shape(infilename); if (!sh) return 1; palette = load_palette(palfilename); if (!palette) return 1; for (int i = 0; i < sh->num_frames; i++) { sprintf(outfilename, "%s%02i.pcx", outprefix, i); cout << "Writing frame " << i << " to " << outfilename << "..." << endl; save_image(sh->frames[i].pixels, palette, sh->width, sh->height, outfilename); } return 0; } exult-1.2/tools/uctools.h0000644000175000001440000002600107732251221011173 #ifndef UCTOOLS_H #define UCTOOLS_H // Opcode flags // Just a 16bit word #define IMMED 0 // Will print a part of data string as comment #define DATA_STRING 1 // Will add command offset before printing #define RELATIVE_JUMP 2 // Will print third byte as decimal after comma #define CALL 3 // Will print in square brackets #define VARREF 4 // Will print in square brackets with "flag:" prefix #define FLGREF 5 // Call of usecode function using extern table #define EXTCALL 6 // An immediate op. and then a rel. jmp address: JSF #define IMMED_AND_RELATIVE_JUMP 7 // Just x bytes #define PUSH 8 // Just a byte #define BYTE 9 // variable + relative jump (for the 'sloop') #define SLOOP 10 #define POP 11 #define IMMED32 12 #define DATA_STRING32 13 #define RELATIVE_JUMP32 14 #define IMMED_RELJUMP32 15 #define SLOOP32 16 // Opcode descriptor typedef struct _opcode_desc { // Mnemonic - NULL if not known yet const char* mnemonic; // Number of operand bytes int nbytes; // Type flags unsigned int type; } opcode_desc; // Opcode table static opcode_desc opcode_table[] = { { NULL, 0, 0 }, // 00 { NULL, 0, 0 }, // 01 { "loop", 10, SLOOP }, // 02 { NULL, 0, 0 }, // 03 { "startconv", 2, RELATIVE_JUMP }, // 04 { "jne", 2, RELATIVE_JUMP }, // 05 { "jmp", 2, RELATIVE_JUMP }, // 06 { "cmps", 4, IMMED_AND_RELATIVE_JUMP }, // 07 JSF { NULL, 0, 0 }, // 08 { "add", 0, 0 }, // 09 { "sub", 0, 0 }, // 0a { "div", 0, 0 }, // 0b { "mul", 0, 0 }, // 0c { "mod", 0, 0 }, // 0d { "and", 0, 0 }, // 0e { "or", 0, 0 }, // 0f { "not", 0, 0 }, // 10 { NULL, 0, 0 }, // 11 { "pop", 2, VARREF }, // 12 { "push\ttrue", 0, 0 }, // 13 { "push\tfalse", 0, 0 }, // 14 { NULL, 0, 0 }, // 15 { "cmpgt", 0, 0 }, // 16 { "cmpl", 0, 0 }, // 17 { "cmpge", 0, 0 }, // 18 { "cmple", 0, 0 }, // 19 { "cmpne", 0, 0 }, // 1a { NULL, 0, 0 }, // 1b { "addsi", 2, DATA_STRING }, // 1c { "pushs", 2, DATA_STRING }, // 1d { "arrc", 2, IMMED }, // 1e { "pushi", 2, IMMED }, // 1f { NULL, 0, 0 }, // 20 { "push", 2, VARREF }, // 21 { "cmpeq", 0, 0 }, // 22 { NULL, 0, 0 }, // 23 { "call", 2, EXTCALL }, // 24 { "ret", 0, 0 }, // 25 { "aidx", 2, VARREF }, // 26 { NULL, 0, 0 }, // 27 { NULL, 0, 0 }, // 28 { NULL, 0, 0 }, // 29 { NULL, 0, 0 }, // 2a { NULL, 0, 0 }, // 2b { "ret2", 0, 0 }, // 2c { "setr", 0, 0 }, // 2d { "initloop", 0, 0 }, // 2e { "addsv", 2, VARREF }, // 2f { "in", 0, 0 }, // 30 { "conv_something", 4, IMMED_AND_RELATIVE_JUMP }, // 31 { "rts", 0, 0 }, // 32 { "say", 0, 0 }, // 33 { NULL, 0, 0 }, // 34 { NULL, 0, 0 }, // 35 { NULL, 0, 0 }, // 36 { NULL, 0, 0 }, // 37 { "callis", 3, CALL }, // 38 { "calli", 3, CALL }, // 39 { NULL, 0, 0 }, // 3a { NULL, 0, 0 }, // 3b { NULL, 0, 0 }, // 3c { NULL, 0, 0 }, // 3d { "push\titemref", 0, 0 }, // 3e { "abrt", 0, 0 }, // 3f { "endconv", 0, 0 }, // 40 { NULL, 0, 0 }, // 41 { "pushf", 2, FLGREF }, // 42 { "popf", 2, FLGREF }, // 43 { "pushw", 1, BYTE }, // 44 { NULL, 0, 0 }, // 45 { "setarrayelem", 2, IMMED }, // 46 { "calle",2,IMMED }, // 47 { "push\teventid", 0, 0 }, // 48 { NULL, 0, 0 }, // 49 { "arra", 0, 0 }, // 4a { "pop\teventid", 0, 0 }, // 4b { "line",2,IMMED }, // 4c { "func",4,DATA_STRING }, // 4d { NULL, 0, 0 }, { NULL, 0, 0 }, // 4e - 4f { "push\tstatic", 2, VARREF }, // 50 { "pop\tstatic", 2, VARREF }, // 51 { "callo",2,IMMED }, // 52 { NULL, 0, 0 }, // 53 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 54-57 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 58-5B { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 5C-5F { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 60-63 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 64-67 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 68-6B { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 6C-6F { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 70-73 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 74-77 { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 78-7B { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 }, // 7C-7F { NULL, 0, 0 }, // 80 { NULL, 0, 0 }, // 81 { "sloop_iter32", 12, SLOOP32 }, // 82 { NULL, 0, 0 }, // 83 { "startconv32", 4, RELATIVE_JUMP32 }, // 84 { "jne32", 4, RELATIVE_JUMP32 }, // 85 { "jmp32", 4, RELATIVE_JUMP32 }, // 86 { "cmps32", 6, IMMED_RELJUMP32 }, // 87 { NULL, 0, 0 }, // 88 { NULL, 0, 0 }, // 89 { NULL, 0, 0 }, // 8a { NULL, 0, 0 }, // 8b { NULL, 0, 0 }, // 8c { NULL, 0, 0 }, // 8d { NULL, 0, 0 }, // 8e { NULL, 0, 0 }, // 8f { NULL, 0, 0 }, // 90 { NULL, 0, 0 }, // 91 { NULL, 0, 0 }, // 92 { NULL, 0, 0 }, // 93 { NULL, 0, 0 }, // 94 { NULL, 0, 0 }, // 95 { NULL, 0, 0 }, // 96 { NULL, 0, 0 }, // 97 { NULL, 0, 0 }, // 98 { NULL, 0, 0 }, // 99 { NULL, 0, 0 }, // 9a { NULL, 0, 0 }, // 9b { "addsi32", 4, DATA_STRING32 }, // 9c { "pushs32", 4, DATA_STRING32 }, // 9d { NULL, 0, 0 }, // 9e { "pushi32", 4, IMMED32 }, // 9f { NULL, 0, 0 }, // a0 { NULL, 0, 0 }, // a1 { NULL, 0, 0 }, // a2 { NULL, 0, 0 }, // a3 { NULL, 0, 0 }, // a4 { NULL, 0, 0 }, // a5 { NULL, 0, 0 }, // a6 { NULL, 0, 0 }, // a7 { NULL, 0, 0 }, // a8 { NULL, 0, 0 }, // a9 { NULL, 0, 0 }, // aa { NULL, 0, 0 }, // ab { NULL, 0, 0 }, // ac { NULL, 0, 0 }, // ad { "sloop32", 13, SLOOP32 }, // ae { NULL, 0, 0 }, // af { NULL, 0, 0 }, // b0 { "conv_something32", 6, IMMED_RELJUMP32 }, // b1 { NULL, 0, 0 }, // b2 { NULL, 0, 0 }, // b3 { NULL, 0, 0 }, // b4 { NULL, 0, 0 }, // b5 { NULL, 0, 0 }, // b6 { NULL, 0, 0 }, // b7 { NULL, 0, 0 }, // b8 { NULL, 0, 0 }, // b9 { NULL, 0, 0 }, // ba { NULL, 0, 0 }, // bb { NULL, 0, 0 }, // bc { NULL, 0, 0 }, // bd { NULL, 0, 0 }, // be { NULL, 0, 0 }, // bf { NULL, 0, 0 }, // c0 { NULL, 0, 0 }, // c1 { NULL, 0, 0 }, // c2 { NULL, 0, 0 }, // c3 { NULL, 0, 0 }, // c4 { NULL, 0, 0 }, // c5 { NULL, 0, 0 }, // c6 { NULL, 0, 0 }, // c7 { NULL, 0, 0 }, // c8 { NULL, 0, 0 }, // c9 { NULL, 0, 0 }, // ca { NULL, 0, 0 }, // cb { NULL, 0, 0 }, // cc { "func32",8,DATA_STRING32 } // cd }; // Embedded function table /* * Tables of usecode intrinsics: */ #define USECODE_INTRINSIC_PTR(NAME) #NAME const char *bg_intrinsic_table[] = { #include "bgintrinsics.h" }; const int bg_intrinsic_size = sizeof(bg_intrinsic_table)/sizeof(char*); const char *si_intrinsic_table[] = { #include "siintrinsics.h" }; const int si_intrinsic_size = sizeof(si_intrinsic_table)/sizeof(char*); #if 0 const char* func_table[] = { "get_random", // 0 "execute_usecode_array", // 1 "delayed_execute_usecode_array", // 2 "show_npc_face", // 3 "hide_npc_face", // 4 "add_answer", // 5 "remove_answer", // 6 "push_answers", // 7 "pop_answers", // 8 "clear_answers", // 9 "select_from_menu", // a "select_from_menu2", // b "input_numeric_value", // c "set_item_shape", // d "find_nearest", // e "play_sound_effect", // f "die_roll", // 10 "get_item_shape", // 11 "get_item_frame", // 12 "set_item_frame", // 13 "get_item_quality", // 14 "set_item_quality", // 15 "get_item_quantity", // 16 "set_item_quantity", // 17 "get_object_position", // 18 "get_distance", // 19 "find_direction", // 1a "get_npc_object", // 1b "get_schedule_type", // 1c "set_schedule_type", // 1d "add_to_party", // 1e "remove_from_party", // 1f "get_npc_property", // 20 "set_npc_property", // 21 "get_avatar_ref", // 22 "get_party_list", // 23 "create_new_object", // 24 "set_last_created", // 25 "update_last_created", // 26 "get_npc_name", // 27 "count_objects", // 28 "take_from_owner", // 29 "get_container_items", // 2a "remove_party_items", // 2b "add_party_items", // 2c NULL, // 2d "play_music", // 2e "npc_nearby", // 2f "find_nearby_avatar", // 30 "is_npc", // 31 "display_runes", // 32 "click_on_item", // 33 NULL, // 34 "find_nearby", // 35 "give_last_created", // 36 "is_dead", // 37 "game_hour", // 38 "game_minute", // 39 "get_npc_number", // 3a "part_of_day", // 3b "get_alignment", // 3c "set_alignment", // 3d "move_object", // 3e NULL, // 3f "item_say", // 40 "projectile_effect", // 41 "get_lift", // 42 "set_lift", // 43 NULL, // 44 NULL, // 45 "sit_down", // 46 NULL, // 47 "display_map", // 48 "kill_npc", // 49 NULL, // 4a "set_npc_attack_mode", // 4b "set_target_npc_to_attack", // 4c "clone_npc", // 4d NULL, // 4e "show_crystal_ball", // 4f "show_wizard_eye", // 50 "resurrect_npc", // 51 "add_spell", // 52 "sprite_effect", // 53 NULL, // 54 "book_mode", // 55 "stop_time", // 56 "cause_light", // 57 "get_barge", // 58 "earthquake", // 59 "is_player_female", // 5a "armageddon", // 5b "halt_scheduled", // 5c "cause_blackout", // 5d "get_array_size", // 5e "mark_stone", // 5f "recall_stone", // 60 NULL, // 61 "is_pc_inside", // 62 "set_orrery_state", // 63 NULL, // 64 "get_timer", // 65 "set_timer", // 66 NULL, // 67 "mouse_exists", // 68 NULL, // 69 "flash_mouse", // 6a NULL, // 6b NULL, // 6c NULL, // 6d "get_container", // 6e "remove_item", // 6f NULL, // 70 NULL, // 71 "get_equipment_list", // 72 NULL, // 73 NULL, // 74 "start_endgame", // 75 "fire_cannon", // 76 "nap_time", // 77 "advance_time", // 78 "in_usecode", // 79 NULL, // 7a NULL, // 7b NULL, // 7c "path_run_usecode", // 7d "close_gumps", // 7e "item_say", // 7f NULL, // 80 "in_gump_mode", // 81 NULL, // 82 NULL, // 83 NULL, // 84 "is_not_blocked", // 85 NULL, // 86 "direction_from", // 87 "get_npc_flag", // 88 "set_npc_flag", // 89 "clear_npc_flag", // 8a "run_usecode", // 8b "fade_palette", // 8c "get_party_list2", // 8d "in_combat", // 8e NULL, // 8f NULL, // 90 NULL, // 91 NULL, // 92 NULL, // 93 NULL, // 94 NULL, // 95 NULL // 96 }; #endif #endif exult-1.2/tools/ucdump.c0000644000175000001440000014015407242176067011013 /* Ultima 7 usecode dump/disassembly utility Distributed under GPL Note: - the source code comments below are possibly SPOILERS. You have beed warned. Maintainer: Maxim S. Shatskih aka Moscow Dragon (maxim__s@mtu-net.ru) History: - originally written June 99 by Maxim S. Shatskih aka Moscow Dragon (maxim__s@mtu-net.ru) Thanks to Keldon Jones (keldon@umr.edu) and Wouter Dijklslag aka Wody Dragon (wody@wody.demon.nl) for their help 11-Oct-99 - added "function search by opcode & intrinsic" feature - added "unknown opcode & intrinsic counting" feature 12-Oct-99 - the good deal of intrinsic functions is now known 6-May-00 - the current version The source must be buildable on any C compiler and runnable on any OS (tested on Win32 and Linux). See source file comments for the description of usecode opcodes & intrinsic functions (the latter one differs between BG & SI) Some general usecode ideas: - usecode functions 0x0-0x3ff are shape handlers - called on double-clicks & other event with appropriate shapes - usecode functions 0x401-0x4ff are NPC handlers - called on double-clicks & other event with appropriate NPCs - NPCID + 0x400 (0x401 for Iolo, 0x417 for LB in BG, 0x41f for Rotoluncia in SI etc). - usecode functions 0x500-0x5ff is for Wisps & guards (nonNPC characters able to talk) (these ranges seems to be hardcoded) - stack machine used to execute bytecodes - the machine's state is: stack local variables(forgotten on function exit, first N of them are call arguments - first pushed is 0, next are 1, 2...) game flags ItemRef (???seems to be valid only for top-level functions-event handlers or maybe is persistent till quitting usecode executuion???) EventID (???seems to be valid only for top-level functions-event handlers or maybe is persistent till quitting usecode executuion???) - game flags are bytes treated as booleans (0/1), persistent across engine shutdown/restart and stored as a simple array (??? 0 or 1 based. Don't remember. Flag 3 means - Tetrahedron is down, flag 4 means - Sphere is down) in GAMEDAT\FLAGINIT. - usecode can also manipulate items & NPCs by means of intrinsic functions - "add" opcode can sum strings (concatenation). Also it can add integer to string - any array operations can be peformed on scalar values. In fact, each scalar value is treated by the array operations as an array with a single element. Vice versa is also true - for instance, ItemsNearItem() function returns an array. Sometimes it is used in enum/next loop as an array, but sometimes it is used as an itemref. - array indices are 1-based as in VB - itemref is a unique ID of the given item. For NPCs, itemref is (-NPCID). For other items, itemrefs seems to be non-persistent (not saved to savegame & re-invented on each engine startup???) indexes into engine's item lists - there is a value called "referent" which identifies item & stored in U7IBUF Maybe Itemref is the same thing? - -356 is always an Itemref for Avatar. So, Avatar's NPC ID is possibly 356. - usecode execution starts from the event handler function. It is called by the engine without arguments (double-click) in some cases. ItemRef & EventID are set before entering usecode. - the easiest case is double-click on some item. In this case, a usecode event handler function called. Function ID usually matches the shape's Type number or is (NPCID + 0x400) for NPCs. ItemRef is set to the item double-clicked, EventID is set to 1 (double-click). - other causes for the engine to call usecode function: - events scheduled by intrinsic functions 1 & 2 have EventID 2 - item is put on another item - the underlying item's handler is called with EventID 3 (Penumbra's plaque) - usecode Egg - also calls a function with EventID 3 - use item as a weapon (flammable oil) - EventID 4 - EventID 5 and 6 - placing the item somewhere in the NPC's inventory (ring of invisibility) - NPC being beaten to death (examples: Hook in BG, Dracothaxus in FoV, Pomdirgun & Rotoluncia in SI) - 7 in SI??? - Avatar & NPC approaching to some distance??? - 9 in SI - hex coords to sextant coords formula (same in BG and SI ) ( x - 933 ) / 10, ( y - 1134 ) / 10 */ #include #include #include /* Opcode flags Just a 16bit word */ #define IMMED 1 /* Immediate 1 byte operand */ #define IMMED_BYTE 2 /* Will print a part of data string as comment */ #define DATA_STRING 4 /* Will add command offset before printing */ #define RELATIVE_JUMP 8 /* Will print third byte as decimal after comma */ #define CALL 16 /* Will print in square brackets */ #define VARREF 32 /* Will print in square brackets with "flag:" prefix */ #define FLGREF 64 /* Call of usecode function using extern table */ #define EXTCALL 128 /* Opcode descriptor */ typedef struct _opcode_desc { /* Mnemonic - NULL if not known yet */ const char* mnemonic; /* Number of operand bytes */ int nbytes; /* Type flags */ unsigned char type; } opcode_desc; /* Opcode table - common to BG & SI */ static opcode_desc opcode_table[] = { { NULL, 0, 0 }, /* 00 */ { NULL, 0, 0 }, /* 01 */ /* Next iteration of For Each-style loop Operands are 1,2, , , is set to next value from Jumps to if array ended ??? what are 1,2? Are they used? */ { "next", 10, VARREF | RELATIVE_JUMP }, /* 02 */ { NULL, 0, 0 }, /* 03 */ /* Asks user to select one the talk answers Jumps where specified if no answer available */ { "ask", 2, RELATIVE_JUMP }, /* 04 */ /* Pops a value from the top of stack, jump if false, zero or empty array */ { "jne", 2, RELATIVE_JUMP }, /* 05 */ /* jump */ { "jmp", 2, RELATIVE_JUMP }, /* 06 */ /* Pops the top-of-stack string & jumps if the string is NOT the last talk answer ??? first operand seems to be always 1 */ { "jmpa", 4, IMMED | RELATIVE_JUMP}, /* 07 */ { NULL, 0, 0 }, /* 08 */ /* Adds two values on the stack, popping them & pushing result Can be used to add integer to string - in this case integer is converted to string and 2 strings are concatenated */ { "add", 0, 0 }, /* 09 */ /* Decrements second value of the stack by first value, popping them & pushing result */ { "sub", 0, 0 }, /* 0a */ /* Divides second value of the stack by first value, popping them & pushing result */ { "div", 0, 0 }, /* 0b */ /* Multiplies two values on the stack, popping them & pushing result */ { "mul", 0, 0 }, /* 0c */ /* Divides second value of the stack by first value, popping them & pushing reminder */ { "mod", 0, 0 }, /* 0d */ /* Boolean AND on two values on stack, popping them & pushing result Top-of-stack variable is the left one in case of string addition */ { "and", 0, 0 }, /* 0e */ /* Boolean OR on two values on stack, popping them & pushing result */ { "or", 0, 0 }, /* 0f */ /* Inverts a boolean value on top of stack */ { "not", 0, 0 }, /* 10 */ { NULL, 0, 0 }, /* 11 */ /* Pops a stack value to given local variable */ { "pop", 2, VARREF }, /* 12 */ /* Pushes a TRUE boolean value on the stack */ { "push\ttrue", 0, 0 }, /* 13 */ /* Pushes a FALSE boolean value on the stack */ { "push\tfalse", 0, 0 }, /* 14 */ { NULL, 0, 0 }, /* 15 */ /* Pops 2 values from the stack, pushes boolean value - TRUE if (top-of-stack-1) value "?" then top-of-stack (where "?" can be greater, greater or equal etc...) */ { "cmpgt", 0, 0 }, /* 16 */ { "cmplt", 0, 0 }, /* 17 */ { "cmpge", 0, 0 }, /* 18 */ { "cmple", 0, 0 }, /* 19 */ { "cmpne", 0, 0 }, /* 1a */ { NULL, 0, 0 }, /* 1b */ /* Adds a string from data segment to string register current contents */ { "addsi", 2, DATA_STRING }, /* 1c */ /* Pushes a string value given by 16bit string offset in data segment to stack */ { "pushs", 2, DATA_STRING }, /* 1d */ /* Pops specified number of values from stack, builds an array from them & pushes it on the stack Pushes the empty array to top of the stack if operand is 0 */ { "arrc", 2, IMMED }, /* 1e */ /* Pushes immediate 16bit integer to stack */ { "pushi", 2, IMMED }, /* 1f */ { NULL, 0, 0 }, /* 20 */ /* Pushes a local variable on stack */ { "push", 2, VARREF }, /* 21 */ /* Compares 2 values on the stack, pops them & pushes TRUE if they are equal */ { "cmpeq", 0, 0 }, /* 22 */ { NULL, 0, 0 }, /* 23 */ /* Calls a usecode function - function number is 0-based index to externs array */ { "call", 2, VARREF | EXTCALL }, /* 24 */ /* Return from function without result returned on the stack */ { "ret", 0, 0 }, /* 25 */ /* Uses the top-of-stack value to index (1-based) the array variable, pops index & pushes result - the value from the array */ { "aget", 2, VARREF }, /* 26 */ { NULL, 0, 0 }, /* 27 */ { NULL, 0, 0 }, /* 28 */ { NULL, 0, 0 }, /* 29 */ { NULL, 0, 0 }, /* 2a */ { NULL, 0, 0 }, /* 2b */ /* ??? Looks like to be the same as "exit" ??? Suggestion: maybe "exit" is for functions, while "exit2" is for event handlers? */ { "exit2", 0, 0 }, /* 2c */ /* Pop the top-of-stack value & sets it as a return value */ { "popr", 0, 0 }, /* 2d */ /* Opens a new For Each-style enumeration loop. Always followed by "next" opcode??? */ { "enum", 0, 0 }, /* 2e */ /* Adds local variable's string value to string register current contents */ { "addsv", 2, VARREF }, /* 2f */ /* If (top-of-stack - 1) value is in top-of-stack array, pushes true, otherwise pushes false - after popping array & value */ { "in", 0, 0 }, /* 30 */ /* Something strange with 2 varrefs (???) as operands Appears in BG only - in talk to Raymundo in the Theatre - trying to sing a song I -am- the Avatar */ { "???", 4, 0 }, /* 31 */ /* Return with a result returned on the stack */ { "retr", 0, 0 }, /* 32 */ /* Displays the string register value (to current talk, sign, scroll or book), string register emptied */ { "say", 0, 0 }, /* 33 */ { NULL, 0, 0 }, /* 34 */ { NULL, 0, 0 }, /* 35 */ { NULL, 0, 0 }, /* 36 */ { NULL, 0, 0 }, /* 37 */ /* Calls engine's intrinsic function with specified number of parameters (popping them). The return value remains on stack */ { "callis", 3, CALL }, /* 38 */ /* Calls engine's intrinsic function with specified number of parameters (popping them). No return value */ { "calli", 3, CALL }, /* 39 */ { NULL, 0, 0 }, /* 3a */ { NULL, 0, 0 }, /* 3b */ { NULL, 0, 0 }, /* 3c */ { NULL, 0, 0 }, /* 3d */ /* Pushes identifier of the item ( for which the usecode event handler is called ) on the stack */ { "push\titemref", 0, 0 }, /* 3e */ /* Aborts the function & all usecode execution, returning to the engine */ { "exit", 0, 0 }, /* 3f */ /* Removes all answers from the current talk */ { "cla", 0, 0 }, /* 40 */ { NULL, 0, 0 }, /* 41 */ /* Pushes game flag's value (boolean) on the stack */ { "pushf", 2, FLGREF }, /* 42 */ /* Pops the stack value to the game flag (boolean) */ { "popf", 2, FLGREF }, /* 43 */ /* Pushes an immediate byte to the stack */ { "pushbi", 1, IMMED_BYTE }, /* 44 */ { NULL, 0, 0 }, /* 45 */ /* Uses the top-of-stack value to index (1-based) the array variable, (top-of-stack - 1) as the new value, and updates a value in the array slot (local variable specified in the operand) */ { "aput", 2, VARREF }, /* 46 */ /* Call of usecode function - function # is the operand ???Suggestion: functions are divided into event handlers (called by external code and the usecode) and functions (called by usecode only). "calle" is used to call the event handler from the usecode, while "call" is used to call a function */ { "calle", 2, EXTCALL }, /* 47 */ /* Pushes the cause of usecode event handler call on the stack */ /* (double-click on item is be 1, NPC death seems to be 7 in SI and 2 in BG ) */ { "push\teventid", 0, 0 }, /* 48 */ { NULL, 0, 0 }, /* 49 */ /* Pops the value from the stack and adds it to array on the top of stack */ /* or pops both values from the stack, builds an array from them */ /* & pushes it on the stack if neither of them are arrays */ { "arra", 0, 0 }, /* 4a */ /* Pops the top-of-stack value & sets the cause of usecode event handler to it (double-click on item is be 1, NPC death seems to be 7 in SI and 2 in BG ) Used to call event handlers from the usecode */ { "pop\teventid", 0, 0 }, /* 4b */ }; /* Embedded function table for Black Gate */ static const char* bg_func_table[] = { /* Random1(Hi) - Returns a random integer or from 1 to Hi inclusively Used to select a random party member for remarks */ "Random1", /* 0 */ /* ExecuteMacro(itemref, array). Executes a macro for this itemref. Macro is an array of opcodes (bytes) and operands (words) Macro opcodes: either 0x35 or 0x45 - deletes an item (fire caused by the flaming oil) 0x46 - sets item's frame number to integer (rotating crossbeam while opening the portcullis gate) 0x52 - the same as ItemSay() function 0x55 - call a usecode event for the item 0x56 - Guardian's phrase with given number All spells use this function - if current weather is 3 - 606 is called instead of the second part of the spell engine (magic negation field at Ambrosia, Armageddon is blocked after shouting 1st mantra & before shouting second). Macro execution is asynchronous to the commands following ExecuteMacro - ??? macro opcodes are executed one per redraw frame counted??? Macro execution seems to be interruptable by opening inventory. The initial red moongate uses this to grow in height and then call another usecode function. This initial sequence is fired from Iolo's usecode hanlder. */ "ExecuteMacro", /* 1 */ /* ScheduleMacro(itemref, array, delay) The same as above - but schedules a macro for execution later Delay seems to be in frame counter units??? (use a serpent venom on somebody - first raises stats, then - after some time - lower them) Can also shout exclamations - "Call it... Heads... Its tails..." - double-click on money. */ "ScheduleMacro", /* 2 */ /* SwitchTalkTo(itemref, face_frame) - switches conversation to other NPC, selecting one of possible face pictures Shows the face in the bottom of the screen if the face on top was not hidden yet Switching talk to -277 means - huge reg Guardian semi-transparent face */ "SwitchTalkTo", /* 3 */ /* HideNPC(itemref) - hides NPC face away from the conversation */ "HideNPC", /* 4 */ /* AddAnswer(str_or_array) - adds a answer or set of answers to */ /* the set of talk threads suggested */ "AddAnswer", /* 5 */ /* RemoveAnswer(str) - removes a given string from set of talk threads suggested */ "RemoveAnswer", /* 6 */ /* SaveTalkStartNew() - saves the conversation state & starts */ /* new blank set of talk answers suggested */ "SaveTalkStartNew", /* 7 */ /* RestoreTalk() - restores set of answers suggested */ /* as was saved in SaveTalkStartNew() */ "RestoreTalk", /* 8 */ /* EmptyTalk() - removes all talk answers Looks like the same as "cla" opcode */ "EmptyTalk", /* 9 */ /* GetAnswer() - asks user to select one of the talk threads & returns it Practically the same functionality as "ask" opcode */ "GetAnswer", /* a */ /* GetAnswerIndex() - asks user to select one of the talk threads & returns the 1-based index of it instead the text itself */ "GetAnswerIndex", /* b */ /* AskNumber(min, max, step, default) - asks user a number by showing a slider */ /* with given parameters */ "AskNumber", /* c */ /* SetItemType(itemref, type) - changes a type of given item to the new value */ "SetItemType", /* d */ /* AreItemsNearNPC(NPCID, type, distance) - returns boolean whether there are items of such Type at the given distance from the given NPC. Distance -1 means - screen borders */ "AreItemsNearNPC", /* e */ /* PlaySoundEffect(sound_num) - plays a given effect soundtrack */ "PlaySoundEffect", /* f */ /* Random2(lo, hi) - returns a random integer from lo to hi inclusively */ "Random2", /* 10 */ /* GetItemType(itemref) - returns a "type" value of the item */ "GetItemType", /* 11 */ /* GetItemFrame(itemref) - returns a "frame" value of the item */ "GetItemFrame", /* 12 */ /* SetItemFrame(itemref, frame) - sets a "frame" value for the item */ "SetItemFrame", /* 13 */ /* GetItemQuality(itemref) - returns a "quality" value of the item */ "GetItemQuality", /* 14 */ /* SetItemQuality(itemref, quality) - sets a "quality" value for the item (Penumbra's plaque) Returns old quality??? */ "SetItemQuality", /* 15 */ NULL, /* 16 */ NULL, /* 17 */ /* GetItemCoords(itemref) - parameter is itemref as returned by ItemSelectModal(), returns array The array is 2 item's coordinates - array[1], array[2] */ "GetItemCoords", /* 18 */ NULL, /* 19 */ NULL, /* 1a */ /* GetNPCID(itemref) - returns NPCID from Itemref - possibly does-nothing function??? Accepts values like -2 for Spark or -356 for Avatar on input */ "GetNPCID", /* 1b */ /* GetNPCClass(NPCID) - returns a number specifying the NPC class - fighter/sage/shopkeeper etc. Used in exclamations like "Oh my aching back!" 10 seems to be Noble (Finnegan & his aching back :-) ) Or maybe I'm wrong and this is GetNPCActivity??? */ "GetNPCClass", /* 1c */ /* SetNPCActivity(NPCID, activity) - sets an NPC activity 11 - Loiter (leave with "go home") 15 - Wait (leave with "wait here") ??? in cheat menu order? */ "SetNPCActivity", /* 1d */ /* JoinNPC(itemref) - joins NPC to the party This seems to only set Party flag on - the same effect as doing this in cheat mode ???in BG, unusual companions (joined by cheat) will not be shown in Inventory/Ztats gumps. Where this information (whether the NPC is a usual companion) is kept? In SI, they will (I saw Rotoluncia's Ztats - though no 2 keys + a wand usually taken from her when dead in inventory. Trying to display Vasculio's Ztats hung the game) - but headless :-) Once more - it is kept somewhere... */ "JoinNPC", /* 1e */ /* DismissNPC(itemref) - dismisses NPC from the party */ "DismissNPC", /* 1f */ /* GetNPCStat(NPCID, property_id) - returns NPC's statistic value (9 is food level, 0 is Strength, 3 is Hits, ) (1 & 4 seems to be Training & Combat???) Vas Mani (Restoration) spell is a good example */ "GetNPCStat", /* 20 */ /* ChangeNPCStat(itemref, property_id, delta) - increments (or decrements for negative delta) NPC's statistic value. */ "ChangeNPCStat", /* 21 */ /* AvatarNPCID() - returns Avatar's NPC ID */ "AvatarNPCID", /* 22 */ /* GetPartyMembers() - returns the array of NPCs which are party members currently */ /* ??? NPC IDs returned??? */ "GetPartyMembers", /* 23 */ /* CreateItem(Type) - creates an item of given Type, returns itemref Must be followed by SetItemFrame()??? */ "CreateItem", /* 24 */ NULL, /* 25 */ /* InsertNewItem(Coords) Parameter is an array of c */ "InsertNewItem", /* 26 */ /* GetNPCName(npc_id_or_array) - returns an NPC name by NPC ID Returns an array of names if array was specified */ "GetNPCName", /* 27 */ /* Counts the amount of party gold if called as Func28(-357, 644, -359, -359) 644 is for sure the Type of gold heap 649 is for sure the Type of serpent venom 839 for hourglass Last parameter seems to be the frame number of the items - -359 means "any" */ NULL, /* 28 */ /* Returns itemref of the given item in Avatar's (or party's??? - parameter 4???) posessions 0 if no such item Func28(-357, 761, -359, -359) - spellbook. Func28(-357, 839, -359, 0) - Nicodemus's hourglass (known as Hourglass Of Fate in SI). Third parameter is quality */ NULL, /* 29 */ /* GetContainerItems(container_itemref, type, quality, ???) - returns an array */ /* ??? of itemrefs */ "GetContainerItems", /* 2a */ /* Reduces the amount of party gold if called Func2b(delta, 644, -359, -359, true) Reduces the amount of party eggs if called Func2b(delta, 377, -359, 24, true) */ NULL, /* 2b */ /* Increases the amount of party gold if called Func2c(delta, 644, -359, -359, true) Returns false if party is overloaded & cannot accept this */ NULL, /* 2c */ /* Not used at all */ NULL, /* 2d */ /* PlayMusic(song#, itemref) - plays a MIDI music track. */ /* Song# = 255 means - mute the MIDI channel. */ "PlayMusic", /* 2e */ /* IsNPCInParty(npc_id) - returns true if given NPC is in party, */ /* otherwise returns false */ "IsNPCInParty", /* 2f */ /* Takes a Type(???), returns an array of all visible items/NPCs of this type */ NULL, /* 30 */ /* IsNPCxxx(itemref) - returns true if given NPC is ????? */ NULL, /* 31 */ /* DisplaySign(gump#, array_of_strings) - displays a sign/plaque */ /* of given gump number & given text (array of strings or single string). */ "DisplaySign", /* 32 */ /* ItemSelectModal() - switches the engine to cross-cursor "use" mode. Returns an itemref of the item selected by user by single-click. Does not return till user will single-click on something. The entity returned can be treated as array with coords at array[2], array[3] */ "ItemSelectModal", /* 33 */ /* Not used at all */ NULL, /* 34 */ /* ItemsNearItem(itemref, type, distance, ???) - returns an array of items of given Type which are closer then Distance to the item specified by Itemref Parameter 4 is possibly frame number to compare??? Type of -1 means - all NPC??? (Fear spell) (Powder keg & cannon ball near the cannon) */ "ItemsNearItem", /* 35 */ /* Takes an NPCID as a single parameter, seems to return the amount of free space in its inventory */ NULL, /* 36 */ NULL, /* 37 */ /* GetTimeHour() - returns hour part of current game time - 0-23 */ "GetTimeHour", /* 38 */ /* GetTimeMinute() - returns minute part of current game time - 0-59 */ "GetTimeMinute", /* 39 */ /* GetItemRef(NPCID) - returns Itemref from NPCID - possibly does-nothing function??? */ "GetItemRef", /* 3a */ NULL, /* 3b */ /* GetNPCxxx(NPCID) - returns the same??? NPC mode as set in function 3d */ NULL, /* 3c */ /* SetNPCxxx(NPCID, mode) - ???sets some NPC mode often called with mode=2 before entering combat ???alignment */ NULL, /* 3d */ /* TeleportItem(itemref, array) - teleports an NPC array[1] - X coord array[2] - Y coord array[3] - height Help spell calls this with (3a8, 47a, 0) array - LB throne room Recall spell calls this with (5aa, 500, 0) array (House of the Dead) - in some cases. Also interesting location - (217, 489, 0) - back from the Sphere. Function 6cf teleports there is Sphere is not destroyed & party does not posesses item 0x347 (the hourglass, maybe parameter 4 in 0x28 checks the Frame number to check whether the hourglass is enchanted??? BTW - there is a known bug in BG that sometimes you can enter the Sphere with non-enchanted hourglass - cause???) What are these locations? */ "TeleportItem", /* 3e */ /* VanishNPC(NPCID) - only parameter is NPCID, no return value Called in eventid 2 for the plaque - never mind what - and NPC -23 (LB) - plaque falling on LB's head Called on Weston (-69) when LB frees him Called on Batlin (GetNPCID(-26)) when he vanishes, feeling the Cube at Avatar's posession Called on -214 in Vesper - when Yvella want to tell Catherine's father & Mara something.... Called on Kreg/Kraig(-245) after he laughs when invis. potion is given to him Called on Addom (-164) after Brion attaches to crystal & completes the orrery viewer Called on -156 (Balayna???) when Rankin says he did not see Balayna for some time Called on all Scara Brae ghosts in For Each loop when Forsythe jumps into the Well The exact logic is not clear - what appears with the vanished NPC? Where it is teleported??? */ "VanishNPC", /* 3f */ /* ItemSay(itemref, str) - displays a string on the screen near the specified item */ "ItemSay", /* 40 */ NULL, /* 41 */ /* GetItemZCoord(itemref) - returns Z coordinate of the item */ "GetItemZCoord", /* 42 */ /* SetItemZCoord(itemref, coord) - sets a Z coordinate for the item */ "SetItemZCoord", /* 43 */ /* GetWeather() - returns current weather - 0-3 3 seems to negate magic */ "GetWeather", /* 44 */ /* SetWeather(weather) - sets new current weather - 0-3 */ "SetWeather", /* 45 */ /* Sits down NPC??? */ NULL, /* 46 */ /* SummonCreature(Type, boolean) - engine under Kal Bet Xen (Swarm), Kal Xen (???) an Kal Vas Xen (Summon). Summons a creature of given Type. Second parameter is true only for Kal Vas Xen Return value??? */ "SummonCreature", /* 47 */ /* Shows a map of Britannia. Double-click on the map, Vas Wis (Peer) spell or reading the Brommer's Britannia book */ "ShowMap", /* 48 */ /* KillNPC(itemref) - kills the given NPC. Owen's suicide is this function alone. Plaque falling on LB's head - KillNPC, then VanishNPC. Balayna takes the vial from you & dies - this function alone Death bolt spell uses it too. These are all occurences. */ "KillNPC", /* 49 */ /* Some kind of comparing 2 numbers (2 params) - returns boolean Used to compare somebody' Strength to item's Quality */ "???", /* 4a */ /* SetNPCAttackMode(NPCID, mode) - sets a combat mode for the NPC Mode 7 is Fleeing - others are in men Fear spell, using dirty diapers on people (it is the same as Fear spell) - mode 7 LB attacking in an LB cheat room - mode 0 */ "SetNPCAttackMode", /* 4b */ /* SetTargetNPCToAttack(attacker_NPCID, target_NPCID) - sets target NPC to attack ??? how it is called in a cheat menu? Usually called with Avatar as target NPC */ "SetTargetNPCToAttack", /* 4c */ /* CloneNPC(NPCID) - clones an NPC - Clone spell Returns something - return value never used. */ "CloneNPC", /* 4d */ /* Not used at all */ NULL, /* 4e */ /* ShowCrystalBall(coords_array) - shows a crystal ball view of a given world point */ "ShowCrystalBall", /* 4f */ /* ShowWizardEye(parm1, parm2) - shows a view for telescope or Wizard Eye spell For telescope - ShowWizardEye(10000, 1000) For Wizard Eye spell - ShowWizardEye(45, 200) */ "ShowWizardEye", /* 50 */ /* ResurrectNPC(itemref) - resurrects an NPC. Itemref is a dead body's itemref Returns false is cannot resurrect - LB in this case says "Alas..." and then about burial. ???what is the cause of such LB's behaviour? When ResurrectNPC returns false? */ "ResurrectNPC", /* 51 */ /* AddSpellToBook(spellnum, 0, spellbook_itemref) - Adds a new spell to the spellbook Returns false if there was already such spell in the book Maybe calling with 1 (never called such in BG) will remove the spell from the book? */ "AddSpellToBook", /* 52 */ /* ExecuteSprite(sprite, coordx, coordy, speedx, speedy, ???, ???) - executes an explosion-like sprite First parameter is sprite number in SPRITES.VGA speedx & speedy are non zero is the sprite floats away (smoke from smokebomb) Last parameters is usually -1 (not so for smokebomb) */ "ExecuteSprite", /* 53 */ /* Powder keg burst??? */ NULL, /* 54 */ /* DisplayBook(itemref) - Displays book or scroll Text will be displayed further by "say" opcode */ "DisplayBook", /* 55 */ /* StopTime(???) - freezes all NPCs for some time. Parameter is duration???? Type 6be object (Egg???) calls this with its Quality as a parameter on eventid 3 Also called in Stop Time spell with the parameter 100 */ "StopTime", /* 56 */ /* CauseLight(duration) - Glimmer/Light/Great Light spell logic duration is 110 for Glimmer, 500 for Light, 5000 for Great Light */ "CauseLight", /* 57 */ /* itemref as a parameter, returns some boolean... ???NPC is on barge At least true return from this blocks Mark spell - even mantra is not shouted */ "???", /* 58 */ /* CauseEarthquake(???) - causes an earthquake. Parameter is 40 for Armageddon spell & variable for Tremor spell Also called from func 85e (Forsythe jumping in the Well of Souls) - with parameter 15 */ "CauseEarthquake", /* 59 */ /* IsPlayerFemale() - returns 0 if male, 1 if female */ "IsPlayerFemale", /* 5a */ /* CauseArmageddon() - all logic of Armageddon spell except shouting mantras, weather change, earthquake, & setting the game flag which affects Batlin's & LB's behaviour. Walks through the all NPC list & makes all of the Dead with Hits < 0 Called also in LB's cheat room - "Busted, you thieving scoundrel bastard!" */ "CauseArmageddon", /* 5b */ /* Sets NPC to some state - like VanishNPC() or KillNPC() */ "???", /* 5c */ /* CauseBlackout() - darken the whole screen for some time */ "CauseBlackout", /* 5d */ /* ArraySize(a) - returns number of elements in the array */ "ArraySize", /* 5e */ /* Something for Mark spell??? */ "???", /* 5f */ /* Called only once, something in a Recall spell Called after setting activity to 31 (Follow Avatar) to all party members and resetting flag 0x39 (what is it???) No return value, single parameter which is itemref */ NULL, /* 60 */ /* Called only once, parameters are NPC strength, 0, 12, 3 Return value exists but not used */ NULL, /* 61 */ /* IsUnderTheRoof() - returns true if the party is under the roof. Sextant will not work under the roof. Also used in some place (???) where it causes a shout "Try it outside!" */ "IsUnderTheRoof", /* 62 */ /* SetOrreryState(coords_array, status) - sets the state of the planets in Brion's orrery. Coords are usually ordinary orrery coords - array of 2 integers. (59c, b4c) status is a small integer which influences the state of the planets. */ "SetOrreryState", /* 63 */ /* Not used at all */ NULL, /* 64 */ /* GetTimerElapsedHours(timer_number) - returns number of hours of game time elapsed since the time set in the timer. Timer valus are persistent beyound doubt - maybe GAMETIM(A) files? Timer 0x0 - Kliftin at Jhelom making the flag of Honor Timers 0x1 - Bennie in LB's house giving free meal Timers 0x2-0x4 - Martina, Wench and Roberto at Buc. Den Timer 0x5 - called from 0x6c3 code deletes all light sources/candles, serpentine daggers, buckets, victims & bloods - Minoc murder scene. A well-known game bug! Proximity usecode Egg 0x6c3 is just at the center of the murder scene with firing distance of 16 (which is exactly the sawmill entrance) The logic is: if flag 0x122 is not set, set it, and then set the timer 0x5. Else - if the flag is already set and if 24 game hours elapsed from timer 0x5 - delete all murder scene objects in the distance 15 aroung the Egg and the Egg iself. So - entering the sawmill second time after more a day from the first time entering it will delete the murder scene. The bug is that sometimes it deletes just at the first time and the player never sees it and cannot pick a dagger. Timer 0x6 - the same with Alagner's body (victim). Timer 0x8 - poisoning Balayna by Rankin. Timer 0xa - Jaana healing. Another well-known game bug! If you ask Jaana to heal when she is in the party, and if flag 0x29 is false, than the "period" is set to 5. Otherwise, the "period" is set to the time elapsed since timer 0xa. Then, if the period < 4, say "I am sorry..." Otherwise, Jaana heals - this sets flag 0x29 and timer 0xa. The bug is that Jaana heals only once per game - and than always says "I am sorry..." Cause of both bugs: game timers are broken beyound doubt. Seriously. Something like GetTimerElapsedHours for 0xa always returns 0 or at least value < 4 and GetTimerElapsedHours for 0x5 always returns >= 24 Too sad. No chances of fixing it using usecode patches. Timer 0xb - the last thievery act by the Avatar. (where is it set???) These are all used timers. */ "GetTimerElapsedHours", /* 65 */ /* SetTimer(timer_number) - sets the timer value to the current game time */ "SetTimer", /* 66 */ /* Is Avatar wearing a fellowship medallion???? */ NULL, /* 67 */ /* IsMousePresent() - returns true if mouse is present, false otherwise */ "IsMousePresent", /* 68 */ /* GetSpeechTrack() - returns a speech track number previously set by SetSpeech() */ "GetSpeechTrack", /* 69 */ NULL, /* 6a */ NULL, /* 6b */ NULL, /* 6c */ NULL, /* 6d */ NULL, /* 6e */ /* DeleteItem(itemref) - deletes an item */ "DeleteItem", /* 6f */ /* Called only once after initial conversation of just-arrived Avatar with Iolo */ NULL, /* 70 */ NULL, /* 71 */ NULL, /* 72 */ NULL, /* 73 */ NULL, /* 74 */ /* StartEndGame(boolean) - TRUE is successful endgame (wand against the gate), FALSE is unsuccessful (passing through the gate) */ "StartEndGame", /* 75 */ /* FireCannon(cannon_itemref, fire_direction, ball_type, ???, cannon_type, cannon_type) - fires a cannon in specified direction */ "FireCannon", /* 76 */ NULL, /* 77 */ NULL, /* 78 */ NULL, /* 79 */ NULL, /* 7a */ NULL, /* 7b */ NULL, /* 7c */ NULL, /* 7d */ /* PlaySpeech() - plays a speech track set by SetSpeech() */ "PlaySpeech", /* 7e */ NULL, /* 7f */ NULL, /* 80 */ NULL, /* 81 */ NULL, /* 82 */ NULL, /* 83 */ NULL, /* 84 */ NULL, /* 85 */ NULL, /* 86 */ NULL, /* 87 */ /* Function 0x88 - GetNPCFlag(Itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Flag 25 causes people to say "Oink!" Returns boolean Or maybe not only NPC flag? - see the very first function on sails & gangplanks... ??? Suggestion. Flagno 10 is "on barge" flag which is set when the NPC is unmovable and mouse controls barge itself (sitting on ship/carpet/cart). A reasonable one. Needs checking. */ "GetNPCFlag", /* 88 */ /* Function 0x89 - SetNPCFlag(itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Sets flag to true */ "SetNPCFlag", /* 89 */ /* Function 0x8a - ResetNPCFlag(itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Sets flag to false */ "ResetNPCFlag", /* 8a */ NULL, /* 8b */ NULL, /* 8c */ NULL, /* 8d */ NULL, /* 8e */ NULL, /* 8f */ NULL, /* 90 */ NULL, /* 91 */ NULL, /* 92 */ /* Itemref as parameter, returns an array of NPCs which are then passed to ResurrectNPC() called only once */ NULL, /* 93 */ /* Called only for orrery viewer Large orrery coords as parameters, called only once and followed by ShowCrystalBall() at the orrery location */ "SetupOrrery", /* 94 */ /* Some spells like An Flam */ NULL, /* 95 */ /* Appears only in crazy talk after answering copy-protection incorrectly */ NULL /* 96 */ }; /* Embedded function table pointer TODO: set to bg_func_table or si_func_table depending on the command line */ const char** func_table = bg_func_table; int func_table_size = sizeof(bg_func_table); /* Functions */ /* Prints module's data segment */ void process_data_seg(FILE* f, unsigned short ds) { long pos; unsigned short off = 0; unsigned char* p; unsigned char* pp; unsigned char* tempstr; /* Allocate a temporary buffer */ tempstr = malloc(70 + 1); pos = ftell(f); pp = p = malloc(ds); fread(p, 1, ds, f); fseek(f, pos, SEEK_SET); /* Print all strings & their offsets */ while( off < ds ) { int len; unsigned short localoff = 0; /* Print all parts of the string - wrapping them around */ while( (len = ( strlen(pp) > 70 )) ? 70 : strlen(pp) ) { /* TODO! Escape characters if ' is part of the string */ memcpy(tempstr, pp, len); tempstr[len] = '\0'; if( localoff ) printf("\tdb\t\'%s\'\n", tempstr); else printf("%04X\tdb\t\'%s\'\n", off, tempstr); localoff += len; pp += len; } pp++; off += localoff + 1; printf("\tdb\t00\n"); } free(p); free(tempstr); } /* Prints single opcode Return number of bytes to advance the code pointer Prints first characters of strings referenced */ unsigned short print_opcode(unsigned char* ptrc, unsigned short coffset, unsigned char* pdataseg, unsigned short* pextern, unsigned short externsize, unsigned char* opcode_buf, unsigned char* intrinsic_buf, int mute, int count_all_opcodes, int count_all_intrinsic) { unsigned short nbytes; unsigned short i; opcode_desc* pdesc; if( count_all_opcodes ) opcode_buf[*ptrc]++; /* Find the description */ pdesc = ( *ptrc >= ( sizeof(opcode_table) / sizeof( opcode_desc ) ) ) ? NULL : opcode_table + ( *ptrc ); if( pdesc && ( pdesc->mnemonic == NULL ) ) /* Unknown opcode */ pdesc = NULL; if( ( pdesc == NULL ) && !count_all_opcodes ) /* Unknown opcode */ opcode_buf[*ptrc]++; /* Number of bytes to print */ nbytes = pdesc ? ( pdesc->nbytes + 1 ) : 1; /* Print label */ if( !mute ) printf("%04X: ", coffset); /* Print bytes */ for( i = 0; i < nbytes; i++ ) if( !mute ) printf("%02X ", ptrc[i]); if( !mute ) { /* Print mnemonic */ if( nbytes < 4 ) printf("\t"); if( nbytes > 6 ) printf("\n\t\t"); printf("\t%s", pdesc ? pdesc->mnemonic : "???"); } /* Print operands if any */ if( ( nbytes == 1 ) || ( pdesc == NULL ) ) { if( !mute ) printf("\n"); return nbytes; } switch( pdesc->type ) { case IMMED: /* Print immediate operand */ if( !mute ) printf("\t%04XH\t\t\t; %d\n", *(unsigned short*)( ptrc + 1 ), *(short*)( ptrc + 1 )); break; case IMMED_BYTE: /* Print immediate operand */ if( !mute ) printf("\t%02XH\t\t\t; %d\n", (unsigned short)(ptrc[1]), (unsigned short)(ptrc[1])); break; case ( VARREF | RELATIVE_JUMP ): /* NEXT command */ if( !mute ) { /* Print variable reference */ printf("\t[%04X], ", *(unsigned short*)( ptrc + 1 )); /* Print variable reference */ printf("[%04X], ", *(unsigned short*)( ptrc + 3 )); /* Print variable reference */ printf("[%04X], ", *(unsigned short*)( ptrc + 5 )); /* Print variable reference */ printf("[%04X], ", *(unsigned short*)( ptrc + 7 )); /* Print jump desination */ printf("%04X\n", *(short*)( ptrc + 9 ) + (short)coffset + nbytes); } break; case ( IMMED | RELATIVE_JUMP ): /* JMPA command */ if( !mute ) { /* Print immediate operand */ printf("\t%04XH,\t", *(unsigned short*)( ptrc + 1 )); /* Print jump desination */ printf("%04X\t", *(short*)( ptrc + 3 ) + (short)coffset + nbytes); /* Print immediate operand */ printf("; %d\n", *(short*)( ptrc + 1 )); } break; case DATA_STRING: if( !mute ) { unsigned char* pstr; int len; /* Print data string operand - first characters only */ pstr = pdataseg + *(unsigned short*)( ptrc + 1 ); len = strlen(pstr); if( len > 20 ) len = 20 - 3; printf("\t%04XH\t\t\t; ", *(unsigned short*)( ptrc + 1 )); for( i = 0; i < len; i++ ) printf("%c", pstr[i]); if( len < strlen(pstr) ) /* String truncated */ printf("..."); printf("\n"); } break; case RELATIVE_JUMP: /* Print jump desination */ if( !mute ) printf("\t%04X\n", *(short*)( ptrc + 1 ) + (short)coffset + 3); break; case CALL: { /* Print call operand */ unsigned short func = *(unsigned short*)( ptrc + 1 ); if( ( func < ( func_table_size / sizeof(const char *) ) ) && func_table[func] ) { /* Known function */ if( !mute ) printf("\t_%s@%d\t%s; %04X\n", func_table[func], ptrc[3], ( strlen(func_table[func]) > 12 ) ? "" : "\t", func); if( count_all_intrinsic ) intrinsic_buf[func]++; } else { /* Unknown function */ if( func >= 256 ) /* TODO: error handling here */ printf("Unknown intrisinc function greater then 256!\n"); intrinsic_buf[func]++; if( !mute ) printf("\t%04X, %d\n", func, ptrc[3]); } } break; case EXTCALL: case ( VARREF | EXTCALL ): { unsigned short externpos = *(unsigned short*)( ptrc + 1 ); /* Print extern call */ if( pdesc->type & VARREF ) { unsigned short externpos = *(unsigned short*)( ptrc + 1 ); if( externpos < externsize ) { if( !mute ) printf("\textern:[%04X]\t\t; %04XH\n", externpos, pextern[externpos]); } else printf("\tBad extern table!\n"); } else if( !mute ) printf("\textern:%04X\t\t\n", externpos); } break; case VARREF: /* Print variable reference */ if( !mute ) printf("\t[%04X]\n", *(unsigned short*)( ptrc + 1 )); break; case FLGREF: /* Print game flag reference */ if( !mute ) printf("\tflag:[%04X]\n", *(unsigned short*)( ptrc + 1 )); break; default: /* Unknown type */ if( !mute ) printf("\n"); break; } return nbytes; } void process_code_seg(FILE* f, unsigned short ds, unsigned short s, unsigned char* opcode_buf, unsigned char* intrinsic_buf, int mute, int count_all_opcodes, int count_all_intrinsic) { long pos; unsigned short size; unsigned short externsize; unsigned short i; unsigned short offset; unsigned short nbytes; unsigned char* p; unsigned char* pp; unsigned char* pdata; unsigned short* pextern; pos = ftell(f); size = s - ds - sizeof(unsigned short); pp = p = malloc(size); pdata = malloc(ds); fread(pdata, 1, ds, f); if( !mute ) printf("Code segment at file offset %08lXH\n", ftell(f)); fread(p, 1, size, f); fseek(f, pos, SEEK_SET); /* Print code segment header */ if( size < 3 * sizeof(unsigned short) ) { printf("Code segment bad!\n"); free(p); free(pdata); return; } /* Print argument counter */ if( !mute ) printf("\t\t.argc %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); /* Print locals counter */ if( !mute ) printf("\t\t.localc %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); /* Print externs section */ externsize = *(unsigned short*)pp; if( !mute ) printf("\t\t.externsize %04XH\n", externsize); pp += sizeof(unsigned short); if( size < ( ( 3 + externsize ) * sizeof(unsigned short) ) ) { printf("Code segment bad!\n"); free(p); free(pdata); return; } size -= ( ( 3 + externsize ) * sizeof(unsigned short) ); pextern = (unsigned short*)pp; for( i = 0; i < externsize; i++ ) { if( !mute ) printf("\t\t.extern %04XH\n", *(unsigned short*)pp); pp += sizeof(unsigned short); } offset = 0; /* Print opcodes */ while( offset < size ) { nbytes = print_opcode(pp, offset, pdata, pextern, externsize, opcode_buf, intrinsic_buf, mute, count_all_opcodes, count_all_intrinsic); pp += nbytes; offset += nbytes; } free(p); free(pdata); } void process_func(FILE* f, long func, int i, int* found, unsigned char* opcode_buf, unsigned char* intrinsic_buf, int scan_mode, unsigned long opcode, unsigned long intrinsic) { unsigned short s, ds, funcnum; long off, bodyoff; /* Save start offset */ off = ftell(f); /* Read function header */ fread(&funcnum, sizeof(unsigned short), 1, f); fread(&s, sizeof(unsigned short), 1, f); /* Save body offset */ bodyoff = ftell(f); fread(&ds, sizeof(unsigned short), 1, f); if( ( ( func == -1 ) || scan_mode ) && ( opcode == -1 ) && ( intrinsic == -1 ) ) /* Only for general list & scan mode */ printf("\tFunction #%d (%04XH), offset = %08lx, size = %04x, data = %04x\n", i, funcnum, off, s, ds); if( ( funcnum == func ) || scan_mode || ( opcode != -1 ) || ( intrinsic != -1 ) ) { /* Only for matching function or in one of the scan modes */ if( funcnum == func ) { *found = 1; printf("Function at file offset %08lX\n\t.funcnumber\t%04XH\n" "\t.msize\t%04XH\n\t.dsize\t%04XH\n", off, funcnum, s, ds); } /* Dump function contents */ if( !scan_mode && ( opcode == -1 ) && ( intrinsic == -1 ) ) process_data_seg(f, ds); if( opcode != -1 ) memset(opcode_buf, 0, 256); if( intrinsic != -1 ) memset(intrinsic_buf, 0, 256); process_code_seg(f, ds, s, opcode_buf, intrinsic_buf, scan_mode || ( opcode != -1 ) || ( intrinsic != -1 ), ( opcode != -1 ), ( intrinsic != -1 )); if( ( ( opcode != -1 ) && opcode_buf[opcode] > 0 ) || ( ( intrinsic != -1 ) && intrinsic_buf[intrinsic] > 0 ) ) { /* Found */ *found = 1; if( intrinsic != -1 ) printf("\tFound function (%04XH) - %d times\n", funcnum, intrinsic_buf[intrinsic]); else printf("\tFound function (%04XH) - %d times\n", funcnum, opcode_buf[opcode]); } } /* Seek back, then to next function */ fseek(f, bodyoff, SEEK_SET); fseek(f, s, SEEK_CUR); } int main(int ac, char** av) { /* Preset to no match */ unsigned long func = -1; const char* funcstr = NULL; unsigned char* opcode_buf = NULL; unsigned char* intrinsic_buf = NULL; long sz; int i = 0; int found = 0; int mode = 0; unsigned long opcode = -1; unsigned long intrinsic = -1; FILE* f; printf("Ultima 7 usecode disassembler v0.7\n\n"); /* Parse command line */ if( ac == 3 ) { if( !strcmp(av[1], "-o") ) { char* stopstr; /* Opcode search */ opcode = strtoul(av[2], &stopstr, 16); if( stopstr - av[2] < strlen(av[2]) ) opcode = -1; else /* Hex opcode OK */ mode = 4; } else if( !strcmp(av[1], "-i") ) { char* stopstr; /* Intrinsic function search */ intrinsic = strtoul(av[2], &stopstr, 16); if( stopstr - av[2] < strlen(av[2]) ) intrinsic = -1; else /* Hex opcode OK */ mode = 5; } } else if( ac == 2 ) { if( !strcmp(av[1], "-l") ) /* List mode */ mode = 2; else if( !strcmp(av[1], "-c") ) /* Opcode scan mode */ mode = 3; else { char* stopstr; /* Disassembly mode */ funcstr = av[1]; func = strtoul(funcstr, &stopstr, 16); if( stopstr - funcstr < strlen(funcstr) ) /* Invalid number */ func = -1; else mode = 1; } } if( mode == 0 ) { printf("Usage:\n"); printf("\tucdump -l - prints list of all present functions\n"); printf("\tucdump -c - scans the whole usecode file for unknown opcodes\n"); printf("\tucdump -o - prints list of functions which use "); printf("the given opcode\n"); printf("\tucdump -i - prints list of functions which use "); printf("the given intrinsic function\n"); printf("\tucdump - disassembles single function to stdout\n"); return -1; } /* Allocate opcode & intrinsic function buffers */ if( mode != 2 ) { opcode_buf = (unsigned char*)malloc(256); intrinsic_buf = (unsigned char*)malloc(256); if( ( opcode_buf == NULL ) || ( intrinsic_buf == NULL ) ) { /* No memory */ if( opcode_buf ) free(opcode_buf); if( intrinsic_buf ) free(intrinsic_buf); printf("Out of memory\n"); return -2; } /* Zero them */ memset(opcode_buf, 0, 256); memset(intrinsic_buf, 0, 256); } /* Open a usecode file */ #ifdef _WIN32 /* Microsoftism */ f = fopen("usecode", "rb"); #else f = fopen("usecode", "r"); #endif if( f == NULL ) { /* Free the buffers */ if( opcode_buf ) free(opcode_buf); if( intrinsic_buf ) free(intrinsic_buf); printf("Failed to open usecode file\n\n"); return -2; } fseek(f, 0, SEEK_END); sz = ftell(f); fseek(f, 0, SEEK_SET); if( mode == 1 ) printf("Looking for function number %08lx\n\n", func); while( ftell(f) < sz ) { process_func(f, func, i, &found, opcode_buf, intrinsic_buf, ( mode == 3 ), opcode, intrinsic); if( ( ( mode != 4 ) && ( mode !=5 ) ) || found ) i++; if( ( mode == 4 ) || ( mode == 5 ) ) found = 0; } if( func == -1 ) { if( ftell(f) != sz ) printf("Problem, tell = %ld!\n", ftell(f)); printf("Functions: %d\n", i); } if( ( ( mode == 1 ) || ( mode == 4 ) ) && !found ) printf("Function not found.\n"); fclose(f); /* Dump unknowns */ if( ( mode == 1 ) || ( mode == 3 ) ) { if( opcode_buf ) { int found = 0; for( i = 0; i < 255; i++ ) if( opcode_buf[i] ) { if( !found ) { printf("Undefined opcodes found\n"); found = 1; } printf("0x%02lx (%d times)\n", i, opcode_buf[i]); } } if( intrinsic_buf ) { int found = 0; for( i = 0; i < 255; i++ ) if( intrinsic_buf[i] ) { if( !found ) { printf("Undefined intrinsic functions found\n"); found = 1; } printf("0x%02lx (%d times)\n", i, intrinsic_buf[i]); } } } /* Free the buffers */ if( opcode_buf ) free(opcode_buf); if( intrinsic_buf ) free(intrinsic_buf); return 0; } exult-1.2/tools/Makefile.am0000644000175000001440000000241407522604603011373 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/../files -I$(srcdir)/../usecode \ -I$(srcdir)/.. -I$(srcdir)/../shapes -I$(srcdir)/../imagewin \ -I$(srcdir)/../conf $(DEBUG_FLAGS) $(CPPFLAGS) $(SDL_CFLAGS) if HAVE_PNG IPACK = ipack else IPACK = endif if BUILD_TOOLS NOINSTTOOLS = wuc wud mklink rip ucdump cmanip EXTRATOOLS = splitshp shp2pcx textpack else EXTRATOOLS = NOINSTTOOLS = endif bin_PROGRAMS = expack $(EXTRATOOLS) $(IPACK) noinst_PROGRAMS = $(NOINSTTOOLS) expack_SOURCES = \ expack.cc expack_LDADD = \ ../files/libu7file.la \ $(SYSLIBS) ipack_SOURCES = \ ipack.cc ipack_LDADD = \ ../files/libu7file.la \ ../shapes/libshapes.la \ ../imagewin/libimagewin.la \ -lpng -lz $(SYSLIBS) wuc_SOURCES = \ wuc.c \ uctools.h wud_SOURCES = wud.c mklink_SOURCES = mklink.c rip_SOURCES = rip.c #ucdump_SOURCES = ucdump.c shp2pcx_SOURCES = shp2pcx.cc shp2pcx_LDADD = $(SYSLIBS) splitshp_SOURCES = splitshp.cc splitshp_LDADD = $(SYSLIBS) textpack_SOURCES = textpack.cc textpack_LDADD = \ ../files/libu7file.la \ $(SYSLIBS) cmanip_SOURCES = \ cmanip.cc cmanip_LDADD = \ ../conf/libconf.la \ ../files/libu7file.la \ $(SYSLIBS) EXTRA_DIST = \ intrins1.txt \ intrins2.txt \ README \ u7bgflag.txt \ u7siflag.txt \ ucformat.txt \ expack.txt CLEANFILES = *~ exult-1.2/tools/Makefile.in0000644000175000001440000004266710061527051011413 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/../files -I$(srcdir)/../usecode \ -I$(srcdir)/.. -I$(srcdir)/../shapes -I$(srcdir)/../imagewin \ -I$(srcdir)/../conf $(DEBUG_FLAGS) $(CPPFLAGS) $(SDL_CFLAGS) @HAVE_PNG_TRUE@IPACK = ipack @HAVE_PNG_FALSE@IPACK = @BUILD_TOOLS_TRUE@NOINSTTOOLS = wuc wud mklink rip ucdump cmanip @BUILD_TOOLS_FALSE@NOINSTTOOLS = @BUILD_TOOLS_TRUE@EXTRATOOLS = splitshp shp2pcx textpack @BUILD_TOOLS_FALSE@EXTRATOOLS = bin_PROGRAMS = expack $(EXTRATOOLS) $(IPACK) noinst_PROGRAMS = $(NOINSTTOOLS) expack_SOURCES = \ expack.cc expack_LDADD = \ ../files/libu7file.la \ $(SYSLIBS) ipack_SOURCES = \ ipack.cc ipack_LDADD = \ ../files/libu7file.la \ ../shapes/libshapes.la \ ../imagewin/libimagewin.la \ -lpng -lz $(SYSLIBS) wuc_SOURCES = \ wuc.c \ uctools.h wud_SOURCES = wud.c mklink_SOURCES = mklink.c rip_SOURCES = rip.c #ucdump_SOURCES = ucdump.c shp2pcx_SOURCES = shp2pcx.cc shp2pcx_LDADD = $(SYSLIBS) splitshp_SOURCES = splitshp.cc splitshp_LDADD = $(SYSLIBS) textpack_SOURCES = textpack.cc textpack_LDADD = \ ../files/libu7file.la \ $(SYSLIBS) cmanip_SOURCES = \ cmanip.cc cmanip_LDADD = \ ../conf/libconf.la \ ../files/libu7file.la \ $(SYSLIBS) EXTRA_DIST = \ intrins1.txt \ intrins2.txt \ README \ u7bgflag.txt \ u7siflag.txt \ ucformat.txt \ expack.txt CLEANFILES = *~ subdir = tools mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @BUILD_TOOLS_FALSE@@HAVE_PNG_TRUE@bin_PROGRAMS = expack$(EXEEXT) \ @BUILD_TOOLS_FALSE@@HAVE_PNG_TRUE@ ipack$(EXEEXT) @BUILD_TOOLS_FALSE@@HAVE_PNG_FALSE@bin_PROGRAMS = expack$(EXEEXT) @BUILD_TOOLS_TRUE@@HAVE_PNG_TRUE@bin_PROGRAMS = expack$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_TRUE@ splitshp$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_TRUE@ shp2pcx$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_TRUE@ textpack$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_TRUE@ ipack$(EXEEXT) @BUILD_TOOLS_TRUE@@HAVE_PNG_FALSE@bin_PROGRAMS = expack$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_FALSE@ splitshp$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_FALSE@ shp2pcx$(EXEEXT) \ @BUILD_TOOLS_TRUE@@HAVE_PNG_FALSE@ textpack$(EXEEXT) @BUILD_TOOLS_TRUE@noinst_PROGRAMS = wuc$(EXEEXT) wud$(EXEEXT) \ @BUILD_TOOLS_TRUE@ mklink$(EXEEXT) rip$(EXEEXT) ucdump$(EXEEXT) \ @BUILD_TOOLS_TRUE@ cmanip$(EXEEXT) @BUILD_TOOLS_FALSE@noinst_PROGRAMS = PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_cmanip_OBJECTS = cmanip.$(OBJEXT) cmanip_OBJECTS = $(am_cmanip_OBJECTS) cmanip_DEPENDENCIES = ../conf/libconf.la ../files/libu7file.la cmanip_LDFLAGS = am_expack_OBJECTS = expack.$(OBJEXT) expack_OBJECTS = $(am_expack_OBJECTS) expack_DEPENDENCIES = ../files/libu7file.la expack_LDFLAGS = am_ipack_OBJECTS = ipack.$(OBJEXT) ipack_OBJECTS = $(am_ipack_OBJECTS) ipack_DEPENDENCIES = ../files/libu7file.la ../shapes/libshapes.la \ ../imagewin/libimagewin.la ipack_LDFLAGS = am_mklink_OBJECTS = mklink.$(OBJEXT) mklink_OBJECTS = $(am_mklink_OBJECTS) mklink_LDADD = $(LDADD) mklink_DEPENDENCIES = mklink_LDFLAGS = am_rip_OBJECTS = rip.$(OBJEXT) rip_OBJECTS = $(am_rip_OBJECTS) rip_LDADD = $(LDADD) rip_DEPENDENCIES = rip_LDFLAGS = am_shp2pcx_OBJECTS = shp2pcx.$(OBJEXT) shp2pcx_OBJECTS = $(am_shp2pcx_OBJECTS) shp2pcx_DEPENDENCIES = shp2pcx_LDFLAGS = am_splitshp_OBJECTS = splitshp.$(OBJEXT) splitshp_OBJECTS = $(am_splitshp_OBJECTS) splitshp_DEPENDENCIES = splitshp_LDFLAGS = am_textpack_OBJECTS = textpack.$(OBJEXT) textpack_OBJECTS = $(am_textpack_OBJECTS) textpack_DEPENDENCIES = ../files/libu7file.la textpack_LDFLAGS = ucdump_SOURCES = ucdump.c ucdump_OBJECTS = ucdump.$(OBJEXT) ucdump_LDADD = $(LDADD) ucdump_DEPENDENCIES = ucdump_LDFLAGS = am_wuc_OBJECTS = wuc.$(OBJEXT) wuc_OBJECTS = $(am_wuc_OBJECTS) wuc_LDADD = $(LDADD) wuc_DEPENDENCIES = wuc_LDFLAGS = am_wud_OBJECTS = wud.$(OBJEXT) wud_OBJECTS = $(am_wud_OBJECTS) wud_LDADD = $(LDADD) wud_DEPENDENCIES = wud_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/cmanip.Po $(DEPDIR)/expack.Po \ @AMDEP_TRUE@ $(DEPDIR)/ipack.Po $(DEPDIR)/mklink.Po \ @AMDEP_TRUE@ $(DEPDIR)/rip.Po $(DEPDIR)/shp2pcx.Po \ @AMDEP_TRUE@ $(DEPDIR)/splitshp.Po $(DEPDIR)/textpack.Po \ @AMDEP_TRUE@ $(DEPDIR)/ucdump.Po $(DEPDIR)/wuc.Po \ @AMDEP_TRUE@ $(DEPDIR)/wud.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ DIST_SOURCES = $(cmanip_SOURCES) $(expack_SOURCES) $(ipack_SOURCES) \ $(mklink_SOURCES) $(rip_SOURCES) $(shp2pcx_SOURCES) \ $(splitshp_SOURCES) $(textpack_SOURCES) ucdump.c $(wuc_SOURCES) \ $(wud_SOURCES) DIST_COMMON = README Makefile.am Makefile.in SOURCES = $(cmanip_SOURCES) $(expack_SOURCES) $(ipack_SOURCES) $(mklink_SOURCES) $(rip_SOURCES) $(shp2pcx_SOURCES) $(splitshp_SOURCES) $(textpack_SOURCES) ucdump.c $(wuc_SOURCES) $(wud_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu tools/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) cmanip$(EXEEXT): $(cmanip_OBJECTS) $(cmanip_DEPENDENCIES) @rm -f cmanip$(EXEEXT) $(CXXLINK) $(cmanip_LDFLAGS) $(cmanip_OBJECTS) $(cmanip_LDADD) $(LIBS) expack$(EXEEXT): $(expack_OBJECTS) $(expack_DEPENDENCIES) @rm -f expack$(EXEEXT) $(CXXLINK) $(expack_LDFLAGS) $(expack_OBJECTS) $(expack_LDADD) $(LIBS) ipack$(EXEEXT): $(ipack_OBJECTS) $(ipack_DEPENDENCIES) @rm -f ipack$(EXEEXT) $(CXXLINK) $(ipack_LDFLAGS) $(ipack_OBJECTS) $(ipack_LDADD) $(LIBS) mklink$(EXEEXT): $(mklink_OBJECTS) $(mklink_DEPENDENCIES) @rm -f mklink$(EXEEXT) $(LINK) $(mklink_LDFLAGS) $(mklink_OBJECTS) $(mklink_LDADD) $(LIBS) rip$(EXEEXT): $(rip_OBJECTS) $(rip_DEPENDENCIES) @rm -f rip$(EXEEXT) $(LINK) $(rip_LDFLAGS) $(rip_OBJECTS) $(rip_LDADD) $(LIBS) shp2pcx$(EXEEXT): $(shp2pcx_OBJECTS) $(shp2pcx_DEPENDENCIES) @rm -f shp2pcx$(EXEEXT) $(CXXLINK) $(shp2pcx_LDFLAGS) $(shp2pcx_OBJECTS) $(shp2pcx_LDADD) $(LIBS) splitshp$(EXEEXT): $(splitshp_OBJECTS) $(splitshp_DEPENDENCIES) @rm -f splitshp$(EXEEXT) $(CXXLINK) $(splitshp_LDFLAGS) $(splitshp_OBJECTS) $(splitshp_LDADD) $(LIBS) textpack$(EXEEXT): $(textpack_OBJECTS) $(textpack_DEPENDENCIES) @rm -f textpack$(EXEEXT) $(CXXLINK) $(textpack_LDFLAGS) $(textpack_OBJECTS) $(textpack_LDADD) $(LIBS) ucdump$(EXEEXT): $(ucdump_OBJECTS) $(ucdump_DEPENDENCIES) @rm -f ucdump$(EXEEXT) $(LINK) $(ucdump_LDFLAGS) $(ucdump_OBJECTS) $(ucdump_LDADD) $(LIBS) wuc$(EXEEXT): $(wuc_OBJECTS) $(wuc_DEPENDENCIES) @rm -f wuc$(EXEEXT) $(LINK) $(wuc_LDFLAGS) $(wuc_OBJECTS) $(wuc_LDADD) $(LIBS) wud$(EXEEXT): $(wud_OBJECTS) $(wud_DEPENDENCIES) @rm -f wud$(EXEEXT) $(LINK) $(wud_LDFLAGS) $(wud_OBJECTS) $(wud_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/cmanip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/expack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ipack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mklink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/rip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shp2pcx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/splitshp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/textpack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucdump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/wuc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/wud.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .c.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$< .c.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `cygpath -w $<` .c.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CCDEPMODE = @CCDEPMODE@ .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: $(mkinstalldirs) $(DESTDIR)$(bindir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-binPROGRAMS uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-noinstPROGRAMS distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-binPROGRAMS install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool tags uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/tools/u7siflag.txt0000644000175000001440000003077007132374315011630 Flag times-used hexadecimal (decimal) 0000:0003 ( 3 ) 0001:0003 ( 3 ) 0002:0000 ( 0 ) 0003:0002 ( 2 ) 0004:0054 ( 84 ) 0005:0003 ( 3 ) 0006:000E ( 14 ) 0007:009F ( 159 ) 0008:0039 ( 57 ) 0009:0037 ( 55 ) 000A:0038 ( 56 ) 000B:0001 ( 1 ) 000C:0002 ( 2 ) 000D:0003 ( 3 ) 000E:0003 ( 3 ) 000F:0005 ( 5 ) 0010:0004 ( 4 ) 0011:0004 ( 4 ) 0012:0000 ( 0 ) 0013:0005 ( 5 ) 0014:0000 ( 0 ) 0015:0006 ( 6 ) 0016:0005 ( 5 ) 0017:0005 ( 5 ) 0018:0006 ( 6 ) 0019:000A ( 10 ) 001A:0002 ( 2 ) 001B:0002 ( 2 ) 001C:0002 ( 2 ) 001D:0002 ( 2 ) 001E:0002 ( 2 ) 001F:0002 ( 2 ) 0020:0002 ( 2 ) 0021:0002 ( 2 ) 0022:0002 ( 2 ) 0023:0002 ( 2 ) 0024:0002 ( 2 ) 0025:0002 ( 2 ) 0026:0002 ( 2 ) 0027:0002 ( 2 ) 0028:0002 ( 2 ) 0029:0000 ( 0 ) 002A:0008 ( 8 ) 002B:0000 ( 0 ) 002C:0015 ( 21 ) 002D:000A ( 10 ) 002E:0000 ( 0 ) 002F:0005 ( 5 ) 0030:0000 ( 0 ) 0031:0000 ( 0 ) 0032:0006 ( 6 ) 0033:0003 ( 3 ) 0034:0000 ( 0 ) 0035:0002 ( 2 ) 0036:0001 ( 1 ) 0037:0000 ( 0 ) 0038:0026 ( 38 ) 0039:0000 ( 0 ) 003A:0000 ( 0 ) 003B:0002 ( 2 ) 003C:0008 ( 8 ) 003D:0005 ( 5 ) 003E:0045 ( 69 ) 003F:0002 ( 2 ) 0040:0000 ( 0 ) 0041:0008 ( 8 ) 0042:0002 ( 2 ) 0043:0004 ( 4 ) 0044:0011 ( 17 ) 0045:0015 ( 21 ) 0046:0002 ( 2 ) 0047:0006 ( 6 ) 0048:0032 ( 50 ) 0049:0000 ( 0 ) 004A:001C ( 28 ) 004B:0000 ( 0 ) 004C:0005 ( 5 ) 004D:0000 ( 0 ) 004E:0006 ( 6 ) 004F:0000 ( 0 ) 0050:0000 ( 0 ) 0051:0000 ( 0 ) 0052:0000 ( 0 ) 0053:0002 ( 2 ) 0054:0004 ( 4 ) 0055:0003 ( 3 ) 0056:0001 ( 1 ) 0057:0001 ( 1 ) 0058:0002 ( 2 ) 0059:0001 ( 1 ) 005A:000C ( 12 ) 005B:0009 ( 9 ) 005C:0000 ( 0 ) 005D:0000 ( 0 ) 005E:0000 ( 0 ) 005F:0006 ( 6 ) 0060:0005 ( 5 ) 0061:0007 ( 7 ) 0062:0000 ( 0 ) 0063:0000 ( 0 ) 0064:0000 ( 0 ) 0065:0000 ( 0 ) 0066:0000 ( 0 ) 0067:0000 ( 0 ) 0068:0000 ( 0 ) 0069:0001 ( 1 ) 006A:0000 ( 0 ) 006B:0000 ( 0 ) 006C:0000 ( 0 ) 006D:0000 ( 0 ) 006E:0000 ( 0 ) 006F:0000 ( 0 ) 0070:0000 ( 0 ) 0071:0000 ( 0 ) 0072:0001 ( 1 ) 0073:0000 ( 0 ) 0074:0000 ( 0 ) 0075:0000 ( 0 ) 0076:0006 ( 6 ) 0077:0000 ( 0 ) 0078:000D ( 13 ) 0079:0008 ( 8 ) 007A:0001 ( 1 ) 007B:0003 ( 3 ) 007C:0004 ( 4 ) 007D:0004 ( 4 ) 007E:000B ( 11 ) 007F:0005 ( 5 ) 0080:0002 ( 2 ) 0081:0000 ( 0 ) 0082:0004 ( 4 ) 0083:0013 ( 19 ) 0084:000C ( 12 ) 0085:0005 ( 5 ) 0086:0000 ( 0 ) 0087:0000 ( 0 ) 0088:0000 ( 0 ) 0089:0000 ( 0 ) 008A:0004 ( 4 ) 008B:0004 ( 4 ) 008C:0002 ( 2 ) 008D:0003 ( 3 ) 008E:0001 ( 1 ) 008F:0002 ( 2 ) 0090:0002 ( 2 ) 0091:000B ( 11 ) 0092:0014 ( 20 ) 0093:0007 ( 7 ) 0094:0003 ( 3 ) 0095:0005 ( 5 ) 0096:0002 ( 2 ) 0097:0002 ( 2 ) 0098:0008 ( 8 ) 0099:0003 ( 3 ) 009A:0002 ( 2 ) 009B:0003 ( 3 ) 009C:0002 ( 2 ) 009D:0002 ( 2 ) 009E:0003 ( 3 ) 009F:0003 ( 3 ) 00A0:0002 ( 2 ) 00A1:0002 ( 2 ) 00A2:0002 ( 2 ) 00A3:0002 ( 2 ) 00A4:0003 ( 3 ) 00A5:000A ( 10 ) 00A6:0003 ( 3 ) 00A7:0002 ( 2 ) 00A8:0002 ( 2 ) 00A9:0004 ( 4 ) 00AA:0002 ( 2 ) 00AB:0000 ( 0 ) 00AC:0002 ( 2 ) 00AD:0002 ( 2 ) 00AE:0002 ( 2 ) 00AF:0003 ( 3 ) 00B0:0003 ( 3 ) 00B1:0003 ( 3 ) 00B2:0005 ( 5 ) 00B3:0003 ( 3 ) 00B4:0007 ( 7 ) 00B5:0002 ( 2 ) 00B6:0003 ( 3 ) 00B7:0007 ( 7 ) 00B8:0003 ( 3 ) 00B9:0002 ( 2 ) 00BA:0002 ( 2 ) 00BB:0002 ( 2 ) 00BC:0002 ( 2 ) 00BD:0002 ( 2 ) 00BE:0003 ( 3 ) 00BF:0003 ( 3 ) 00C0:0006 ( 6 ) 00C1:0002 ( 2 ) 00C2:0002 ( 2 ) 00C3:0000 ( 0 ) 00C4:0002 ( 2 ) 00C5:0002 ( 2 ) 00C6:0002 ( 2 ) 00C7:0002 ( 2 ) 00C8:0003 ( 3 ) 00C9:0002 ( 2 ) 00CA:0004 ( 4 ) 00CB:0001 ( 1 ) 00CC:0007 ( 7 ) 00CD:0002 ( 2 ) 00CE:0008 ( 8 ) 00CF:000A ( 10 ) 00D0:0006 ( 6 ) 00D1:0006 ( 6 ) 00D2:0006 ( 6 ) 00D3:0009 ( 9 ) 00D4:000A ( 10 ) 00D5:000E ( 14 ) 00D6:0001 ( 1 ) 00D7:0005 ( 5 ) 00D8:0002 ( 2 ) 00D9:000C ( 12 ) 00DA:0003 ( 3 ) 00DB:000F ( 15 ) 00DC:0004 ( 4 ) 00DD:0007 ( 7 ) 00DE:0004 ( 4 ) 00DF:0003 ( 3 ) 00E0:0002 ( 2 ) 00E1:0002 ( 2 ) 00E2:000F ( 15 ) 00E3:0008 ( 8 ) 00E4:0002 ( 2 ) 00E5:0002 ( 2 ) 00E6:000F ( 15 ) 00E7:0005 ( 5 ) 00E8:000A ( 10 ) 00E9:0005 ( 5 ) 00EA:001C ( 28 ) 00EB:0007 ( 7 ) 00EC:0005 ( 5 ) 00ED:0002 ( 2 ) 00EE:0002 ( 2 ) 00EF:0009 ( 9 ) 00F0:0004 ( 4 ) 00F1:0004 ( 4 ) 00F2:0002 ( 2 ) 00F3:0002 ( 2 ) 00F4:0001 ( 1 ) 00F5:0001 ( 1 ) 00F6:0004 ( 4 ) 00F7:0000 ( 0 ) 00F8:0000 ( 0 ) 00F9:0000 ( 0 ) 00FA:0002 ( 2 ) 00FB:0002 ( 2 ) 00FC:0002 ( 2 ) 00FD:0004 ( 4 ) 00FE:0002 ( 2 ) 00FF:0007 ( 7 ) 0100:0002 ( 2 ) 0101:0000 ( 0 ) 0102:0000 ( 0 ) 0103:0002 ( 2 ) 0104:0003 ( 3 ) 0105:0000 ( 0 ) 0106:0003 ( 3 ) 0107:0000 ( 0 ) 0108:0002 ( 2 ) 0109:0000 ( 0 ) 010A:0002 ( 2 ) 010B:0003 ( 3 ) 010C:0003 ( 3 ) 010D:0000 ( 0 ) 010E:0003 ( 3 ) 010F:0002 ( 2 ) 0110:000B ( 11 ) 0111:0005 ( 5 ) 0112:0003 ( 3 ) 0113:0002 ( 2 ) 0114:0005 ( 5 ) 0115:0009 ( 9 ) 0116:0002 ( 2 ) 0117:0002 ( 2 ) 0118:0003 ( 3 ) 0119:0002 ( 2 ) 011A:0001 ( 1 ) 011B:0001 ( 1 ) 011C:0003 ( 3 ) 011D:0006 ( 6 ) 011E:0002 ( 2 ) 011F:0009 ( 9 ) 0120:0002 ( 2 ) 0121:0006 ( 6 ) 0122:0006 ( 6 ) 0123:0006 ( 6 ) 0124:0000 ( 0 ) 0125:0002 ( 2 ) 0126:0000 ( 0 ) 0127:0001 ( 1 ) 0128:000A ( 10 ) 0129:0003 ( 3 ) 012A:0002 ( 2 ) 012B:0004 ( 4 ) 012C:0000 ( 0 ) 012D:0002 ( 2 ) 012E:0003 ( 3 ) 012F:0003 ( 3 ) 0130:0002 ( 2 ) 0131:0002 ( 2 ) 0132:0003 ( 3 ) 0133:0002 ( 2 ) 0134:0002 ( 2 ) 0135:0007 ( 7 ) 0136:0005 ( 5 ) 0137:0002 ( 2 ) 0138:0000 ( 0 ) 0139:0002 ( 2 ) 013A:0002 ( 2 ) 013B:0003 ( 3 ) 013C:0006 ( 6 ) 013D:0003 ( 3 ) 013E:0003 ( 3 ) 013F:0004 ( 4 ) 0140:0002 ( 2 ) 0141:0003 ( 3 ) 0142:0004 ( 4 ) 0143:0003 ( 3 ) 0144:0002 ( 2 ) 0145:0003 ( 3 ) 0146:0002 ( 2 ) 0147:0002 ( 2 ) 0148:0004 ( 4 ) 0149:0003 ( 3 ) 014A:0002 ( 2 ) 014B:0002 ( 2 ) 014C:0005 ( 5 ) 014D:0003 ( 3 ) 014E:0017 ( 23 ) 014F:0005 ( 5 ) 0150:0002 ( 2 ) 0151:0001 ( 1 ) 0152:0004 ( 4 ) 0153:0000 ( 0 ) 0154:0000 ( 0 ) 0155:0002 ( 2 ) 0156:0001 ( 1 ) 0157:0002 ( 2 ) 0158:0002 ( 2 ) 0159:0000 ( 0 ) 015A:0000 ( 0 ) 015B:0004 ( 4 ) 015C:0005 ( 5 ) 015D:0006 ( 6 ) 015E:0001 ( 1 ) 015F:0002 ( 2 ) 0160:0005 ( 5 ) 0161:0005 ( 5 ) 0162:0005 ( 5 ) 0163:0005 ( 5 ) 0164:0002 ( 2 ) 0165:0003 ( 3 ) 0166:0001 ( 1 ) 0167:0003 ( 3 ) 0168:0005 ( 5 ) 0169:0003 ( 3 ) 016A:0002 ( 2 ) 016B:0003 ( 3 ) 016C:0004 ( 4 ) 016D:0007 ( 7 ) 016E:002E ( 46 ) 016F:000D ( 13 ) 0170:005B ( 91 ) 0171:0015 ( 21 ) 0172:0044 ( 68 ) 0173:000F ( 15 ) 0174:0010 ( 16 ) 0175:000F ( 15 ) 0176:0008 ( 8 ) 0177:0009 ( 9 ) 0178:0009 ( 9 ) 0179:0009 ( 9 ) 017A:0008 ( 8 ) 017B:0003 ( 3 ) 017C:0008 ( 8 ) 017D:0009 ( 9 ) 017E:0009 ( 9 ) 017F:0009 ( 9 ) 0180:0008 ( 8 ) 0181:0008 ( 8 ) 0182:0009 ( 9 ) 0183:0000 ( 0 ) 0184:0000 ( 0 ) 0185:0000 ( 0 ) 0186:0000 ( 0 ) 0187:0002 ( 2 ) 0188:0000 ( 0 ) 0189:0002 ( 2 ) 018A:0002 ( 2 ) 018B:0004 ( 4 ) 018C:0003 ( 3 ) 018D:0002 ( 2 ) 018E:0002 ( 2 ) 018F:0007 ( 7 ) 0190:0008 ( 8 ) 0191:0002 ( 2 ) 0192:0002 ( 2 ) 0193:0002 ( 2 ) 0194:0002 ( 2 ) 0195:0002 ( 2 ) 0196:0002 ( 2 ) 0197:0002 ( 2 ) 0198:0002 ( 2 ) 0199:0001 ( 1 ) 019A:0001 ( 1 ) 019B:0002 ( 2 ) 019C:0002 ( 2 ) 019D:0002 ( 2 ) 019E:0002 ( 2 ) 019F:0001 ( 1 ) 01A0:0002 ( 2 ) 01A1:0003 ( 3 ) 01A2:0003 ( 3 ) 01A3:0003 ( 3 ) 01A4:0003 ( 3 ) 01A5:0005 ( 5 ) 01A6:0003 ( 3 ) 01A7:0001 ( 1 ) 01A8:0004 ( 4 ) 01A9:0002 ( 2 ) 01AA:0002 ( 2 ) 01AB:0002 ( 2 ) 01AC:0002 ( 2 ) 01AD:0002 ( 2 ) 01AE:0001 ( 1 ) 01AF:0002 ( 2 ) 01B0:0002 ( 2 ) 01B1:0002 ( 2 ) 01B2:0005 ( 5 ) 01B3:0006 ( 6 ) 01B4:0002 ( 2 ) 01B5:0002 ( 2 ) 01B6:0003 ( 3 ) 01B7:0006 ( 6 ) 01B8:0008 ( 8 ) 01B9:0003 ( 3 ) 01BA:0003 ( 3 ) 01BB:000A ( 10 ) 01BC:0007 ( 7 ) 01BD:0005 ( 5 ) 01BE:0003 ( 3 ) 01BF:0002 ( 2 ) 01C0:0002 ( 2 ) 01C1:0002 ( 2 ) 01C2:0003 ( 3 ) 01C3:0006 ( 6 ) 01C4:0003 ( 3 ) 01C5:0002 ( 2 ) 01C6:0002 ( 2 ) 01C7:0002 ( 2 ) 01C8:0002 ( 2 ) 01C9:0003 ( 3 ) 01CA:0001 ( 1 ) 01CB:0005 ( 5 ) 01CC:0012 ( 18 ) 01CD:0006 ( 6 ) 01CE:0005 ( 5 ) 01CF:0001 ( 1 ) 01D0:0000 ( 0 ) 01D1:0004 ( 4 ) 01D2:0000 ( 0 ) 01D3:000B ( 11 ) 01D4:0009 ( 9 ) 01D5:000B ( 11 ) 01D6:0009 ( 9 ) 01D7:0009 ( 9 ) 01D8:000B ( 11 ) 01D9:0002 ( 2 ) 01DA:0000 ( 0 ) 01DB:0000 ( 0 ) 01DC:0000 ( 0 ) 01DD:0000 ( 0 ) 01DE:0000 ( 0 ) 01DF:0000 ( 0 ) 01E0:0003 ( 3 ) 01E1:0004 ( 4 ) 01E2:0005 ( 5 ) 01E3:0005 ( 5 ) 01E4:0001 ( 1 ) 01E5:0006 ( 6 ) 01E6:0003 ( 3 ) 01E7:0005 ( 5 ) 01E8:0002 ( 2 ) 01E9:0003 ( 3 ) 01EA:0002 ( 2 ) 01EB:0005 ( 5 ) 01EC:0005 ( 5 ) 01ED:0004 ( 4 ) 01EE:0004 ( 4 ) 01EF:0001 ( 1 ) 01F0:0004 ( 4 ) 01F1:0004 ( 4 ) 01F2:0004 ( 4 ) 01F3:0008 ( 8 ) 01F4:0004 ( 4 ) 01F5:0003 ( 3 ) 01F6:0003 ( 3 ) 01F7:0003 ( 3 ) 01F8:0007 ( 7 ) 01F9:0003 ( 3 ) 01FA:0002 ( 2 ) 01FB:0007 ( 7 ) 01FC:0003 ( 3 ) 01FD:0002 ( 2 ) 01FE:0009 ( 9 ) 01FF:0003 ( 3 ) 0200:0002 ( 2 ) 0201:0004 ( 4 ) 0202:0006 ( 6 ) 0203:0003 ( 3 ) 0204:0003 ( 3 ) 0205:0003 ( 3 ) 0206:0001 ( 1 ) 0207:0003 ( 3 ) 0208:0002 ( 2 ) 0209:0002 ( 2 ) 020A:0002 ( 2 ) 020B:0002 ( 2 ) 020C:0002 ( 2 ) 020D:0002 ( 2 ) 020E:0001 ( 1 ) 020F:0001 ( 1 ) 0210:0001 ( 1 ) 0211:0004 ( 4 ) 0212:0005 ( 5 ) 0213:0001 ( 1 ) 0214:0002 ( 2 ) 0215:000B ( 11 ) 0216:0003 ( 3 ) 0217:0002 ( 2 ) 0218:0002 ( 2 ) 0219:0002 ( 2 ) 021A:0003 ( 3 ) 021B:0004 ( 4 ) 021C:0008 ( 8 ) 021D:0008 ( 8 ) 021E:0004 ( 4 ) 021F:0004 ( 4 ) 0220:0004 ( 4 ) 0221:0001 ( 1 ) 0222:0001 ( 1 ) 0223:0002 ( 2 ) 0224:0002 ( 2 ) 0225:0001 ( 1 ) 0226:0003 ( 3 ) 0227:0004 ( 4 ) 0228:0003 ( 3 ) 0229:0002 ( 2 ) 022A:0002 ( 2 ) 022B:0005 ( 5 ) 022C:0003 ( 3 ) 022D:0004 ( 4 ) 022E:0008 ( 8 ) 022F:0008 ( 8 ) 0230:0008 ( 8 ) 0231:0008 ( 8 ) 0232:0008 ( 8 ) 0233:0007 ( 7 ) 0234:0002 ( 2 ) 0235:0000 ( 0 ) 0236:0006 ( 6 ) 0237:0005 ( 5 ) 0238:0002 ( 2 ) 0239:0006 ( 6 ) 023A:0008 ( 8 ) 023B:0002 ( 2 ) 023C:0003 ( 3 ) 023D:0004 ( 4 ) 023E:000A ( 10 ) 023F:0006 ( 6 ) 0240:0006 ( 6 ) 0241:0006 ( 6 ) 0242:0006 ( 6 ) 0243:0005 ( 5 ) 0244:0005 ( 5 ) 0245:0005 ( 5 ) 0246:0005 ( 5 ) 0247:0005 ( 5 ) 0248:0008 ( 8 ) 0249:0000 ( 0 ) 024A:0004 ( 4 ) 024B:0002 ( 2 ) 024C:0002 ( 2 ) 024D:0002 ( 2 ) 024E:0002 ( 2 ) 024F:0004 ( 4 ) 0250:0005 ( 5 ) 0251:0002 ( 2 ) 0252:0002 ( 2 ) 0253:0004 ( 4 ) 0254:0003 ( 3 ) 0255:0003 ( 3 ) 0256:0002 ( 2 ) 0257:0002 ( 2 ) 0258:0002 ( 2 ) 0259:0002 ( 2 ) 025A:0000 ( 0 ) 025B:0004 ( 4 ) 025C:0002 ( 2 ) 025D:0004 ( 4 ) 025E:0007 ( 7 ) 025F:0005 ( 5 ) 0260:0003 ( 3 ) 0261:0002 ( 2 ) 0262:0006 ( 6 ) 0263:0004 ( 4 ) 0264:0002 ( 2 ) 0265:0002 ( 2 ) 0266:0000 ( 0 ) 0267:0004 ( 4 ) 0268:0002 ( 2 ) 0269:0002 ( 2 ) 026A:0003 ( 3 ) 026B:0004 ( 4 ) 026C:0002 ( 2 ) 026D:0004 ( 4 ) 026E:0003 ( 3 ) 026F:000E ( 14 ) 0270:0006 ( 6 ) 0271:0003 ( 3 ) 0272:0003 ( 3 ) 0273:0003 ( 3 ) 0274:0004 ( 4 ) 0275:0002 ( 2 ) 0276:0002 ( 2 ) 0277:0000 ( 0 ) 0278:0003 ( 3 ) 0279:0006 ( 6 ) 027A:0006 ( 6 ) 027B:0005 ( 5 ) 027C:0005 ( 5 ) 027D:0006 ( 6 ) 027E:0005 ( 5 ) 027F:0006 ( 6 ) 0280:0006 ( 6 ) 0281:0005 ( 5 ) 0282:0006 ( 6 ) 0283:0006 ( 6 ) 0284:0005 ( 5 ) 0285:0009 ( 9 ) 0286:0000 ( 0 ) 0287:0005 ( 5 ) 0288:0005 ( 5 ) 0289:0007 ( 7 ) 028A:0007 ( 7 ) 028B:0006 ( 6 ) 028C:000C ( 12 ) 028D:000A ( 10 ) 028E:0009 ( 9 ) 028F:0014 ( 20 ) 0290:000C ( 12 ) 0291:0009 ( 9 ) 0292:000C ( 12 ) 0293:0012 ( 18 ) 0294:000A ( 10 ) 0295:000A ( 10 ) 0296:0009 ( 9 ) 0297:000D ( 13 ) 0298:0002 ( 2 ) 0299:0007 ( 7 ) 029A:000A ( 10 ) 029B:000C ( 12 ) 029C:0008 ( 8 ) 029D:0008 ( 8 ) 029E:0002 ( 2 ) 029F:0001 ( 1 ) 02A0:0005 ( 5 ) 02A1:0003 ( 3 ) 02A2:0002 ( 2 ) 02A3:0002 ( 2 ) 02A4:0002 ( 2 ) 02A5:0002 ( 2 ) 02A6:0002 ( 2 ) 02A7:0002 ( 2 ) 02A8:0002 ( 2 ) 02A9:0003 ( 3 ) 02AA:0003 ( 3 ) 02AB:0003 ( 3 ) 02AC:0003 ( 3 ) 02AD:0003 ( 3 ) 02AE:0003 ( 3 ) 02AF:0003 ( 3 ) 02B0:0003 ( 3 ) 02B1:0004 ( 4 ) 02B2:0003 ( 3 ) 02B3:0002 ( 2 ) 02B4:0002 ( 2 ) 02B5:0002 ( 2 ) 02B6:0002 ( 2 ) 02B7:0002 ( 2 ) 02B8:0003 ( 3 ) 02B9:0004 ( 4 ) 02BA:0001 ( 1 ) 02BB:0007 ( 7 ) 02BC:0003 ( 3 ) 02BD:0003 ( 3 ) 02BE:0004 ( 4 ) 02BF:0003 ( 3 ) 02C0:0002 ( 2 ) 02C1:0000 ( 0 ) 02C2:0002 ( 2 ) 02C3:0004 ( 4 ) 02C4:0003 ( 3 ) 02C5:0003 ( 3 ) 02C6:0003 ( 3 ) 02C7:0003 ( 3 ) 02C8:0003 ( 3 ) 02C9:0002 ( 2 ) 02CA:0003 ( 3 ) 02CB:0003 ( 3 ) 02CC:0002 ( 2 ) 02CD:0003 ( 3 ) 02CE:0003 ( 3 ) 02CF:0003 ( 3 ) 02D0:0003 ( 3 ) 02D1:0001 ( 1 ) 02D2:0000 ( 0 ) 02D3:0001 ( 1 ) 02D4:0001 ( 1 ) 02D5:0001 ( 1 ) 02D6:0000 ( 0 ) 02D7:0000 ( 0 ) 02D8:0000 ( 0 ) 02D9:0003 ( 3 ) 02DA:0004 ( 4 ) 02DB:0003 ( 3 ) 02DC:0002 ( 2 ) 02DD:0004 ( 4 ) 02DE:0001 ( 1 ) 02DF:0001 ( 1 ) 02E0:0000 ( 0 ) 02E1:0003 ( 3 ) 02E2:000B ( 11 ) 02E3:0003 ( 3 ) 02E4:0002 ( 2 ) 02E5:0003 ( 3 ) 02E6:0002 ( 2 ) 02E7:0002 ( 2 ) 02E8:0004 ( 4 ) 02E9:0002 ( 2 ) 02EA:0004 ( 4 ) 02EB:0004 ( 4 ) 02EC:0004 ( 4 ) 02ED:0002 ( 2 ) 02EE:0004 ( 4 ) 02EF:0002 ( 2 ) 02F0:0002 ( 2 ) 02F1:0005 ( 5 ) 02F2:0005 ( 5 ) 02F3:0005 ( 5 ) 02F4:0002 ( 2 ) 02F5:0002 ( 2 ) 02F6:0002 ( 2 ) 02F7:0002 ( 2 ) 02F8:0002 ( 2 ) 02F9:0002 ( 2 ) 02FA:0003 ( 3 ) 02FB:0002 ( 2 ) 02FC:0009 ( 9 ) 02FD:0002 ( 2 ) 02FE:0003 ( 3 ) 02FF:0003 ( 3 ) 0300:0002 ( 2 ) 0301:0000 ( 0 ) 0302:0004 ( 4 ) 0303:0004 ( 4 ) 0304:0002 ( 2 ) 0305:0002 ( 2 ) 0306:0002 ( 2 ) 0307:0002 ( 2 ) 0308:0001 ( 1 ) 0309:0008 ( 8 ) 030A:0008 ( 8 ) 030B:0008 ( 8 ) 030C:0008 ( 8 ) 030D:0002 ( 2 ) 030E:0002 ( 2 ) 030F:0002 ( 2 ) 0310:0002 ( 2 ) 0311:0002 ( 2 ) 0312:0000 ( 0 ) 0313:000A ( 10 ) 0314:0003 ( 3 ) 0315:0002 ( 2 ) 0316:0000 ( 0 ) 0317:0000 ( 0 ) 0318:0001 ( 1 ) exult-1.2/tools/expack.txt0000644000175000001440000000563007453337025011362 Expack Documentation ==================== NAME ==== expack - manipulate Flex files SYNOPSIS ======== expack -a FLEXFILE FILE... expack -c FLEXFILE FILE... expack -x FLEXFILE [INDEX] expack -i MANIFEST expack -l FLEXFILE DESCRIPTION =========== expack is a command-line utility that lets you extract and create Flex files. Flex files are archives (which means that they act as containers for other files, somewhat like directories) used by Ultima 7 to store most of its data. Note that the names of the original files are not stored in the Flex --- files are only retrievable by their index. Modes of operation ================== -a Add --NOT IMPLEMENTED YET. FUTURE ENHANCEMENT-- This command adds one or more FILEs to the end of FLEXFILE. -c Create This command takes one or more FILEs and bundles them into FLEXFILE, overwriting it in the process. -x Extract Lets you extract the files contained within FLEXFILE. If INDEX is given only the file at this position will be unpacked, otherwise all files are extracted. The created files will be named index.u7o. -i Input Similar to "Create", this command creates FLEXFILE from a number of input files. However, "Input" takes the names of the input files from MANIFEST instead of the command line. MANIFEST must be a list of file names, one per line. The first name is that of the Flex file that is to be created, the rest are the input files used in building it. -l List This command lists the contents of a FLEXFILE. It gives you the number of files contained within the Flex file, as well as the length of each file. EXAMPLES ======== expack -a animals.flx bee.wav Adds bee.wav to the Flex file animals.flx. expack -a animals.flx hamster.wav snake.wav donkey.wav Adds hamster.wav, snake.wav, and donkey.wav to the Flex file animals.flx. expack -c animals.flx duck.wav cat.wav cow.wav dog.wav Creates a new Flex file animals.flx containing duck.wav, cat.wav, cow.wav, and dog.wav. expack -x text.flx 17 Extracts the file at position 17fromtext.flxinto17.u7o. expack -x text.flx Extracts all files from text.flx into files named 0.u7o, 1.u7o, 2.u7o, etc. expack -i wavlist With wavlist reading: jmsfx.flx ant.wav bee.wav cat.wav will create a new Flex file jmsfx.flx consisting of ant.wav, bee.wav, andcat.wav. expack -l text.flx Lists the number and lenghts of files contained in text.flx. BUGS ==== The "Add" command (-a) does not work yet. AUTHOR ====== This manpage was written by Robert Bihlmeyer based on a text by Marc Winterrowd. It may be freely redistributed and modified under the terms of the GNU General Public License version 2 or higher. Index NAME SYNOPSIS DESCRIPTION Modes of operation EXAMPLES BUGS AUTHOR This document was created by man2html, using the manual pages. Time: GMT, April 05, 2002 exult-1.2/tools/intrins1.txt0000644000175000001440000000526507132374315011657 U7BG - External call list callis 0000, 1 callis 0001, 2 callis 0002, 3 calli _SwitchTalkTo@2 ; 0003 calli _HideNPC@1 ; 0004 calli _AddAnswer@1 ; 0005 calli _RemoveAnswer@1 ; 0006 calli _SaveAnswers@0 ; 0007 calli _RestoreAnswers@0 ; 0008 calli 0009, 0 callis GetAnswer@0 ; 000A callis 000B, 0 callis _AskNumber@4 ; 000C calli _SetItemType@2 ; 000D callis 000E, 3 calli 000F, 1 callis _Random2@2 ; 0010 callis _GetItemType@1 ; 0011 callis _GetItemFrame@1 ; 0012 calli _SetItemFrame@2 ; 0013 callis _GetItemQuality@1 ; 0014 callis 0015, 2 callis 0016, 2 callis 0017, 2 callis 0018, 1 callis 0019, 2 callis 001A, 2 callis 001B, 1 callis 001C, 1 calli 001D, 2 calli 001E, 1 calli 001F, 1 callis _GetNPCProperty@2 ; 0020 callis _SetNPCProperty@3 ; 0021 callis 0022, 0 callis GetPartyMembers@0 ; 0023 callis 0024, 1 callis 0025, 1 callis 0026, 1 callis GetPlayerName@1 ; 0027 callis 0028, 4 callis 0029, 4 callis _GetContainerItems@4 ; 002A callis 002B, 5 callis 002C, 5 ; 002D - Not found calli _PlayMusic@2 ; 002E callis NPCInParty@1 ; 002F callis 0030, 1 callis 0031, 1 calli DisplaySign@2 ; 0032 callis _ItemSelectModal@0 ; 0033 ; 0034 - Not found callis 0035, 4 callis 0036, 1 callis 0037, 1 callis GetTimeHour@0 ; 0038 callis GetTimeMinute@0 ; 0039 callis 003A, 1 callis 003B, 0 callis 003C, 1 calli 003D, 2 calli 003E, 2 calli 003F, 1 calli _ItemSay@2 ; 0040 callis 0041, 3 callis 0042, 1 calli 0043, 2 callis 0044, 0 calli 0045, 1 calli 0046, 2 callis 0047, 2 callis 0048, 0 calli 0049, 1 callis 004A, 2 calli 004B, 2 calli 004C, 2 callis 004D, 1 ; 004E - Not found calli 004F, 1 calli 0050, 2 callis 0051, 1 callis 0052, 3 calli 0053, 7 callis 0054, 3 calli 0055, 1 calli 0056, 1 calli 0057, 1 callis 0058, 1 calli 0059, 1 callis _IsPlayerFemale@0 ; 005A calli 005B, 0 calli 005C, 1 calli _StartEndgame@0 ; 005D callis _ArraySize@1 ; 005E calli 005F, 1 calli 0060, 1 callis 0061, 4 callis 0062, 0 calli 0063, 2 ; 0064 - Not found callis 0065, 1 calli 0066, 1 callis 0067, 0 callis _DetectMouse@0 ; 0068 callis 0069, 0 calli 006A, 1 callis 006B, 1 callis 006D, 0 calli 006C, 2 callis 006E, 1 calli 006F, 1 calli 0070, 0 calli 0071, 3 callis 0072, 4 calli 0073, 0 callis 0074, 1 calli 0075, 1 calli 0076, 6 calli 0077, 1 calli 0078, 1 callis 0079, 1 calli 007A, 0 calli 007B, 8 calli 007C, 0 callis 007D, 4 calli 007E, 0 calli 007F, 2 calli 0080, 1 callis 0081, 0 calli 0082, 2 calli 0083, 0 calli 0084, 0 callis 0085, 3 calli 0086, 2 callis 0087, 2 callis 0088, 2 calli 0089, 2 calli 008A, 2 calli 008B, 3 calli 008C, 3 callis 008D, 0 callis 008E, 0 callis 008F, 1 callis 0090, 1 calli 0091, 0 calli 0092, 1 callis 0093, 1 calli 0094, 1 calli 0095, 1 callis 0096, 1 exult-1.2/tools/intrins2.txt0000644000175000001440000000652707132374315011662 U7SI - External call list callis 0000, 1 callis 0001, 2 callis 0002, 3 calli _SwitchTalkTo@2 ; 0003 calli _HideNPC@1 ; 0004 calli _AddAnswer@2 ; 0005 calli _RemoveAnswer@2 ; 0006 calli SaveAnswers@0 ; 0007 calli RestoreAnswers@0 ; 0008 calli 0009, 1 ; 000A - Not used ; 000B - Not used calli _AskNumber@1 ; 000C calli _SetItemType@1 ; 000D calli 000E, 0 calli 000F, 0 calli _Random2@0 ; 0010 callis _GetItemType@0 ; 0011 callis _GetItemFrame@0 ; 0012 callis _SetItemFrame@4 ; 0013 calli _GetItemQuality@2 ; 0014 callis 0015, 3 calli 0016, 1 callis 0017, 2 callis 0018, 1 callis 0019, 1 callis 001A, 1 calli 001B, 2 callis 001C, 1 callis 001D, 2 callis 001E, 2 callis 001F, 2 callis _GetNPCProperty@1 ; 0020 callis _SetNPCProperty@2 ; 0021 callis 0022, 2 callis GetPartyMembers@1 ; 0023 callis 0024, 1 calli 0025, 2 calli 0026, 1 calli GetPlayerName@1 ; 0027 callis 0028, 2 callis 0029, 3 callis _GetContainerItems@0 ; 002A callis 002B, 0 callis 002C, 1 callis 002D, 2 callis PlayMusic@1 ; 002E callis NPCInParty@1 ; 002F callis 0030, 1 callis 0031, 4 callis DisplaySign@4 ; 0032 callis _ItemSelectModal@4 ; 0033 callis 0034, 5 callis 0035, 5 callis 0036, 6 callis 0037, 6 callis GetTimeHour@0 ; 0038 calli GetTimeMinute@2 ; 0039 callis 003A, 1 callis 003B, 1 callis 003C, 1 callis 003D, 1 calli 003E, 2 callis 003F, 0 calli _ItemSay@1 ; 0040 callis 0041, 4 callis 0042, 1 callis 0043, 1 callis 0044, 1 callis 0045, 0 callis 0046, 0 callis 0047, 1 callis 0048, 0 callis 0049, 1 calli 004A, 2 calli 004B, 2 calli 004C, 1 calli 004D, 2 calli 004E, 1 callis 004F, 3 callis 0050, 1 calli 0051, 2 callis 0052, 0 calli 0053, 1 calli 0054, 2 callis 0055, 2 callis 0056, 1 calli 0057, 1 callis 0058, 2 calli 0059, 2 callis _IsPlayerFemale@1 ; 005A calli 005B, 2 callis 005C, 1 callis _StartEndgame@1 ; 005D calli _ArraySize@2 ; 005E ; 005F - 0062 Not used callis 0063, 1 calli 0064, 1 callis 0065, 1 callis 0066, 3 calli 0067, 1 calli _DetectMouse@7 ; 0068 callis 0069, 3 calli 006A, 1 calli 006B, 1 calli 006C, 1 callis 006D, 1 calli 006E, 1 callis 006F, 0 ; 0070 - Not used calli 0071, 1 calli 0072, 0 callis 0073, 1 calli 0074, 1 calli 0075, 1 callis 0076, 4 callis 0077, 0 ; 0078 - 0079 Not used callis 007A, 1 calli 007B, 1 callis 007C, 0 ; 007D - Not used callis 007E, 0 calli 007F, 1 callis 0080, 1 calli 0081, 2 callis 0082, 0 callis 0083, 1 calli 0084, 1 calli 0085, 0 calli 0086, 0 calli 0087, 3 callis 0088, 4 ; 0089 - Not used callis 008A, 1 calli 008B, 1 ; 008C - Not used calli 008D, 1 calli 008E, 1 callis 008F, 1 calli 0090, 0 calli 0091, 8 calli 0092, 0 calli 0093, 0 callis 0094, 4 ; 0095 - Not used callis 0096, 1 ; 0097 - Not used calli 0098, 0 calli 0099, 2 calli 009A, 1 callis 009B, 0 calli 009C, 2 ; 009D - Not used calli 009E, 0 calli 009F, 1 callis 00A0, 3 calli 00A1, 2 callis 00A2, 2 callis 00A3, 2 calli 00A4, 2 calli 00A5, 2 callis 00A6, 0 calli 00A7, 3 calli 00A8, 3 calli 00A9, 3 callis 00AA, 0 callis 00AB, 0 callis 00AC, 1 ; 00AD - Not used calli 00AE, 1 ; 00AF - 00B0 Not used calli 00B1, 1 callis 00B2, 1 calli 00B3, 2 calli 00B4, 1 calli 00B5, 4 calli 00B6, 4 calli 00B7, 1 callis 00B8, 1 calli 00BA, 2 ; 00BB - Not used callis 00BC, 1 calli 00BD, 2 callis 00BE, 2 callis 00BF, 3 calli 00C0, 2 calli 00C1, 6 callis 00C2, 1 calli 00C3, 1 calli 00C4, 4 calli 00C5, 2 exult-1.2/tools/textpack.cc0000644000175000001440000001125107724430453011474 /** ** Textpack.cc - Convert text file to a Flex file. ** ** Written: 2/14/2002 **/ /* * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include #endif #include #include #include "Flex.h" #include "utils.h" #include "exceptions.h" #include "msgfile.h" using std::atoi; using std::cerr; using std::cin; using std::cout; using std::endl; using std::exit; using std::ifstream; using std::ofstream; using std::istream; using std::ostream; using std::size_t; using std::strlen; using std::vector; /* * Read in a Flex file where each entry is a 0-delimited text string. */ static void Read_flex ( const char *filename, // File to read. vector& strings // Strings are stored here. ) { Flex in(filename); // May throw exception. int cnt = in.number_of_objects(); strings.resize(cnt); for (int i = 0; i < cnt; i++) { size_t len; strings[i] = in.retrieve(i, len); if (!len) // Empty? { delete strings[i]; strings[i] = 0; } } } /* * Write out a Flex file where each entry is a 0-delimited text string. */ static void Write_flex ( const char *filename, // File to write. char *title, // For the header. vector& strings // Okay if some are null. ) { ofstream out; U7open(out, filename); // May throw exception. Flex_writer writer(out, title, strings.size()); for (vector::const_iterator it = strings.begin(); it != strings.end(); ++it) { const char *str = *it; if (str) out << str; out.put((char) 0); // 0-delimit. writer.mark_section_done(); } if (!writer.close()) throw file_write_exception(filename); } /* * Write out text, with each line in the form "nnn:sssss", where nnn is * the Flex entry #, and anything after the ':' is the string. * NOTES: Null entry #'s will be skipped in the output. * Max. text length is 1024. */ static void Write_text ( ostream& out, vector& strings // Strings to write. ) { out << "# Written by Exult Textpack tool" << endl; int cnt = strings.size(); for (int i = 0; i < cnt; i++) { char *text = strings[i]; if (!text) continue; if (strlen(text) + 1 > 1024) { cerr << "Text in entry " << i << " is too long" << endl; exit(1); } out << i << ':' << text << endl; } out.flush(); } /* * Print usage and exit. */ static void Usage() { cerr << "Usage: textpack -[x|c] flexfile [textfile]" << endl << " Missing [textfile] => stdin/stdout" << endl; exit(1); } /* * Create or extract from Flex files consisting of text entries. */ int main ( int argc, char **argv ) { if (argc < 3 || argv[1][0] != '-') Usage(); // (Exits.) char *flexname = argv[2]; vector strings; // Text stored here. switch (argv[1][1]) // Which function? { case 'c': // Create Flex. if (argc >= 4) // Text filename given? { ifstream in; // Open as text. try { U7open(in, argv[3], true); } catch (exult_exception& e) { cerr << e.what() << endl; exit(1); } if (Read_text_msg_file(in, strings) == -1) exit(1); } else // Default to stdin. if (Read_text_msg_file(cin, strings) == -1) exit(1); try { Write_flex(flexname, "Flex created by Exult", strings); } catch (exult_exception& e){ cerr << e.what() << endl; exit(1); } break; case 'x': // Extract to text. try { Read_flex(flexname, strings); } catch (exult_exception& e){ cerr << e.what() << endl; exit(1); } if (argc >= 4) // Text file given? { ofstream out; try { U7open(out, argv[3], true); } catch(exult_exception& e) { cerr << e.what() << endl; exit(1); } Write_text(out, strings); } else Write_text(cout, strings); break; default: Usage(); } // Clean up allocated strings. for (vector::iterator it = strings.begin(); it != strings.end(); ++it) delete *it; return 0; } exult-1.2/tools/mklink.c0000644000175000001440000001530007124132423010760 /* * mklink -- Create "linkdep1" and "linkdep2" files from the * "usecode" file. * * Copyright (c) 1999 Keldon Jones */ #include #include /* Some basic types */ typedef unsigned char byte; typedef unsigned short u16b; typedef unsigned long u32b; /* Info about one usecode function */ typedef struct usecode_func usecode_func; struct usecode_func { /* Location in usecode */ u32b where; /* Size of function in bytes */ u16b size; /* Number of called functions */ u16b num_call; /* List of called functions */ u16b *called; /* Have we been visited */ u16b visited; }; /* List of usecode functions */ usecode_func functions[4096]; /* * Read an unsigned 16-bit value from a file. */ void read_u16b(FILE *fff, u16b *n) { u16b x; byte c; c = fgetc(fff); x = c; c = fgetc(fff); x |= c << 8; *n = x; } /* * Read an unsigned 32-bit value from a file. */ void read_u32b(FILE *fff, u32b *n) { u32b x; byte c; c = fgetc(fff); x = c; c = fgetc(fff); x |= c << 8; c = fgetc(fff); x |= c << 16; c = fgetc(fff); x |= c << 24; *n = x; } /* * Write an unsigned 16-bit value to a file. */ void write_u16b(FILE *fff, u16b n) { byte c; c = n & 0xFF; fputc(c, fff); n >>= 8; c = n & 0xFF; fputc(c, fff); } /* * Write an unsigned 32-bit value to a file. */ void write_u32b(FILE *fff, u32b n) { byte c; c = n & 0xFF; fputc(c, fff); n >>= 8; c = n & 0xFF; fputc(c, fff); n >>= 8; c = n & 0xFF; fputc(c, fff); n >>= 8; c = n & 0xFF; fputc(c, fff); } /* * Return the sum of the sizes of all functions in this tree. */ u16b get_total_size(u16b *call_tree, u16b tree_size) { usecode_func *u_ptr; u16b size = 0; int i; /* Add size of each function */ for (i = 0; i < tree_size; i++) { /* Get pointer to function info */ u_ptr = &functions[call_tree[i]]; /* Add in size of this function */ size += u_ptr->size; } /* Return total size */ return size; } /* * Return a list of all functions in the call tree of the given function. * * This function is recursive. */ u16b *get_tree(u16b func_num, u16b *num) { usecode_func *u_ptr; u16b *sub_tree, sub_size; u16b *our_tree, our_size; int i, j; /* Get pointer to function info */ u_ptr = &functions[func_num]; /* No need to return a tree */ if (u_ptr->visited) { /* No tree */ *num = 0; return NULL; } /* Start with ourselves */ our_size = 1; /* Start array */ our_tree = (u16b *)malloc(sizeof(u16b)); /* Copy our number into tree */ our_tree[0] = func_num; /* We've visited this function */ u_ptr->visited = 1; /* Add elements from each called function */ for (i = 0; i < u_ptr->num_call; i++) { /* Get the sub-tree */ sub_tree = get_tree(u_ptr->called[i], &sub_size); /* No tree returned */ if (!sub_size) continue; /* Increase the number in our tree */ our_size += sub_size; /* Grow our tree */ our_tree = (u16b *)realloc(our_tree, sizeof(u16b) * our_size); /* Copy elements from sub-tree */ for (j = 0; j < sub_size; j++) { /* Copy one element */ our_tree[our_size - j - 1] = sub_tree[j]; } /* Destroy sub-tree */ free(sub_tree); } /* Return size */ *num = our_size; return our_tree; } /* * Clear the "visited" flag from each function. */ void clear_visited(void) { int i; /* Clear all "visited" flags */ for (i = 0; i < 4096; i++) { /* Clear this flag */ functions[i].visited = 0; } } /* * Compare two function numbers. */ int comp_func(const void *one, const void *two) { u16b first = *((u16b *)one); u16b second = *((u16b *)two); /* Equal */ if (first == second) return 0; /* First smaller */ if (first < second) return -1; /* Second smaller */ return 1; } /* * Sort a function call tree and remove duplicates. */ void fix_tree(u16b *tree, u16b *tree_size) { /* Just call qsort (I'm feeling lazy) */ qsort(tree, *tree_size, sizeof(u16b), comp_func); } /* * Process the "usecode" file and create the two index files. */ int main(void) { FILE *usecode, *linkdep1, *linkdep2; u16b func_num, data_size, max_func; u16b total_size, lnk2_written = 0; u16b *func_tree, tree_size; usecode_func *u_ptr; int i, j; /* Open the usecode file for reading */ usecode = fopen("usecode", "rb"); /* Check for failure */ if (!usecode) { /* Error message */ fprintf(stderr, "Could not open usecode!\n"); /* Give up */ exit(1); } /* Open the linkdep files for writing */ linkdep1 = fopen("linkdep1", "wb"); linkdep2 = fopen("linkdep2", "wb"); /* Read the first function number */ read_u16b(usecode, &func_num); /* Process the usecode file */ while (!feof(usecode)) { /* Get pointer to function */ u_ptr = &functions[func_num]; /* Remember start of function */ u_ptr->where = ftell(usecode) - 2; /* Read the function size */ read_u16b(usecode, &u_ptr->size); /* Read the data size */ read_u16b(usecode, &data_size); /* Skip the data section */ fseek(usecode, data_size, SEEK_CUR); /* Skip number of args and local vars */ fseek(usecode, 4, SEEK_CUR); /* Read number of called functions */ read_u16b(usecode, &u_ptr->num_call); /* Allocate space for table */ u_ptr->called = (u16b *)malloc(sizeof(u16b) * u_ptr->num_call); /* Read table */ for (i = 0; i < u_ptr->num_call; i++) { /* Read this entry */ read_u16b(usecode, &u_ptr->called[i]); } /* Skip past end of function */ fseek(usecode, u_ptr->where + u_ptr->size + 4, SEEK_SET); /* Track highest function number */ max_func = func_num; /* Read the next function number */ read_u16b(usecode, &func_num); } /* Write data about each function */ for (i = 0; i <= max_func; i++) { /* Get pointer to function */ u_ptr = &functions[i]; /* Write null data for null function */ if (!u_ptr->size) { /* Write nothing */ write_u16b(linkdep1, lnk2_written); write_u16b(linkdep1, 0xffff); /* Go to next function */ continue; } /* Get function tree */ func_tree = get_tree(i, &tree_size); /* Fix up the function tree */ fix_tree(func_tree, &tree_size); /* Clear visited flags */ clear_visited(); /* Get total size of function + all called functions */ total_size = get_total_size(func_tree, tree_size); /* Write to linkdep1 */ write_u16b(linkdep1, lnk2_written); write_u16b(linkdep1, total_size); /* Write each pointer */ for (j = 0; j < tree_size; j++) { /* Write this pointer to linkdep2 */ write_u32b(linkdep2, functions[func_tree[j]].where); /* One more pointer written */ lnk2_written++; } /* Destroy the function tree */ free(func_tree); } /* Write ending on linkdep1 */ write_u16b(linkdep1, lnk2_written); write_u16b(linkdep1, 0); /* Close files */ fclose(usecode); fclose(linkdep1); fclose(linkdep2); /* Done */ return 0; } exult-1.2/shapeid.cc0000644000175000001440000002115010040665553010121 /* * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gamewin.h" #include "shapeid.h" #include "vgafile.h" #include "fontvga.h" #include "fnames.h" #include "game.h" #include "Configuration.h" #include "utils.h" #include "segfile.h" #include "u7drag.h" #include "U7file.h" using std::cerr; using std::cout; using std::endl; using std::string; Shape_manager *Shape_manager::instance = 0; /* * Singletons: */ Game_window *Game_singletons::gwin = 0; Game_map *Game_singletons::gmap = 0; Effects_manager *Game_singletons::eman = 0; Shape_manager *Game_singletons::sman = 0; Usecode_machine *Game_singletons::ucmachine = 0; Game_clock *Game_singletons::gclock = 0; Palette *Game_singletons::pal = 0; Gump_manager *Game_singletons::gumpman = 0; Party_manager *Game_singletons::partyman = 0; void Game_singletons::init ( Game_window *g ) { gwin = g; gmap = g->get_map(); eman = g->get_effects(); sman = Shape_manager::get_instance(); ucmachine = g->get_usecode(); gclock = g->get_clock(); pal = g->get_pal(); gumpman = g->get_gump_man(); partyman = g->get_party_man(); } /* * Create shape manager. */ Shape_manager::Shape_manager ( ) : bg_paperdolls_allowed(false), bg_multiracial_allowed(false), bg_paperdolls(false), fonts(0) { assert(instance == 0); instance = this; std::string str; config->value("config/gameplay/bg_paperdolls", str, "yes"); if (str == "yes") bg_paperdolls = true; config->set("config/gameplay/bg_paperdolls", str, true); } /* * Load files. */ void Shape_manager::load ( ) { // Determine some colors based on the default palette Palette pal; pal.load(PALETTES_FLX, 0); // could throw! // Get a bright green. special_pixels[POISON_PIXEL] = pal.find_color(4, 63, 4); // Get a light gray. special_pixels[PROTECT_PIXEL] = pal.find_color(62, 62, 55); // Yellow for cursed. special_pixels[CURSED_PIXEL] = pal.find_color(62, 62, 5); // Red for hit in battle. special_pixels[HIT_PIXEL] = pal.find_color(63, 4, 4); // What about charmed/cursed/paralyzed? shapes.init(); shapes.read_info(GAME_BG); // Read in shape dimensions. files[SF_GUMPS_VGA].load(GUMPS_VGA, PATCH_GUMPS); if (Game::get_game_type()==SERPENT_ISLE) { files[SF_PAPERDOL_VGA].load(PAPERDOL, PATCH_PAPERDOL); if (!files[SF_PAPERDOL_VGA].is_good()) gwin->abort("Can't open 'paperdol.vga' file."); } else { try { files[SF_PAPERDOL_VGA].load( "/paperdol.vga"); files[SF_BG_SIGUMP_FLX].load( "/gumps.vga"); files[SF_BG_SISHAPES_VGA].load( "/shapes.vga"); if (files[SF_PAPERDOL_VGA].is_good() && files[SF_BG_SIGUMP_FLX].is_good() && files[SF_BG_SISHAPES_VGA].is_good()) { std::cout << "Support for SI Paperdolls and Multiracial Avatars in BG is enabled." << std::endl; bg_paperdolls_allowed = true; bg_multiracial_allowed = true; } else std::cout << "Bad SI 'paperdol.vga', 'gumps.vga' or 'shapes.vga'." << std::endl << "Support for SI Paperdolls and Multiracial Avatars in BG is disabled." << std::endl; } catch (const exult_exception &e) { std::cerr << "Couldn't open SI 'paperdol.vga', 'gumps.vga' or 'shapes.vga'." << std::endl << "Support for SI Paperdolls and Multiracial Avatars in BG is disabled." << std::endl; } } files[SF_SPRITES_VGA].load(SPRITES_VGA, PATCH_SPRITES); files[SF_FACES_VGA].load(FACES_VGA, PATCH_FACES); files[SF_EXULT_FLX].load("/exult.flx"); const char* gamedata = game->get_resource("files/gameflx").str; std::cout << "Loading " << gamedata << "..." << std::endl; files[SF_GAME_FLX].load(gamedata); if (!fonts) { fonts = new Fonts_vga_file(); fonts->init(); } // Get translucency tables. std::size_t len, nxforms = sizeof(xforms)/sizeof(xforms[0]); // RGBA blend colors: static unsigned char blends[4*11] = { 144,40,192,128, 96,40,16,128, 100,108,116,192, 68,132,28,128, 255,208,48,64, 28,52,255,128, 8,68,0,128, 255,8,8,118, 255,244,248,128, 56,40,32,128, 228,224,214,82}; for (int i = 0; i < nxforms; i++) xforms[i].set_color(blends[4*i], blends[4*i+1], blends[4*i+2], blends[4*i+3]); if (U7exists(XFORMTBL)) { // Read in translucency tables. Segment_file xf(XFORMTBL); for (int i = 0; i < nxforms; i++) { uint8 *data = (uint8*)xf.retrieve(i, len); std::memcpy(xforms[nxforms - 1 - i].colors, data, sizeof(xforms[0].colors)); delete[] data; } } else // Create algorithmically. { gwin->get_pal()->load(PALETTES_FLX, 0); for (int i = 0; i < nxforms; i++) { gwin->get_pal()->create_trans_table(xforms[i].r/4, xforms[i].g/4, xforms[i].b/4, xforms[i].a, xforms[i].colors); } } invis_xform = &xforms[nxforms - 1 - 0]; // ->entry 0. } /* * Reload one of the shape files (msg. from ExultStudio). */ void Shape_manager::reload_shapes ( int dragtype // Type from u7drag.h. ) { U7FileManager::get_ptr()->reset(); // Cache no longer valid. switch (dragtype) { case U7_SHAPE_SHAPES: shapes.init(); // Reread .vga file. shapes.read_info(GAME_BG); //+++++Needs work. // ++++Reread text? break; case U7_SHAPE_GUMPS: files[SF_GUMPS_VGA].load(GUMPS_VGA, PATCH_GUMPS); break; case U7_SHAPE_FONTS: fonts->init(); break; case U7_SHAPE_FACES: files[SF_FACES_VGA].load(FACES_VGA, PATCH_FACES); break; case U7_SHAPE_SPRITES: files[SF_SPRITES_VGA].load(SPRITES_VGA, PATCH_SPRITES); break; case U7_SHAPE_PAPERDOL: files[SF_PAPERDOL_VGA].load(PAPERDOL, PATCH_PAPERDOL); break; default: cerr << "Type not supported: " << dragtype << endl; break; } } /* * Clean up. */ Shape_manager::~Shape_manager() { delete fonts; assert(this == instance); instance = 0; } /* * Text-drawing methods: */ int Shape_manager::paint_text_box(int fontnum, const char *text, int x, int y, int w, int h, int vert_lead, int pbreak, int shading) { if(shading>=0) gwin->get_win()->fill_translucent8( 0, w, h, x, y, xforms[shading]); return fonts->paint_text_box(gwin->get_win()->get_ib8(), fontnum, text, x, y, w, h, vert_lead, pbreak); } int Shape_manager::paint_text(int fontnum, const char *text, int xoff, int yoff) { return fonts->paint_text(gwin->get_win()->get_ib8(), fontnum, text, xoff, yoff); } int Shape_manager::paint_text(int fontnum, const char *text, int textlen, int xoff, int yoff) { return fonts->paint_text(gwin->get_win()->get_ib8(), fontnum, text, textlen, xoff, yoff); } int Shape_manager::get_text_width(int fontnum, const char *text) { return fonts->get_text_width(fontnum, text); } int Shape_manager::get_text_width(int fontnum, const char *text, int textlen) { return fonts->get_text_width(fontnum, text, textlen); } int Shape_manager::get_text_height(int fontnum) { return fonts->get_text_height(fontnum); } int Shape_manager::get_text_baseline(int fontnum) { return fonts->get_text_baseline(fontnum); } Font *Shape_manager::get_font(int fontnum) { return fonts->get_font(fontnum); } /* * Read in shape. */ Shape_frame *ShapeID::cache_shape() { if (framenum == -1) return 0; if (has_trans != 2) has_trans = 0; if (!shapefile) { // Special case. shape = sman->shapes.get_shape(shapenum, framenum); if (has_trans != 2) has_trans = sman->shapes.get_info(shapenum).has_translucency(); } else if (shapefile < SF_OTHER) { shape = sman->files[(int) shapefile].get_shape( shapenum, framenum); if (shapefile == SF_SPRITES_VGA) has_trans = 1; } else { std::cerr << "Error! Wrong ShapeFile!" << std::endl; return 0; } return shape; } int ShapeID::get_num_frames() const { if (!shapefile) return sman->shapes.get_num_frames(shapenum); else if (shapefile < SF_OTHER) { if (!sman->files[(int) shapefile].is_good()) return 0; return sman->files[(int) shapefile].get_num_frames(shapenum); } std::cerr << "Error! Wrong ShapeFile!" << std::endl; return 0; } exult-1.2/vec.h0000644000175000001440000000445410054030532007117 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef VEC_H #define VEC_H #include template class Exult_vector : public std::vector { private: typedef std::vector baseClass; public: typedef typename baseClass::size_type size_type; typedef typename baseClass::iterator iterator; Exult_vector() : baseClass() {} Exult_vector(size_type n) : baseClass() { reserve(n); } #ifndef MACOS /* should be something like PROPER_STD_CPP_LIB or so */ T& at(int i) { return (*this)[i]; } #endif void put(int i, T& v) // Set i'th entry. { if (i >= (int)this->size()) { insert(this->begin() + this->size(), i - this->size(), 0); push_back(v); } else (*this)[i] = v; } int put(T& v) // Put in a free spot & return it. { int i = find(0); if (i < 0) i = this->size(); put(i, v); return (i); } size_type find( const T& obj ) const { size_type pos = 0; for (const T *X = &*this->begin(); X != &*this->end(); ++X, ++pos) { if( *X == obj ) return pos; } return -1; } size_type append( const T& obj ) { push_back( obj ); return this->size() - 1; } void remove( const T& obj ) { // Correct way. An iterator isn't a pointer, necessarily for(iterator X = this->begin(); X != this->end(); ++X) { if( *X == obj ) { erase(X); return; } } } }; class Game_object; class Egg_object; class Actor; typedef Exult_vector Game_object_vector; typedef Exult_vector Egg_vector; typedef Exult_vector Actor_vector; #endif exult-1.2/win32/0000777000175000001440000000000010062225324007214 5exult-1.2/win32/exultstudioico.rc0000644000175000001440000000272210062225266012552 // Exult Resource Script #include "winresrc.h" #define IDI_ICON1 101 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "exultstudio.ico" #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,2,0,0 PRODUCTVERSION 1,2,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN //VALUE "CompanyName", "The Exult Team\0" VALUE "FileDescription", "Exult Studio\0" VALUE "FileVersion", "1.2\0" VALUE "InternalName", "Exult Studio\0" VALUE "LegalCopyright", "Copyright 2004\0" VALUE "OriginalFilename", "exult_studio.exe\0" VALUE "ProductName", "Exult Studio\0" VALUE "ProductVersion", "1.2\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif // !_MAC #endif // English (Australia) resources exult-1.2/win32/exultstudio.ico0000644000175000001440000001774607421316752012247 hF 00V ( xP(  hTDt0`$L8xdXL84(  lP4|\<|l`PD4l$P4`,llPP44Tl(P8( lP4||\\<<lP4ԘlH(||ll``PPDD44$$td|XlL\ 1 **save games are now compressed as zip files. 0 disables compression, 1 enables it, 2 compresses even a bit better. Default is 1. data **see 2.3. for pathsettings data/music **optional. Location of digital music. See also 3.4. blackgate ./blackgate ./blackgate **optional. Default is the same as , change to whatever you like. Also see 2.4. before changing it. ./blackgate/static **optional. See 2.4. before changing it. ./blackgate/gamedat **optional. See 2.4. before changing it. (default) **configure custom key bindings or leave the (default) - see 5.2. jmsfx.flx **optional setting see 3.6. for configuration serpentisle ./serpentisle ./serpentisle **optional. Default is the same as , change to whatever you like. Also see 2.4. before changing it. ./serpentisle/static **optional. See 2.4. before changing it. ./serpentisle/gamedat **optional. See 2.4. before changing it. (default) **configure custom key bindings or leave the (default) - see 5.2. jmsisfx.flx **optional setting see 3.6. for configuration no **options are yes/no/verbose. This is used to trace the executed Usecode. (You shouldn't need this unless you are a programmer.) no **options are yes/no. Used to trace intrinsics. (You shouldn't need this unless you are a programmer.) no **options are yes/no. If enabled, show combat messages. no no yes **enable/disable cheats no **this skips the in-game intro in BG; Iolo talks to Petre, the Avatar appears, Iolo talks to you, the mayor talks to you and so on. no **this skips the splash screen, the intro before you get to the game menu. Disabling it brings you straight to the game menu. 0 **activates the status faces and the position on the screen. -1 disable,0 right, 1 middle, 2 right. no **yes enables using of the middle mouse button. no **yes enables faster cursor movement in full screen mode. no **yes enables SI style paperdolls in BG. 0 **0 is default, negative values make combat easier, positive makes it harder. It affects the chance of a hit, and the HP's lost if a hit occurs. Ranges from -3 to 3 (easiest to hardest). original **original or keypause. On keypause the game pauses when you hit space so you can make changes in combat. no **no is default. With yes you see the hitpoints of NPCs in brackets after their name. no **yes doesn't pause the game when gumps are shown. 8 **Controls how far the Avatar will move before Exult recalculates the Avatar's and the party's movement. Bigger # avoids jerkiness, but may cause other problems. yes **double right-click lets the Avatar walk automatically to where you clicked. no **yes forces the party to walk in a formation similar to the original game. 2.3. Path-Settings You have two choices on how to setup Exult. The first one is very easy, just install Exult to the directory where you have The Black Gate or Serpent Isle installed. Concerning the paths you don't have to configure anything, at least for the game you have installed it to. For the other game you will need to edit exult.cfg. The other is a little more complicated but appeals to control freaks like me: Make a directory c:\ultima7 make two subfolders named "blackgate" and "serpentisle" (without the quotes of course) Extract or install the two Ultima 7 games into the appropriate folder ("The Black Gate" to c:\ultima7\blackgate and "Serpent Isle" to c:\ultima7\serpentisle) Install Exult to c:\ultima7. Now you have to edit the file c:\ultima7\exult.cfg file like this (Non-Windows users please look at 2.2. for the location of exult.cfg): data blackgate ./blackgate serpentisle ./serpentisle You can either use the relative (e.g. ./blackgate) or absolute (e.g. c:\ultima\blackgate) path to point to the correct directory. Note: Better don't use spaces in the path (e.g. c:\ultima 7\the black gate\). Some people seem to have problems with that. Note: path settings in exult.cfg are the same on all operating systems. Of course you need to make adjustments on UNIX based systems when you enter the absolute path. 2.4. Further directory customizations You can also specify whereExult reads and stores the game specific data, like the files in the Static and Gamedat directory and the save games. This is optional and not required but may be useful if you want to exercise absolute control. Some explanation what these dirs are for: * Savegames this is where Exult stores your savegames. Normally you find these in the dir set in . * Static the most important dir. Here you have the data files from the original game. You should never touch these files. * Gamedat contains the (dynamic) data for the game you're currently playing. It's where the "journey onward" 'savegame' is stored. If you don't change the location of either the Static or Gamedat directories, Exult expects to find both directories in the path you specified in . Don't ever point these two at the same directory. My recommendations and example for BG (for SI use the same syntax) are: data blackgate ./blackgate ./blackgate ./blackgate/static ./blackgate/gamedat 2.5. Command line options Exult offers some "hidden" command line options: * -h or --help Shows all the command line parameters in stderr (stderr.txt on Windows systems) * -v or --version Shows version information in stderr * -c configfile Specify alternate config file (relative or absolute paths work) * --bg Starts the game with the Black Gate menu * --si Starts the game with the Serpent Isle menu * --nomenu Skips game menu. * --buildmap x x = 0 shows all roofs, x = 2 pops them all. You have to specify the game first (Example: exult --bg --buildmap 0). Builds the map of the game specified. The map is huge and in pcx format, you will need a lot of ram to even look at this map once it is build (and even that requires a lot of patience) Exult is required to be run in windowed mode and you get the best map if you started a new game before you build the map. * --nocrc Recently we added a crc check that Exult doesn't start when the exult*.flx files in the data dir aren't the same it got compiled with. This parameter lets the game start nethertheless. Don't try this if you don't know what you are doing. * --game gamename Loads a game specified in exult.cfg when there are other games made with Exult Studio. -------------------------------------------------------------------------------- 3. Audio 3.1. Music There are three ways that music is played in Exult. One is using MIDI, which plays the music through any GM MIDI device, Timidity can be used in Linux. Another way is Digital Music encoded into OGG (similar to MP3) which was recorded directly from a Roland MT-32. The third option is FMSynth which emulates Opl2/Adlib. The MIDI files are converted on-the-fly from the original Ultima 7 MT-32 files to General Midi format so that they will be playable on modern General Midi and General Midi/GS supporting sound cards. The options for changing the Music driver are in the opening Exult menu Setup screen or in the actual game's audio options. Currently only the in game options menu works correctly. You can choose between: * Normal This setting utilizes the MIDI driver of your system. See the MIDI conversion order below. * Digital Digital Music plays the OGG files which must be located in the Exult data/music directory. This does not use MIDI but plays the music digitally through any soundcard. * FMSynth This is a Software FM Synthesizer (also known as a emulated Opl2/Adlib). It has a 'dual'mode for stereo sound. Use "config/audio/midi/dual_opl" set to "yes" or "no" to enable/disable it. Default is "yes". You don't have to restart Exult anymore if you change this in the game. The order of MIDI conversion quality is: * none This option will output the music with nothing changed. Because the mapping will be for MT32s you should only use this option if you have a MT32 compatible device or you have replaced the music. * gs127 This option is for midi devices that have a MT32 patch bank installed in Bank 127. Some GS implementation have this, some don't. Only use this if you know that you have a MT32 implementation on Bank 127. * gs This will convert the MT32 patches to their equivalent GS patches. This will be a more accurate conversion that straight gm since more of the MT32 patches are in the GS set. However, not all midi devices will support this mode. * gm This will convert the MT32 patches to standard General Midi patches. Conversion is fairly accurate but some instruments may be different. NOTE: Currently the conversion to GS and GS127 is not finished and the notes are only mapped to General Midi. 3.2. Abilities and limitations of the music engine Due to the way the class was constructed input can be in either .mid, .rmi or the Miles Sound System .xmi format. There are no limitations to they types of .mid and .rmi supported. They can be Type 0, 1 and the rarely seen type 2. The loading routine is also fairly lenient of erroneous XMIDI files that do not have correct XMIDI headers. During the development of the XMIDI class it was found that certain .xmi files in Serpent Isle had the first patch changes after the first note. The converter will attempt to correct these errors. However it may cause problems with some midi files. Currently this can not be disabled and may change in the future. 3.3. Windows MIDI Mapper You can now tell Exult which MIDI device it should use. Useful if you want Exult to use a different MIDI device than the default Windows device (like an MT-32). To do this start Exult, on the menu choose "Exit". Now open the file stdout.txt in the folder where exult.exe is located. You will see a listing of the midi devices. For example with an SB Live! in Win2k it will look like this: 4 Midi Devices Detected Listing midi devices: -1: Microsoft MIDI-Mapper 0: A: SB Live! MIDI Synth 1: B: SB Live! MIDI Synth 2: SB Live! MIDI UART By default Exult uses the Microsoft MIDI-Mapper (which uses the device you choose in the Windows Multimedia Properties). To change the MIDI Device open exult.cfg and change -1 with the device you want to use. 3.4. Digital Music Exult needs the Digital Music pack to play Digital Music in the game. The music pack contains music for both Black Gate and Serpent Isle, encoded in high quality OGG format. Simon Quinn recorded the current Digital Music pack on an original Roland MT-32 and with this you will experience the music as it would be heard with the original game. Digital Music should work on any platform that supports digital sound and does not use any MIDI, so it is also a good option for platforms with no MIDI support. Additionally, Digital Music supports a number of background atmospheric SFX tracks that are played when no music is playing. These consist of wind, bird etc effects outside and other sound effects when inside a dungeon. These SFX tracks are not available when using MIDI as they play Roland MT-32 specific voices that cannot be mapped to GM/GS. These SFX tracks do not play when the music is switched off. 3.5. Installation of the digital music packs The Digital Music pack can be downloaded from http://exult.sourceforge.net/download.php, the files are called Ogg encoded Music files for Exult Part 1(use with 1.1.x snapshot only) (U7MusicOGG_1of2.zip) and Ogg encoded Music files for Exult Part 2(use with 1.1.x snapshot only) (U7MusicOGG_2of2.zip). The readme.txt found in the ZIP files contains installation instructions that are no longer 100% valid and should not be followed. Create a music directory in exult/data (i.e. exult/data/music/) and extract the two ZIP files U7MusicOGG_1of2.zip and U7MusicOGG_2of2.zip into this directory. If you are not sure where the data directory is, search for the file exult_bg.flx on your hard drive as this file is always in the data directory. Now start up Exult and start either a game of BG or SI. Hit 'ESC' to enter the game menu. Here select Audio Options and in the "Music options" set the driver option to digital. It isn't necessary but you can also customize the location of the music files by adding to exult.cfg. Example: data data/music 3.6. Digital Wave Sound Effects Exult needs the so called sfx packs to enable sound effects for Ultima 7. You have to download separate packs for each game as order of the sfx in BG and SI varies a bit and otherwise will sound odd. However there is a little issue with sfx playback in SI: In combat the sfx may be a little wrong as we still haven't figured out all the data in the 'weapons.dat'. Also Exult doesn't yet playback all the sfx that the original did. Note that configuring your soundfonts is not needed for digital wave sfx. We currently have two soundpacks for each game. Joseph Morris recorded the original SoundBlaster sfx and Simon Quinn recorded the Roland MT32 sfx. You can find them on our download page at http://exult.sourceforge.net/download.php. Extract the zip files into your Exult data directory and write down the name of the pack in your exult.cfg file (see 2.2.). You don't need to set correct paths anymore if the pack is in the data directory. An example of how the relevant part of exult.cfg looks with these packs: jmsfx.flx jmsisfx.flx 3.7. Speech Exult can play the Ultima VII's speech through SDL, and its own internal mixer. Configuration is managed through Exult's configuration file. 3.8. Turn off Audio Press 'Esc' to turn on/off Music, Speech and SoundFX via the in-game menu or change the settings in exult.cfg - see 2.2.. 3.9. Linux and Audio If you want to use the MIDI music option in Exult and use Timidity to play the MIDI, the timidity.cfg file must go into the same directory as the Exult executable, otherwise Timidity will not work. Apparently Exult has some problem with the sound drivers in the 2.4 kernel, notably with the SoundBlaster Live. Therefore we advice our users to install ALSA (Advanced Linux Sound Architecture) found at http://www.alsa-project.org. ALSA is going to replace OSS in the upcoming stable (2.6) Kernel anyway. We are sorry for this. -------------------------------------------------------------------------------- 4. Video 4.1. Resolution By default Exult runs at 320x200 (which is the resolution the original Ultima VII used). Exult can use different scaling engines to double the size to 640x400 and increase the quality of the graphics. Using higher resolutions is considered cheating as you can see too much of the surrounding area. Since the game was designed to be played at a specific size, this can actually lead to plot-stopping problems; hence we will not fix any problem caused by your cheating! Don't say we didn't warn you :-) Actually being able to play in higher resolutions is one of the big advantages of Exult but as mentioned above it comes with a price. Within the game you can use the 'Alt +' and 'Alt -' to switch resolution.. 4.2. Scaler The scalers also work with higher resolutions than 320x200. To change the scaling method either use the Exult menu or change your exult.cfg - see 2.2.. * Scale2x by Andrea Mazzoleni. This is a non-blurring scaler that looks good without soaking up a lot of CPU sycles. Get more information on this scaler at http://scale2x.sf.net. * SuperEagle by Derek Liauw. Only 2x. * Super2xSai by Derek Liauw. Only 2x. * 2xSaI by Derek Liauw. Only 2x. * BilinearPlus same as Bilinear and it may even be a bit faster.. * Bilinear bilinear interpolation to smooth the result. Slower, but looks better. Only 2x. * Point simple but very fast scaler. Only duplicates pixels, no fancy interpolation. Can be used for arbitrary integer scales (2x, 3x, 4x...). * Interlaced identical to point except that it skips every other line to be even faster The scalers by Derek Liauw are slower but look much better. Try out yourself which one you like most. More information on the excellent scaling engines by Derek Liauw is available at http://elektron.its.tudelft.nl/~dalikifa/. -------------------------------------------------------------------------------- 5. Movement and Keys 5.1. Movement * Hold right mouse button down to move Avatar. * Double-click with the right mouse button will make the Avatar find a path to the selected spot. * Click on objects with left button to identify them. * Double-click on characters to hold conversations. * Double-click on doors, shutters with left button to open or close them. Note that on MacOS you have to hold down the 'Cmd' key and the mouse button to have the functionality of a right mouse button. Nadir implemented keyboard walking in the post 1.0 versions of Exult. The Avatar can be moved with the arrow keys (or the keypad keys for more precise movement). When you move while holding shift the Avatar runs. 5.2. Keyboard commands All key commands of Exultcan be changed for either BG or SI. However, there is a default setting which closely follows the original with the addition of some improvements. To change your key bindings first edit the file defaultkeys.txt in your Exult directory, change the bindings and save the file (e.g. as my_keys.txt). Now you have to change exult.cfg to use that file. You can even choose if you want to change your key bindings for BG or SI. See the keys settings at 2.2.. Change (default) to my_keys.txt. During the game press 'h' to see a help screen with all the keys (for MacOS change Alt for Cmd - the in-game help screen shows the correct key combination for MacOS). 'KP' means keypad. Default keyboard commands KP+/- : Change brightness Alt-KP+/- : Change resolution F4 : Toggle full screen right : walk east left : walk west up : walk north down : walk south KP1 : walk southwest KP2 : walk south KP3 : walk southeast KP4 : walk west KP5 : recenter map KP6 : walk east KP7 : walk northwest KP8 : walk north KP9 : walk northeast Shift-right : run east Shift-left : run west Shift-up : run north Shift-down : run south Shift-KP1 : run southwest Shift-KP2 : run south Shift-KP3 : run southeast Shift-KP4 : run west Shift-KP6 : run east Shift-KP7 : run northwest Shift-KP8 : run north Shift-KP9 : run northeast Ctrl-x : Cut selected object (when in Map Edit mode) Ctrl-c : Copy selected object (when in Map Edit mode) Ctrl-v : Paste selected object (when in Map Edit mode) b : Use spellbook c : Combat mode f : Use food g : Use Abacus h : Show list of keyboard commands i : Show inventory j : SI: Show jawbone k : BG: Try all keys to unlock a lock k : SI: Use keyring Alt-k : SI: Try all keys to unlock a lock l : SI: Show combat stats m : Show map p : Use lockpicks Alt-q : Exit game r : Brings up status bars. First three strokes change the location of the bar. The fourth disables it again. Ctrl-r : Quick restore Ctrl-Alt-s : Screenshot Ctrl-s : Quick save s : Show save/load box Esc : Show Game menu box and closes all open boxes t : Target, instead of double clicking, shows a cursor and pauses the game until you click on something v : About screen w : Use watch, shows the time if you got a watch Alt-x : Exit game z : Show stats 1 : Show inventory for Avatar 2 : Show inventory for character 2 3 : Show inventory for character 3 4 : Show inventory for character 4 5 : Show inventory for character 5 6 : Show inventory for character 6 7 : Show inventory for character 7 8 : Show inventory for character 8 In conversations you have the ability not just click on the answer with the mouse but also to use the numeric keys. The response options aren't numbered visually but logically with the dots. Also press 'Esc' to select "bye" if possible. 5.3. Cheat keys Press 'ctrl-h' during the game to see a help screen with all the cheat keys. 'KP' means keypad. Cheat commands Alt-+/- : Switch resolution( you may have to use the keypad) Alt-Arrow keys : Scroll map home : Recenter map Ctrl-Arrow keys : move selection (x,y coordinates) Ctrl-Page keys : move selection (z coordinates) F2 : Cheat screen similar to the originals'. Allows for some level of NPC editing and other cheat options F3 : Map teleport F10 : Show endgame F11 : SI: Play alternate intro Ctrl-b : Shape browser Insert : Create object (that is chosen in the shape browser) Ctrl-d : Delete object e : Toggle egg display Alt-g : Toggle God mode Ctrl-g : Change avatar gender Ctrl-Alt-h : Resurrect, heal party, cure poison and still hunger Alt-i : Toggle infravision Ctrl-l : Level up party l : Decrement skiplift Alt-h : Hackmover (you can move all objects around and it disables weight check Ctrl-Alt-m : Toggle Map editor (useful for Exult Studio) Ctrl-m : Get 100 gold coins Alt-Shift-m : Play previous song Alt-m : Play next song Alt-n : SI: Toggle naked flag Alt-p : SI: Toggle Petra mode Alt-s : SI: Change skin color Ctrl-Alt-t : Map teleport Ctrl-t : Advance to next time period Alt-t : Teleport (to current cursor position) Alt-w : Toggle archwizard mode (all spells etc.) Alt-1 : Test music, sfx, speech Ctrl-Alt-g : Grab NPC for cheat screen Ctrl-Alt-p : Pick pocket cheat, when enabled double-clicking on a NPC displays the actors inventory Ctrl-n : NPC number, When enabled, clicking an a NPC will display their number instead of their name. Useful for the cheat screen. -------------------------------------------------------------------------------- 6. Game Menu 6.1. Access to the Game menu You can access the Game menu either by pressing the disk icon in the Avatar's inventory screen or by pressing 'Esc'. You then have the following options. 6.2. Load/Save Game This on is pretty straightforward. You can load and save a game, delete a game and view some information of a save game on the right side (a screenshot and some stats). If you have a wheel mouse you can scroll one line up/down by using the wheel. Pressing 'Alt' while using the wheel scrolls by pages. Pressing Cancel exits the Load/Save options. 6.3. Video Options In this option screen you are able to determine how Exult displays the game. * Resolution lets you choose between various resolutions. You can choose between 320x200, 320x240, 400x300, 512x384, 640x480 and 800x600. If you want higher resolutions edit exult.cfg outlined in 2.2. Settings in exult.cfg. * Scaling choose between 1x and 2x. What it does is explained in 4.2. Scaler. * Scaler lets you choose your favorite scaling engine. Also look at 4.2. Scaler for an explanation. * Full Screen enable or disable running Exult in full screen. * OK/Cancel Ok accepts your changes, Cancel discards your changes. 6.4. Audio Options Look at 3. Audio to see explanation on the settings. * Audio Enable or disable all Audio in Exult. * Music Enable or disable music. * driver choose between Normal, Digital or FMSynth. * conversion choose between None, GM, GS, GS127. * effects alters the way the midi is played. Choose between Reverb, Chorus, Both (Reverb and Chorus) or disable it. * looping Disable restores the (broken) way the original handled the music looping flag. * SFX Enable or disable digital sound effects. * Speech Options Enable or disable the speech in the games. * OK/Cancel Ok accepts your changes, Cancel discards your changes. 6.5. Gameplay Options * Status Bars You can either disable the status bars or choose its position on the bottom of the screen (left, middle, right). * Text Background shows a tinted background behind text in conversations to make it easier to read. Either disable it or choose between the colors purple, orange, light gray, green, yellow, pale blue, dark green, red, bright white, dark gray and white. * Fast Mouse makes the mouse cursor move faster in full screen modes. Enable or disable it. * Use middle mouse button In the normal game, the middle mouse button activates the target-function (which could also be accomplished by pressing 't'). For modal gumps, the middle mouse acts as 'return', the right button as 'escape', so you can now for example accept the default slider value by just pressing the middle button. The escape function is also available during most other actions like selecting a target or conversations. Enable or disable it. * Doubleclick closes gumps pretty straightforward, right? * Right click closes gumps the same but different. * Double Right Pathfinds Double right-clicking on a spot makes the avatar walk to it. * Gumps pause games In the original the game got paused when Gumps were shown. Enable/disable it. * Cheats Enables or disables all the cheats that we implemented in Exult. See 5.3. Cheat keys what those cheats are. * Speed if Exult seems too fast lower this setting. If it seems to sluggish raising this setting may help. * Paperdolls only available in Black Gate. Enables or disable Paperdolls (inventory screen) in the style of Serpent Isle. * OK/Cancel Ok accepts your changes, Cancel discards your changes. 6.6. Combat Options As many people think that the U7 combat engine is far too easy, too hard or just can't stand the real-time-combat Jeff put in some options to make combat more interesting. * Difficulty Ranges from Easiest (-3) to Hardest (3). It affects the chance of a hit, and the HP's lost if a hit occurs. * ShowHits With this enabled you can see the hitpoints of NPCs in brackets after their name when you left-click on them. * Mode choose between Original and SpacePauses. SpacePauses gives you a little more control of combat. When you hit space the game pauses and you can direct a party member by right-clicking, then clicking on a target to attack. Or change weapons, choose a favourite spell. 6.7. Quit Exits Exult. -------------------------------------------------------------------------------- 7. OS specific notes 7.1. How to get the Zaurus port working Some people were confused where to put the Exult and U7 files and this is just a quick guide. The long guide is in the next section. * BG and SI are expected to be installed in /mnt/cf/exult-data/bg and /mnt/cf/exult-data/si * Exult binary is in /opt/QtPalmtop/bin/ * the data files (like exult_bg.flx) go into /opt/QtPalmtop/share/exult/ * exult.cfg is can be found as /home/root/.exult.cfg 7.2. Error Log * MacOS/Win32: Exult generates the files 'stdout.txt' and 'stderr.txt'. These may give you some idea of what is going on under the hood. When Exult suddenly quits, sometimes these files can help. * UNIX/UNIX clones: the above mentioned logs are shown in the console from which Exult is started. ./exult >&log will send both stderr and stdout to the file named "log". -------------------------------------------------------------------------------- 8. Zaurus Guide 8.1. Author of this Guide This file was written by Artaxerxes (Aurelien Marchand). He can be contacted at artaxerxes2 at iname dot com. Please ask if you want to send attachments no matter what their size. 8.2. Sharp Zaurus Introduced in April 2002, this PDA is really a pico-computer (one degree of magnitude less than micro). It runs a version of Linux on the ARM processor. It is possible to use cross-compilers to create programs that will run on the Zaurus, even if compiling from a x86 machine. This is notably the case for the Zaurus port of Exult. More information about the Zaurus can be gleaned on http://www.myZaurus.com. 8.3. Zaurus SL5x00 and ROMs Sharp occasionnally releases new versions of its ROM for Zaurus. Consider a new ROM like a new Linux distribution: new packages, new look, new kernel etc. It is possible to update the ROM thanks to information found on the Zaurus web site mentioned earlier. The current Exult package for the Zaurus is created for the stock SL-5500 ROM v2.12. It has been reported to work on the SL5000-D (the earlier and less capable version). However, it has been reported that the package will not run properly using the latest ROM (no matter what version of the Zaurus you use). More detailed information on how to fix this problem will be found further down this document. 8.4. Exult and Zaurus Exult uses SDL for multimedia access to the computer (music and video in particular). In order to play Exult on your Zaurus, you need to install the SDL library as well as the SDL-mixer library. Do not use the stock versions found on http://www.libsdl.org. Rather, use thespecially prepared versions for Zaurus found on http://www.gnurou.org. These versions support more features and are the only tested ones. 8.5. Installing new packages The first step to install a new package is to have the package downloaded and accessible from your Zaurus. I use a method I am comfortable with. If you have your own method and if it works, please keep using it! To copy packages on my Zaurus, I plug the cradle via USB to my Linux machine (Mandrake 8.2). I've changed the modules.usbmap file so that inserting the Zaurus on the cradle will automatically use the usbdnet module to access the Zaurus via USB-over-ethernet. Search the net to find out how. Once the connection is done, I upload the file via FTP to /mnt/cf/Documents/application/ipkg/. Then I start the add/remove package, select add new package and choose the file I just uploaded. 8.6. Using the standard ROM If like me you still use the standard ROM, simply install the SDL, SDL-mixer and Exult packages. You will also have to transfer the U7 data files to the Zaurus. I chose to install the data files on my Compact Flash card (/mnt/cf/) on the /mnt/cf/exult-data/si/static directory. Simply copy the content of your U7's static/ dir to this dir and you'll be done. The previous example is for Serpent Isle ("si" as you can see in the file path). For Black Gate, you would put "bg" instead of "si". Only the static dir is relevant. You can copy everything if you want to but it will space for nothing. 8.7. Installing the non-required packages Two additional packages exist and are not required. They hold the new musics for Exult and thus can be found on the Exult's download page. If you choose to install them as well, simply copy them to the Zaurus (see 5.1) and install them normally. 8.8. Using the latest ROM As mentioned earlier, Exult won't run properly on the latest ROM (v3.10 as of 20030801). There are a few reason why. First, since I haven't installed this ROM, I cannot test it. Then, I know they have changed the default user to be "zaurus" instead of "root", which mess up the paths and the config file. Indeed, by default, Exult reads its config file on ~/.exult.cfg which gets expanded to /home/root/.exult.cfg on the default ROM but to /home/zaurus/.exult.cfg on the newest ROM. Since the package installs all user-related files to /home/root, Exult won't find them on the latest ROM. Not only ~/.exult.cfg is concerned, but also ~/.exult/ which contains the gamedat (current runing game) and the savegames. Finally, the files' owner is set to "root" so the user "zaurus" won't be able to alter files and directories. 8.9. Solving the problems with the latest ROM In order to play, you'll have to change the location of the files installed by the package to /home/zaurus/ instead of /home/root/. I have not done this, but I expect you'd have to "su" to be able to change it. "su" is a command to become superuser (root). Not only you want to move the files ~/.exult.cfg and ~/.exult/ to /home/zaurus/ but you also want to edit the ~/.exult.cfg so that every occurence of /home/root/ is replaced with /home/zaurus. Please remember I have not done nor tested this, but here are the commands I suppose you'd have to type. First, open a terminal (install one if you don't have one). From the terminal, verify who you are by typing ($ is the prompt): $ cd ~/ $ whoami $ pwd The "whoami" command should return "zaurus". The "pwd" command should return "/home/zaurus/". Then copy the Exult files: $ cp /home/root/.exult* ~/ -rf And change ownership to yourself. You might have to become root to do so: $ su # chown zaurus:zaurus /home/zaurus/.exult* -R # chown zaurus:zaurus /opt/QtPalmtop/share/exult -R # chown zaurus:zaurus /opt/QtPalmtop/bin/exult* -R # chown zaurus:zaurus /opt/QtPalmtop/pics/exult.png -R # chown zaurus:zaurus /opt/QtPalmtop/apps/Games/exult.desktop -R # exit The # is the root's prompt. The "exit" command will stop the "su" command and make you return to the "zaurus" user. It is now time to edit the .exult.cfg. A fast way to do it: $ sed -e 's/root/zaurus/' >~/.exult.cfg ~/.exult.cfg_new $ mv ~/.exult.cfg_new ~/.exult.cfg Normally, you should be able to start and play the game normally. Let me know if I am missing anything. 8.10. Useful tidbits The key mappings are found in the files /opt/QtPalmtop/share/exult/keys_bg.txt and /opt/QtPalmtop/share/exult/keys_si.txt The Application keys are mapped this way: 'Calendar' = 'F9' = inventory (like pressing 'I') 'Address Book' = 'F10' = target mode (like pressing 'T') 'Home' = 'F12' = combat mode (like pressing 'C') 'Menu Popup' = 'F11' = use all keys (like pressing 'K' or 'Alt-K') 'Email' = 'F13' = spellbook (like pressing 'B') Save often. I have not had a crash since I'm using the latest SDL packages but you never know. Report any problem to the Exult forum at http://exult.sf.net/forum/ or email me (see 8.1.). -------------------------------------------------------------------------------- 9. Credits and Contact 9.1. Thanks * The people of SourceForge without whom this project would not be where it is today. * The paper by Gary Thompson on the structure of the U7 data files was crucial to the early development of Exult. * Work by Maxim Shatskih, Jakob Shonberg, and Wouter Dijkslag made the "usecode" interpreter possible. * Olivier Marcoux's technical document was also crucial in understanding some data files. * Thanks also go to the person who wrote u7items.txt and the contributor of the "avatar.ttf" font. * Aurelien Marchand (Artaxerxes) for his extensive guide for the Zaurus. 9.2. Contacting us You can contact the Exult team and/or get more information from: http://exult.sourceforge.net/ or http://sourceforge.net/projects/exult/ exult-1.2/txtscroll.cc0000644000175000001440000001310410054030532010526 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include #endif #include "exult_types.h" #include "files/U7file.h" #include "gamewin.h" #include "shapeid.h" #include "txtscroll.h" #include "font.h" #include "game.h" #include "SDL_timer.h" #include "SDL_events.h" #include "SDL_keysym.h" #ifndef UNDER_CE using std::atoi; using std::size_t; using std::strchr; using std::string; using std::strlen; using std::strncmp; using std::vector; #endif TextScroller::TextScroller(const char *archive, int index, Font *fnt, Shape *shp) { font = fnt; shapes = shp; U7object txtobj(archive, index); size_t len; const char CR = '\r', LF = '\n'; char *txt, *ptr, *end; txt = txtobj.retrieve(len); ptr = txt; end = ptr+len; text = new vector(); while(ptrpush_back(string(start)); ptr += 1; } else break; } delete [] txt; } TextScroller::~TextScroller() { delete text; } int TextScroller::show_line(Game_window *gwin, int left, int right, int y, int index) { Shape_manager *sman = Shape_manager::get_instance(); //The texts used in the main menu contains backslashed sequences that //indicates the output format of the lines: // \Px include picture number x (frame nr. of shape passed to constructor) // \C center line // \L left aligned to right center line // \R right aligned to left center line // | carriage return (stay on same line) // #xxx display character with number xxx string str = (*text)[index]; const char * ptr = str.c_str(); char *txt = new char[strlen(ptr)+1]; char *txtptr = txt; int ypos = y; int vspace = 2; // 2 extra pixels between lines // Align text to the left by default int align = -1; int xpos = left; int center = (right+left)/2; bool add_line = true; while(*ptr) { if(!strncmp(ptr,"\\P",2)) { int pix = *(ptr+2)-'0'; ptr +=3; Shape_frame *frame = shapes->get_frame(pix); if (frame) { sman->paint_shape(center-frame->get_width()/2, ypos, frame); ypos += frame->get_height()+vspace; } } else if(!strncmp(ptr,"\\C",2)) { ptr += 2; align = 0; } else if(!strncmp(ptr,"\\L",2)) { ptr += 2; align = 1; } else if(!strncmp(ptr,"\\R",2)) { ptr += 2; align = -1; } else if(*ptr=='|' || *(ptr+1)==0) { if(*(ptr+1)==0 && *ptr!='|') { *txtptr++ = *ptr; add_line = false; } *txtptr = 0; if(align<0) xpos = center-font->get_text_width(txt); else if(align==0) xpos = center-font->get_text_width(txt)/2; else xpos = center; font->draw_text(gwin->get_win()->get_ib8(), xpos,ypos,txt); if(*ptr!='|') ypos += font->get_text_height()+vspace; txtptr = txt; // Go to beginning of string ++ptr; } else if(*ptr=='#') { ptr++; if(*ptr=='#') { // Double hash *txtptr++ = *ptr++; continue; } char numerical[4] = {0,0,0,0}; char *num = numerical; while (*ptr >= '0' && *ptr <= '9') *num++ = *ptr++; *txtptr++ = atoi(numerical); } else *txtptr++ = *ptr++; } delete [] txt; if(add_line) ypos += font->get_text_height(); return ypos; } bool TextScroller::run(Game_window *gwin) { gwin->clear_screen(); gwin->show(1); int topx = (gwin->get_width()-320)/2; int topy = (gwin->get_height()-200)/2; int endy = topy+200; uint32 starty = endy; uint32 startline = 0; unsigned int maxlines = text->size(); bool looping = true; bool complete = false; SDL_Event event; uint32 next_time = SDL_GetTicks() + 200; uint32 incr = 120; // pal.apply(); gwin->get_pal()->apply(); while(looping) { int ypos = starty; uint32 curline = startline; gwin->clear_screen(); do { if(curline==maxlines) break; ypos = show_line(gwin, topx, topx+320, ypos, curline++); if(ypos=maxlines) { looping = false; complete = true; break; } } } while (yposshow(1); do { // this could be a problem when too many events are produced while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: if(event.key.keysym.sym==SDLK_RSHIFT || event.key.keysym.sym==SDLK_LSHIFT) incr = 0; else looping = false; break; case SDL_KEYUP: incr = 120; next_time = SDL_GetTicks(); break; case SDL_MOUSEBUTTONUP: looping = false; break; default: break; } } } while (next_time > SDL_GetTicks()); next_time = SDL_GetTicks() + incr; if(!looping) gwin->get_pal()->fade_out(c_fade_out_time); starty--; } gwin->clear_screen(); gwin->show(1); return complete; } int TextScroller::get_count() { return text->size(); } exult-1.2/browser.cc0000644000175000001440000001627707724430447010214 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include "files/U7file.h" #include "gamewin.h" #include "game.h" #include "browser.h" #include "exult.h" #include "font.h" #include "items.h" #include "shapeid.h" #ifndef HAVE_SNPRINTF extern int snprintf(char *, size_t, const char *, /*args*/ ...); namespace std { using ::snprintf; } #else #endif ShapeBrowser::ShapeBrowser() { num_shapes = 0; current_shape = 0; num_frames = 0; current_frame = 0; num_files = game->get_resource("files/shapes/count").num; current_file = 0; shapes = 0; num_palettes = game->get_resource("palettes/count").num; current_palette = 0; num_xforms = game->get_resource("xforms/count").num; current_xform = -1; } ShapeBrowser::~ShapeBrowser() { if(shapes) delete shapes; } static void handle_key(int shift, int& value, int max, int amt = 1) { if (max == 0) return; if(shift) value -= amt; else value += amt; while (value<0) value = max+value; while (value>=max) value = value-max; } void ShapeBrowser::browse_shapes() { Game_window *gwin = Game_window::get_instance(); Shape_manager *sman = Shape_manager::get_instance(); Image_buffer8 *ibuf = gwin->get_win()->get_ib8(); Font *font = fontManager.get_font("MENU_FONT"); int maxx = gwin->get_width(); int centerx = maxx/2; int maxy = gwin->get_height(); int centery = maxy/2; Palette pal; char buf[255]; str_int_pair pal_tuple, xform_tuple; const char *fname; snprintf(buf,255,"files/shapes/%d",current_file); fname = game->get_resource(buf).str; if(!shapes) shapes = new Vga_file(fname); bool looping = true; bool redraw = true; SDL_Event event; //int active; do { if (redraw) { gwin->clear_screen(); snprintf(buf,255,"palettes/%d",current_palette); pal_tuple = game->get_resource(buf); char xfrsc[256]; if (current_xform > 0) { snprintf(xfrsc, 255, "xforms/%d", current_xform); xform_tuple = game-> get_resource(xfrsc); pal.load(pal_tuple.str, pal_tuple.num, xform_tuple.str, xform_tuple.num); } else pal.load(pal_tuple.str,pal_tuple.num); snprintf(buf,255,"VGA File: '%s'", fname); //font->draw_text(ibuf, 0, 170, buf); font->paint_text_fixedwidth(ibuf, buf, 2, maxy-30, 8); num_shapes = shapes->get_num_shapes(); snprintf(buf,255,"Shape: %2d/%d", current_shape, num_shapes-1); //font->draw_text(ibuf, 0, 180, buf); font->paint_text_fixedwidth(ibuf, buf, 2, maxy-20, 8); num_frames = shapes->get_num_frames(current_shape); snprintf(buf,255,"Frame: %2d/%d", current_frame, num_frames-1); //font->draw_text(ibuf, 160, 180, buf); font->paint_text_fixedwidth(ibuf, buf, 162, maxy-20, 8); snprintf(buf,255,"Palette: %s, %d", pal_tuple.str, pal_tuple.num); //font->draw_text(ibuf, 0, 190, buf); font->paint_text_fixedwidth(ibuf, buf, 2, maxy-10, 8); if (num_frames) { Shape_frame *frame = shapes->get_shape( current_shape, current_frame); if (frame) { snprintf(buf,255,"%d x %d", frame->get_width(), frame->get_height()); //font->draw_text(ibuf, 32, 32, buf); font->paint_text_fixedwidth(ibuf, buf, 2, 22, 8); Shape_info& info = ShapeID::get_info(current_shape); snprintf(buf,255,"class: %2i ready_type: 0x%02x", info.get_shape_class(), info.get_ready_type()); font->paint_text_fixedwidth(ibuf, buf, 2, 12, 8); //font->draw_text(ibuf, 32, 16, item_names[current_shape]); font->paint_text_fixedwidth(ibuf, item_names[current_shape], 2, 2, 8); //draw outline gwin->get_win()->fill8(255, frame->get_width()+4, frame->get_height()+4, gwin->get_width()/2 - frame->get_xleft() - 2, gwin->get_height()/2 - frame->get_yabove() - 2); gwin->get_win()->fill8(0, frame->get_width()+2, frame->get_height()+2, gwin->get_width()/2 - frame->get_xleft()-1, gwin->get_height()/2 - frame->get_yabove()-1); //draw shape sman->paint_shape(gwin->get_width()/2, gwin->get_height()/2, frame, 1); } else font->draw_text(ibuf, centerx-20, centery-5, "No Shape"); } else font->draw_text(ibuf, centerx-20, centery-5, "No Shape"); pal.apply(); redraw = false; } SDL_WaitEvent(&event); if(event.type==SDL_KEYDOWN) { redraw = true; int shift = event.key.keysym.mod & KMOD_SHIFT; //int ctrl = event.key.keysym.mod & KMOD_CTRL; switch(event.key.keysym.sym) { case SDLK_ESCAPE: looping = false; break; case SDLK_v: handle_key(shift, current_file, num_files); current_shape = 0; current_frame = 0; delete shapes; snprintf(buf,255,"files/shapes/%d",current_file); fname = game->get_resource(buf).str; shapes = new Vga_file(fname); break; case SDLK_p: handle_key(shift, current_palette, num_palettes); current_xform = -1; break; case SDLK_x: handle_key(shift, current_xform, num_xforms); break; // Shapes case SDLK_s: if ((event.key.keysym.mod & KMOD_ALT) && (event.key.keysym.mod & KMOD_CTRL)) make_screenshot(true); else { handle_key(shift, current_shape, num_shapes); current_frame = 0; } break; case SDLK_UP: handle_key(1, current_shape, num_shapes); current_frame = 0; break; case SDLK_DOWN: handle_key(0, current_shape, num_shapes); current_frame = 0; break; case SDLK_j: // Jump by 20. handle_key(shift, current_shape, num_shapes, 20); current_frame = 0; break; case SDLK_PAGEUP: handle_key(1, current_shape, num_shapes, 20); current_frame = 0; break; case SDLK_PAGEDOWN: handle_key(0, current_shape, num_shapes, 20); current_frame = 0; break; // Frames case SDLK_f: handle_key(shift, current_frame, num_frames); break; case SDLK_LEFT: handle_key(1, current_frame, num_frames); break; case SDLK_RIGHT: handle_key(0, current_frame, num_frames); break; default: break; } } } while(looping); } bool ShapeBrowser::get_shape(int& shape, int& frame) { if(!shapes || current_file!=0) return false; else { shape = current_shape; frame = current_frame; return true; } } exult-1.2/frameseq.h0000644000175000001440000000316007724430450010153 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_FRAMESEQ #define INCL_FRAMESEQ 1 /* * A sequence of frames. Frame 0 is the resting state. */ class Frames_sequence { unsigned char *frames; int num_frames; public: Frames_sequence(int cnt, unsigned char *f); ~Frames_sequence() { delete [] frames; } // Get resting frame. unsigned char get_resting() const { return frames[0]; } // Get next frame. Call // with index = 0 for first one. unsigned char get_next(int& index) const { if (++index >= num_frames) index = 1; return frames[index]; } void decrement(int& index) const { if (--index <= 0) index = num_frames - 1; } // Find frame, masking off rotation. // Rets. 0 if not found. int find_unrotated(unsigned char frame) { for (int i = num_frames - 1; i > 0; i--) if (((frame ^ frames[i])&0xf) == 0) return i; return 0; } }; #endif exult-1.2/Makefile.common0000644000175000001440000001745710061526063011136 VPATH=$(SRC):$(SRC)/audio:$(SRC)/audio/midi_drivers:$(SRC)/conf:$(SRC)/data:$(SRC)/files:$(SRC)/files/zip:$(SRC)/flic: \ $(SRC)/gumps:$(SRC)/imagewin:$(SRC)/mapedit/tools/mockup:$(SRC)/mapedit/tools/smooth:$(SRC)/objs:$(SRC)/pathfinder \ $(SRC)/shapes:$(SRC)/server:$(SRC)/tools:$(SRC)/usecode:$(SRC)/usecode/compiler:$(SRC)/usecode/ucxt:$(SRC)/usecode/ucxt/src VERSION=1.2 MAIN_OBJS=actions.o actorio.o actors.o alloc.o \ args.o bggame.o browser.o cheat.o \ combat.o delobjs.o devgame.o \ dir.o drag.o effects.o exult.o exultmenu.o \ game.o gameclk.o gamedat.o gamemap.o \ gamerend.o gamewin.o keys.o keyactions.o \ menulist.o monsters.o mouse.o npcnear.o npctime.o palette.o \ party.o \ paths.o readnpcs.o schedule.o segfile.o sigame.o tqueue.o txtscroll.o \ exultico.o cheat_screen.o shapeid.o version.o windrag.o # unused: npctest.o PATH_OBJS=Astar.o PathFinder.o Zombie.o path.o CONF_OBJS=Configuration.o XMLEntity.o # unused: xmain.o AUDIO_OBJS=Audio.o conv.o Midi.o xmidi.o soundtest.o $(MIDI_DRV_OBJS) # unused: test.o u7audiotool.o FLIC_OBJS=playfli.o FILE_OBJS+=U7file.o Flex.o IFF.o Table.o Flat.o utils.o listfiles.o crc.o \ msgfile.o # Zipfile support objs ZIP_OBJS=zip.o unzip.o GUMPS_OBJS= Actor_gump.o Book_gump.o File_gump.o Gump.o Gump_button.o \ Gump_widget.o misc_buttons.o Paperdoll_gump.o \ Paperdoll_gump_info.o Scroll_gump.o Sign_gump.o Slider_gump.o \ Spellbook_gump.o Stats_gump.o Text_gump.o Yesno_gump.o \ Gamemenu_gump.o Newfile_gump.o Gump_ToggleButton.o \ AudioOptions_gump.o Face_button.o CombatStats_gump.o \ Jawbone_gump.o VideoOptions_gump.o Face_stats.o Gump_manager.o \ Text_button.o GameplayOptions_gump.o CombatOptions_gump.o \ Enabled_button.o IMAGEWIN_OBJS=imagebuf.o imagewin.o iwin8.o ibuf8.o ibuf16.o imagescl.o \ savepcx.o SHAPES_OBJS=bodies.o items.o shapeinf.o shapevga.o vgafile.o font.o fontvga.o \ monstinf.o u7drag.o OBJS_OBJS=animate.o barge.o chunks.o chunkter.o \ contain.o egg.o iregobjs.o mappatch.o objs.o objiter.o \ spellbook.o virstone.o jawbone.o objnames.o USECODE_OBJS=stackframe.o ucfunction.o ucinternal.o ucmachine.o ucsched.o intrinsics.o \ useval.o conversation.o keyring.o ucdisasm.o OBJS+=$(MAIN_OBJS) $(PATH_OBJS) $(CONF_OBJS) $(AUDIO_OBJS) $(FLIC_OBJS) $(FILE_OBJS) $(GUMPS_OBJS) $(OBJS_OBJS) $(SHAPES_OBJS) $(IMAGEWIN_OBJS) $(USECODE_OBJS) $(ZIP_OBJS) $(SERVER_OBJS) EXULT_FLX = data/exult.flx data/exult_flx.h EXULT_FLX_OBJECTS = \ data/exult_quotes.shp \ data/exult_credits.shp \ data/quotes.txt \ data/credits.txt \ data/exult_logo.shp \ data/exult0.pal \ data/black_gate.shp \ data/serpent_isle.shp \ data/meditown.mid \ data/font.shp \ data/setup.shp \ data/play_intro.shp \ data/full_screen.shp \ data/cheating.shp \ data/ok.shp \ data/cancel.shp \ data/pointers.shp \ data/exit.shp \ data/play_1st_scene.shp \ data/extras.shp \ data/midi_conversion.shp \ data/sfx_conversion.shp \ data/palette_fades.shp \ data/scaling_method.shp \ data/savegump.shp \ data/sav_downdown.shp \ data/sav_down.shp \ data/sav_up.shp \ data/sav_upup.shp \ data/sav_slider.shp \ data/sav_selected.shp \ data/gameplayoptions.shp \ data/gamemenu.shp \ data/audiooptions.shp \ data/videooptions.shp \ data/hp_bar.shp \ data/sfx_icon.shp \ data/flx.in EXULT_BG_FLX = data/exult_bg.flx data/exult_bg_flx.h EXULT_BG_FLX_OBJECTS = \ data/bg/hoe_of_destruction.shp \ data/bg/caddellite_helmet.shp \ data/bg/great_dagger.shp \ data/bg/magic_boomerang.shp \ data/bg/gorget.shp \ data/bg/magicgorget.shp \ data/bg/cleaver.shp \ data/bg/faces.shp \ data/bg/faces2.shp \ data/bg/amulets.shp \ data/bg/bgfiredoom.shp \ data/bg/fellowshipstaff.shp \ data/bg/BGmap.shp \ data/bg/defaultkeys.txt \ data/bg/dupre_face.shp \ data/bg/fem_av_face.shp \ data/bg/iolo_face.shp \ data/bg/male_av_face.shp \ data/bg/shamino_face.shp \ data/bg/greaves.shp \ data/bg/spiked_shield.shp \ data/bg/mr_faces.shp \ data/bg/mr_intro.shp \ data/bg/firesword.shp \ data/bg/greencloak.shp \ data/bg/greycloak.shp \ data/bg/ring_of_protection.shp \ data/bg/greentop.shp \ data/bg/orangedress.shp \ data/bg/bluedress.shp \ data/bg/death_scythe.shp \ data/bg/firewand.shp \ data/bg/knife.shp \ data/bg/starburst.shp \ data/bg/hawk.shp \ data/bg/musket_ammo.shp \ data/bg/shoes.shp \ data/bg/triple_xbow.shp \ data/bg/pants.shp \ data/bg/collar.shp \ data/bg/hoods.shp \ data/bg/musket.shp \ data/bg/custom_sword.shp \ data/bg/flx.in EXULT_SI_FLX = data/exult_si.flx data/exult_si_flx.h EXULT_SI_FLX_OBJECTS = \ data/si/SImap.shp \ data/si/defaultkeys.txt \ data/si/flx.in FLEXES = $(EXULT_FLX) $(EXULT_BG_FLX) $(EXULT_SI_FLX) $(EXEC) : $(FLEXES) $(OBJS) $(CXX) $(LFLAGS) -o $@ $(OBJS) $(LIBS) expack$(EXEEXT) : expack.o $(FILE_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ $(EXULT_FLX): expack$(EXEEXT) $(EXULT_FLX_OBJECTS) expack$(EXEEXT) -i data/flx.in $(EXULT_BG_FLX): expack$(EXEEXT) $(EXULT_BG_FLX_OBJECTS) expack$(EXEEXT) -i data/bg/flx.in $(EXULT_SI_FLX): expack$(EXEEXT) $(EXULT_SI_FLX_OBJECTS) expack$(EXEEXT) -i data/si/flx.in cmanip$(EXEEXT) : cmanip.o $(CONF_OBJS) $(FILE_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ IPACK_OBJS=ipack.o U7file.o Flex.o IFF.o Table.o Flat.o utils.o imagebuf.o ibuf8.o ibuf16.o vgafile.o pngio.o ipack$(EXEEXT) : $(IPACK_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ -lpng -lz mklink$(EXEEXT) : mklink.o $(CXX) $(LFLAGS) -o $(@) $+ mockup$(EXEEXT): main.o $(CC) $(LFLAGS) -o $(@) $+ $(SDL_IMAGE_LIBS) rip$(EXEEXT) : rip.o $(CXX) $(LFLAGS) -o $(@) $+ SMOOTH_OBJS=config.o image.o linked.o param.o plugin.o smooth.o smooth$(EXEEXT) : $(SMOOTH_OBJS) $(CC) $(LFLAGS) -o $(@) $+ $(SDL_IMAGE_LIBS) shp2pcx$(EXEEXT) : shp2pcx.o $(CXX) $(LFLAGS) -o $(@) $+ splitshp$(EXEEXT) : splitshp.o $(CXX) $(LFLAGS) -o $(@) $+ textpack$(EXEEXT) : textpack.o $(FILE_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ u7voice2syx$(EXEEXT) : u7voice2syx.o $(FILE_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ wud$(EXEEXT) : wud.o uctools.h bgintrinsics.h siintrinsics.h $(CXX) $(LFLAGS) -o $(@) wud.o wuc$(EXEEXT) : wuc.o $(CXX) $(LFLAGS) -o $(@) $+ UCC_OBJS=ucparse.o uclex.o ucmain.o ucexpr.o ucfun.o ucloc.o ucstmt.o ucsym.o ucc$(EXEEXT) : $(UCC_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ -liberty ucparse.cc: bison -d usecode/compiler/ucparse.yy -o ucparse.c mv ucparse.c ucparse.cc uclex.cc: flex usecode/compiler/uclex.ll mv lex.yy.c uclex.cc UCXT_OBJS=$(CONF_OBJS) utils.o ucdata.o ucxt.o ucfunc.o ops.o ucxt$(EXEEXT) : $(UCXT_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ CONFREGRESS_OBJS=$(CONF_OBJS) xmain.o utils.o confregress$(EXEEXT) : $(CONFREGRESS_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ head2data$(EXEEXT) : head2data.o $(FILE_OBJS) $(CXX) $(LFLAGS) -o $(@) $+ head2data.test: head2data data/u7bgintrinsics.data data/u7siintrinsics.data all: $(EXEC) clean: rm -f $(OBJS) expack.o $(EXEC) expack$(EXEEXT) data/exult.flx data/exult_flx.h data/exult_bg.flx data/exult_bg_flx.h data/exult_si.flx data/exult_si_flx.h tools: expack$(EXEEXT) cmanip$(EXEEXT) ipack$(EXEEXT) mklink$(EXEEXT) mockup$(EXEEXT) rip$(EXEEXT) shp2pcx$(EXEEXT) smooth$(EXEEXT) splitshp$(EXEEXT) textpack$(EXEEXT) wuc$(EXEEXT) wud$(EXEEXT) u7voice2syx$(EXEEXT) ucc$(EXEEXT) ucxt$(EXEEXT) head2data$(EXEEXT) head2data.test toolsclean: rm -f expack.o expack$(EXEEXT) $(FILE_OBJS) rm -f cmanip$(EXEEXT) cmanip.o rm -f ipack.o ipack$(EXEEXT) $(IPACK_OBJS) rm -f main.o mockup$(EXEEXT) rm -f mklink.o mklink$(EXEEXT) rm -f rip.o rip$(EXEEXT) rm -f shp2pcx.o shp2pcx$(EXEEXT) rm -f splitshp.o splitshp$(EXEEXT) rm -f $(SMOOTH_OBJS) smooth$(EXEEXT) rm -f textpack.o textpack$(EXEEXT) rm -f ucc.o ucc$(EXEEXT) rm -f u7voice2syx.o u7voice2syx$(EXEEXT) rm -f wuc.o wuc$(EXEEXT) rm -f wud.o wud$(EXEEXT) rm -f $(UCXT_OBJS) ucxt$(EXEEXT) rm -f $(UCC_OBJS) ucc$(EXEEXT) ucparse.cc ucparse.h uclex.cc rm -f $(CONFREGRESS_OBJS) confregress$(EXEEXT) rm -f head2data.o head2data$(EXEEXT) data/u7bgintrinsics.data data/u7siintrinsics.data exult-1.2/ltmain.sh0000644000175000001440000043256310013577154010032 # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" # Parse our command line options once, thoroughly. while test $# -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" exit 0 ;; --config) ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 exit 0 ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # Mandrake: (gc) It's bad to link C++ code with GCC, so we need to use the compiler name if provided if test "$mode" = link && test -n "$archive_cmds" && test -x "/usr/bin/perl"; then case $nonopt in *cc | *++ | gcc* | *-gcc* | egcs*) archive_cmds=`echo $archive_cmds | perl -pe 's/^\S+\s+//'` archive_cmds="$nonopt $archive_cmds" archive_expsym_cmds=`echo $archive_expsym_cmds | perl -pe 's/^\S+\s+//'` archive_expsym_cmds="$nonopt $archive_expsym_cmds" esac fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then case $nonopt in *cc | *++ | gcc* | *-gcc* | xlc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= prev= lastarg= srcfile="$nonopt" suppress_output= user_target=no for arg do case $prev in "") ;; xcompiler) # Aesthetically quote the previous argument. prev= lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac # Accept any command-line options. case $arg in -o) if test "$user_target" != "no"; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi user_target=next ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) prev=xcompiler continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac case $user_target in next) # The next one is the -o target name user_target=yes continue ;; yes) # We got the output file user_target=set libobj="$arg" continue ;; esac # Accept the current argument as the source file. lastarg="$srcfile" srcfile="$arg" # Aesthetically quote the previous argument. # Backslashify any backslashes, double quotes, and dollar signs. # These are the only characters that are still specially # interpreted inside of double-quoted scrings. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $lastarg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi done case $user_target in set) ;; no) # Get the name of the library object. libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; *) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSfmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $libobj" else removelist="$libobj" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" else # Don't build PIC code command="$base_compile $srcfile" fi if test "$build_old_libs" = yes; then lo_libobj="$libobj" dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$libobj"; then dir="$objdir" else dir="$dir/$objdir" fi libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` if test -d "$dir"; then $show "$rm $libobj" $run $rm $libobj else $show "$mkdir $dir" $run $mkdir $dir status=$? if test $status -ne 0 && test ! -d $dir; then exit $status fi fi fi if test "$compiler_o_lo" = yes; then output_obj="$libobj" command="$command -o $output_obj" elif test "$compiler_c_o" = yes; then output_obj="$obj" command="$command -o $output_obj" fi $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test x"$output_obj" != x"$libobj"; then $show "$mv $output_obj $libobj" if $run $mv $output_obj $libobj; then : else error=$? $run $rm $removelist exit $error fi fi # If we have no pic_flag, then copy the object into place and finish. if (test -z "$pic_flag" || test "$pic_mode" != default) && test "$build_old_libs" = yes; then # Rename the .lo from within objdir to obj if test -f $obj; then $show $rm $obj $run $rm $obj fi $show "$mv $libobj $obj" if $run $mv $libobj $obj; then : else error=$? $run $rm $removelist exit $error fi xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` # Now arrange that obj and lo_libobj become the same file $show "(cd $xdir && $LN_S $baseobj $libobj)" if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 else error=$? $run $rm $removelist exit $error fi fi # Allow error messages only from the first compilation. suppress_output=' >/dev/null 2>&1' fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $srcfile" else # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" output_obj="$obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test x"$output_obj" != x"$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Create an invalid libtool object if no PIC, so that we do not # accidentally link it into a program. if test "$build_libtool_libs" != yes; then $show "echo timestamp > $libobj" $run eval "echo timestamp > \$libobj" || exit $? else # Move the .lo from within objdir $show "$mv $libobj $lo_libobj" if $run $mv $libobj $lo_libobj; then : else error=$? $run $rm $removelist exit $error fi fi fi # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 ;; # libtool link mode link | relink) modename="$modename: link" case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invokation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args="$nonopt" compile_command="$nonopt" finalize_command="$nonopt" compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= # We need to know -static, to get the right output filenames. for arg do case $arg in -all-static | -static) if test "X$arg" = "X-all-static"; then if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test $# -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n $prev prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | no/*-*-nonstopux*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.lo | *.$objext) # A library or standard object. if test "$prev" = dlfiles; then # This file was specified with -dlopen. if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $arg" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` prev= else case $arg in *.lo) libobjs="$libobjs $arg" ;; *) objs="$objs $arg" ;; esac fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d $output_objdir; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test $linkmode = prog; then # Determine which files to process case $pass in dlopen) libs="$dlfiles" save_deplibs="$deplibs" # Collect dlpreopened libraries deplibs= ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test $linkmode = oldlib && test $linkmode = obj; then $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 continue fi if test $pass = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do # Search the libtool library lib="$searchdir/lib${name}.la" if test -f "$lib"; then found=yes break fi done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test $pass = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi if test $pass = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test $pass = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then echo echo "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not used here." else echo echo "*** Warning: Linking the shared library $output against the" echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test $pass != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test $found = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variable installed. installed=yes # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test $linkmode = oldlib && test $linkmode = obj; }; then # Add dl[pre]opened files of deplib test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test $pass = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test $linkmode != prog && test $linkmode != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test $pass = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. dlprefiles="$dlprefiles $lib" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test $pass = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test $linkmode = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" fi continue fi if test $linkmode = prog && test $pass != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test $linkalldeplibs = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # Link against this shared library if test "$linkmode,$pass" = "prog,link" || { test $linkmode = lib && test $hardcode_into_libs = yes; }; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac if test $linkmode = prog; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi fi fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`echo $soroot | ${SED} -e 's/^.*\///'` newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n $old_archive_from_expsyms_cmds if test $linkmode = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test $linkmode = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test $linkmode = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" add="-l$name" fi if test $linkmode = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test $linkmode = prog; then if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi # Try to link the static library # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo echo "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test $linkmode = lib; then if test -n "$dependency_libs" && { test $hardcode_into_libs != yes || test $build_old_libs = yes || test $link_static = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test $link_all_deplibs != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="-L$absdir/$objdir" else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="-L$absdir" fi ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test $pass = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test $pass != dlopen; then test $pass != scan && dependency_libs="$newdependency_libs" if test $pass != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do case $deplib in -L*) new_libs="$deplib $new_libs" ;; *) case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi if test "$pass" = "conv" && { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then libs="$deplibs" # reset libs deplibs= fi done # for pass if test $linkmode = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else echo echo "*** Warning: Linking the shared library $output against the non-libtool" echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test $# -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. libext=al oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi current="$2" revision="$3" age="$4" # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test $age -gt $current; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) major=`expr $current - $age + 1` case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test $loop != 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=.`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test $loop != 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= verstring="0.0" case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring="" ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs. $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'` deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'` dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test $hardcode_into_libs != yes || test $build_old_libs = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. ;; *) # Add libc to deplibs on all other systems if necessary. if test $build_libtool_need_lc = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behaviour. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done # It is ok to link against an archive when # building a shared library. if $AR -t $potlib > /dev/null 2>&1; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | ${SED} 10q \ | egrep "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for file magic test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check below in file_magic test if eval echo \"$potent_lib\" 2>/dev/null \ | ${SED} 10q \ | egrep "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for regex pattern test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | grep . >/dev/null; then echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" echo "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test $allow_undefined = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test $hardcode_into_libs = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi test -z "$dlname" && dlname=$soname lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Ensure that we have .o objects for linkers which dislike .lo # (e.g. aix) in case we are running --disable-static for obj in $libobjs; do xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` if test ! -f $xdir/$oldobj; then $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? fi done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else save_deplibs="$deplibs" for conv in $convenience; do tmp_deplibs= for test_deplib in $deplibs; do if test "$test_deplib" != "$conv"; then tmp_deplibs="$tmp_deplibs $test_deplib" fi done deplibs="$tmp_deplibs" done eval cmds=\"$archive_cmds\" deplibs="$save_deplibs" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. $show "echo timestamp > $libobj" $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" else # Just create a symlink. $show $rm $libobj $run $rm $libobj xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$libobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` $show "(cd $xdir && $LN_S $oldobj $baseobj)" $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` case $host in *darwin*) # Don't allow lazy linking, it breaks C++ global constructors compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | ${SED} -e 's%^.*/%%'` $run eval 'echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test $need_relink = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe ;; *) exeext= ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 ${SED} $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # win32 systems need to use the prog path for dll # lookup to work *-*-cygwin* | *-*-pw32*) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ # Export the path to the program. PATH=\"\$progdir:\$PATH\" export PATH exec \$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else # Ensure that we have .o objects in place in case we decided # not to build a shared library, and have fallen back to building # static libs even though --disable-static was passed! for oldobj in $oldobjs; do if test ! -f $oldobj; then xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$oldobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` $show "(cd $xdir && ${LN_S} $obj $baseobj)" $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? fi done eval cmds=\"$old_archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi # We do not want portage's install root ($D) present. Check only for # this if the .la is being installed. if test "$installed" = yes && test "$D"; then eval mynewdependency_lib="`echo "$libdir/$name" |sed -e "s:$D::g" -e 's://:/:g'`" else mynewdependency_lib="$libdir/$name" fi # Do not add duplicates if test "$mynewdependency_lib"; then if test -z "`echo $newdependency_libs |grep -e "$mynewdependency_lib"`"; then newdependency_libs="$newdependency_libs $mynewdependency_lib" fi fi ;; *) if test "$installed" = yes; then # Rather use S=WORKDIR if our version of portage supports it. # This is because some ebuild (gcc) do not use $S as buildroot. if test "$PWORKDIR"; then S="$PWORKDIR" fi # We do not want portage's build root ($S) present. if test -n "`echo $deplib |grep -e "$S"`" && test "$S"; then mynewdependency_lib="" # We do not want portage's install root ($D) present. elif test -n "`echo $deplib |grep -e "$D"`" && test "$D"; then eval mynewdependency_lib="`echo "$deplib" |sed -e "s:$D::g" -e 's://:/:g'`" else mynewdependency_lib="$deplib" fi else mynewdependency_lib="$deplib" fi # Do not add duplicates if test "$mynewdependency_lib"; then if test -z "`echo $newdependency_libs |grep -e "$mynewdependency_lib"`"; then newdependency_libs="$newdependency_libs $mynewdependency_lib" fi fi ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac # Do not add duplicates if test "$installed" = yes && test "$D"; then install_libdir="`echo "$install_libdir" |sed -e "s:$D::g" -e 's://:/:g'`" fi $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test $need_relink = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test $# -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 continue fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`echo $file | ${SED} -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in /usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`echo $destfile | ${SED} -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = ":" && exit 0 echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do echo " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" echo "more information, such as the ld(1) and ld.so(8) manual pages." echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved enviroment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$objdir" else objdir="$dir/$objdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test $mode = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test $mode = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test $mode = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) if test "$build_old_libs" = yes; then oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` rmfiles="$rmfiles $dir/$oldobj" fi ;; *) # Do a test to see if this is a libtool program. if test $mode = clean && (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$file rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: exult-1.2/drag.cc0000644000175000001440000003725510032176335007432 /* * drag.cc - Dragging objects in Game_window. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include /* Debugging */ #include "gamewin.h" #include "gamemap.h" #include "drag.h" #include "Gump_button.h" #include "Gump.h" #include "mouse.h" #include "paths.h" #include "actors.h" #include "cheat.h" #include "chunks.h" #include "Audio.h" #include "Gump_manager.h" #include "ucmachine.h" #include "barge.h" using std::cout; using std::endl; /* * Create for a given (newly created) object. */ Dragging_info::Dragging_info ( Game_object *newobj // Object NOT in world. This is // dropped, or deleted. ) : obj(newobj), is_new(true), gump(0), button(0), old_pos(-1, -1, -1), old_foot(0, 0, 0, 0), old_lift(-1), quantity(obj->get_quantity()), paintx(-1000), painty(-1000), readied_index(-1), mousex(-1), mousey(-1), rect(0, 0, 0, 0), save(0), okay(true), possible_theft(false) { rect = gwin->get_shape_rect(obj); rect.enlarge(8); // Make a little bigger. // Create buffer to backup background. save = gwin->get_win()->create_buffer(rect.w, rect.h); } /* * Begin a possible drag. */ Dragging_info::Dragging_info ( int x, int y // Mouse position. ) : obj(0), is_new(false), gump(0), button(0), old_pos(-1, -1, -1), old_foot(0, 0, 0, 0), old_lift(-1), quantity(0), readied_index(-1), mousex(x), mousey(y), rect(0, 0, 0, 0), save(0), okay(false), possible_theft(false) { // First see if it's a gump. gump = gumpman->find_gump(x, y); if (gump) { obj = gump->find_object(x, y); if (obj) { // Save location info. gump->get_shape_location(obj, paintx, painty); old_pos = Tile_coord(obj->get_cx(), obj->get_cy(), 0); } else if ((button = gump->on_button(x, y)) != 0) { gump = 0; if (!button->is_draggable()) return; button->push(); // Pushed button, so make noise. Audio::get_ptr()->play_sound_effect( Audio::game_sfx(96)); gwin->set_painted(); } else if (gump->is_draggable()) { // Dragging whole gump. paintx = gump->get_x(); painty = gump->get_y(); cout << "(x,y) rel. to gump is (" << (x-paintx) << ", " << (y-painty) << ")"<find_object(x, y); if (!obj) return; // Get coord. where painted. gwin->get_shape_location(obj, paintx, painty); old_pos = obj->get_tile(); old_foot = obj->get_footprint(); } if (obj) { quantity = obj->get_quantity(); // Save original lift. old_lift = obj->get_outermost()->get_lift(); } okay = true; } /* * Delete dragging info. */ Dragging_info::~Dragging_info ( ) { delete save; } /* * First motion. * * Output: false if failed. */ bool Dragging_info::start ( int x, int y // Mouse position. ) { if (x - mousex <= 2 && mousex - x <= 2 && y - mousey <= 2 && mousey - y <= 2) return (false); // Wait for greater motion. if (obj) { // Don't want to move walls. if (!cheat.in_hack_mover() && !obj->is_dragable() && !obj->get_owner()) { Mouse::mouse->flash_shape(Mouse::tooheavy); obj = 0; gump = 0; okay = false; return (false); } Game_object *owner = obj->get_outermost(); if (owner == obj) { if (!cheat.in_hack_mover() && !Fast_pathfinder_client::is_grabable( gwin->get_main_actor()->get_tile(), obj->get_tile())) { Mouse::mouse->flash_shape(Mouse::blocked); obj = 0; okay = false; return (false); } } } // Store original pos. on screen. rect = gump ? (obj ? gump->get_shape_rect(obj) : gump->get_dirty()) : gwin->get_shape_rect(obj); if (gump) // Remove from actual position. if (obj) { Container_game_object *owner = gump->get_cont_or_actor(x,y); if (owner) readied_index = owner->find_readied(obj); gump->remove(obj); } else gumpman->remove_gump(gump); else obj->remove_this(true); // This SHOULD work (jsf 21-12-01). // Make a little bigger. rect.enlarge(obj ? 8 : 12); Rectangle crect = gwin->clip_to_win(rect); gwin->paint(crect); // Paint over obj's. area. // Create buffer to backup background. save = gwin->get_win()->create_buffer(rect.w, rect.h); return true; } /* * Mouse was moved while dragging. * * Output: true iff movement started/continued. */ bool Dragging_info::moved ( int x, int y // Mouse pos. in window. ) { if (!obj && !gump) return (false); if (rect.w == 0) { if (!start(x, y)) return false; } else // Not first time? Restore beneath. gwin->get_win()->put(save, rect.x, rect.y); gwin->set_painted(); int deltax = x - mousex, deltay = y - mousey; mousex = x; mousey = y; // Shift to new position. rect.shift(deltax, deltay); paintx += deltax; painty += deltay; if (gump && !obj) // Dragging a gump? gump->set_pos(paintx, painty); gwin->add_dirty(gwin->clip_to_win(rect)); return (true); } /* * Paint object being moved. */ void Dragging_info::paint ( ) { if (!rect.w) // Not moved enough yet? return; if (save) // Save background. gwin->get_win()->get(save, rect.x, rect.y); if (obj) { if (obj->get_flag(Obj_flags::invisible)) obj->paint_invisible(paintx, painty); else obj->paint_shape(paintx, painty); } else if (gump) { gump->paint(); } } /* * Mouse was released, so drop object. * Return true iff the dropping mouseclick has been handled. * (by buttonpress, drag) */ bool Dragging_info::drop ( int x, int y, // Mouse pos. bool moved // has mouse moved from starting pos? ) { bool handled = moved; if (button) { button->unpush(); if (button->on_button(x, y)) // Clicked on button. button->activate(); handled = true; } else if (!obj) // Only dragging a gump? { if (!gump) return handled; if (!moved) // A click just raises it to the top. gumpman->remove_gump(gump); gumpman->add_gump(gump); } else if (!moved) // For now, if not moved, leave it. return handled; else if (!drop(x, y)) // Drop it. put_back(); // Wasn't (all) moved. obj = 0; // Clear so we don't paint them. gump = 0; gwin->paint(); return handled; } /* * Check weight. * * Output: false if too heavy, with mouse flashed. */ static bool Check_weight ( Game_window *gwin, Game_object *to_drop, Game_object *owner // Who the new owner will be. ) { if (cheat.in_hack_mover()) // hack-mover -> no weight checking return true; if (!owner) return true; owner = owner->get_outermost(); if (!owner->get_flag(Obj_flags::in_party)) return true; // Not a party member, so okay. int wt = owner->get_weight() + to_drop->get_weight(); if (wt/10 > owner->get_max_weight()) { Mouse::mouse->flash_shape(Mouse::tooheavy); return false; } return true; } /* * Put back object where it came from. */ void Dragging_info::put_back ( ) { if (gump) // Put back remaining/orig. piece. { // And don't check for volume! obj->set_chunk(old_pos.tx, old_pos.ty); // Restore saved vals. gump->add(obj, -2, -2, -2, -2, true); } else if (is_new) { obj->set_invalid(); // It's not in the world. obj->remove_this(); } else // Normal object. Put it back. obj->move(old_pos); obj = 0; // Just to be safe. is_new = false; } /* * Drop object on a gump. * * Output: False if not (all) of object was dropped. */ bool Dragging_info::drop_on_gump ( int x, int y, // Mouse position. Game_object *to_drop, // == obj if whole thing. Gump *on_gump // Gump to drop it on. ) { if (!Check_weight(gwin, to_drop, on_gump->get_cont_or_actor(x,y))) return false; if (on_gump != gump) // Not moving within same gump? possible_theft = true; // Add, and allow to combine. if (!on_gump->add(to_drop, x, y, paintx, painty, false, true)) { // Failed. if (to_drop != obj) { // Watch for partial drop. int nq = to_drop->get_quantity(); if (nq < quantity) obj->modify_quantity(quantity - nq); } Mouse::mouse->flash_shape(Mouse::wontfit); return false; } return true; } /* * Drop object onto the map. * * Output: False if not (all) of object was dropped. */ bool Dragging_info::drop_on_map ( int x, int y, // Mouse position. Game_object *to_drop // == obj if whole thing. ) { int max_lift = cheat.in_hack_mover() ? 13 : gwin->get_main_actor()->get_lift() + 5; int skip = gwin->get_render_skip_lift(); if (max_lift >= skip) // Don't drop where we cannot see. max_lift = skip - 1; // Drop where we last painted it. int posx = paintx, posy = painty; if (posx == -1000) // Unless we never painted. { posx = x; posy = y; } int lift; // Was it dropped on something? Game_object *found = gwin->find_object(x, y); bool dropped = false; // 1 when dropped. if (found && found != obj) { if (!Check_weight(gwin, to_drop, found)) return false; if (found->drop(to_drop)) dropped = possible_theft = true; // Try to place on 'found'. else if ((lift = found->get_lift() + found->get_info().get_3d_height()) <= max_lift) dropped = gwin->drop_at_lift(to_drop,posx, posy, lift); else { // Too high. Mouse::mouse->flash_shape(Mouse::redx); Audio::get_ptr()->play_sound_effect( Audio::game_sfx(76)); return false; } } // Find where to drop it. for (lift = old_lift; !dropped && lift <= max_lift; lift++) dropped = gwin->drop_at_lift(to_drop, posx, posy, lift); if (!dropped) { Mouse::mouse->flash_shape(Mouse::blocked); Audio::get_ptr()->play_sound_effect(Audio::game_sfx(76)); return false; } // Moved more than 2 tiles. if (!gump && to_drop->get_tile().distance(old_pos) > 2) possible_theft = true; return true; } /* * Drop at given position. * ++++++NOTE: Potential problems here with 'to_drop' being deleted by * call to add(). Probably add() should provide feedback if obj. * is combined with another. * * Output: False if put_back() should be called. */ bool Dragging_info::drop ( int x, int y // Mouse position. ) { // Get orig. loc. info. int oldcx = old_pos.tx/c_tiles_per_chunk, oldcy = old_pos.ty/c_tiles_per_chunk; Game_object *to_drop = obj; // If quantity, split it off. // Being liberal about taking stuff: int okay_to_move = to_drop->get_flag(Obj_flags::okay_to_take); int old_top = old_pos.tz + obj->get_info().get_3d_height(); // First see if it's a gump. Gump *on_gump = gumpman->find_gump(x, y); // Don't prompt if within same gump. if (quantity > 1 && (!on_gump || on_gump != gump)) quantity = gumpman->prompt_for_number(0, quantity, 1, quantity); if (quantity <= 0) return false; if (quantity < obj->get_quantity()) { // Need to drop a copy. to_drop = gmap->create_ireg_object( obj->get_shapenum(), obj->get_framenum()); to_drop->modify_quantity(quantity - 1); if (okay_to_move) // Make sure copy is okay to take. to_drop->set_flag(Obj_flags::okay_to_take); } // Drop it. if (!(on_gump ? drop_on_gump(x, y, to_drop, on_gump) : drop_on_map(x, y, to_drop))) return false; // Make a 'dropped' sound. Audio::get_ptr()->play_sound_effect(Audio::game_sfx(74)); if (!gump) // Do eggs where it came from. gmap->get_chunk(oldcx, oldcy)->activate_eggs(obj, old_pos.tx, old_pos.ty, old_pos.tz, old_pos.tx, old_pos.ty); // Special: BlackSword in SI. else if (readied_index >= 0 && obj->get_shapenum() == 806) // Do 'unreadied' usecode. gump->get_cont_or_actor(x,y)->call_readied_usecode( readied_index, obj, Usecode_machine::unreadied); if (on_gump) // Do 'readied' usecode. { Container_game_object *owner = on_gump->get_cont_or_actor(x,y); int index = owner ? owner->find_readied(obj) : -1; if (index >= 0) owner->call_readied_usecode(index, obj, Usecode_machine::readied); } // On a barge? Barge_object *barge = gwin->get_moving_barge(); if (barge) barge->set_to_gather(); // Refigure what's on barge. // Check for theft. if (!okay_to_move && !cheat.in_hack_mover() && possible_theft && !gwin->is_in_dungeon()) gwin->theft(); if (to_drop == obj) // Whole thing? { // Watch for stuff on top of it. if (old_foot.w > 0) Map_chunk::gravity(old_foot, old_top); return true; // All done. } // Subtract quantity moved. obj->modify_quantity(-quantity); return false; // Put back the rest. } /* * Begin a possible drag when the mouse button is depressed. Also detect * if the 'close' checkmark on a gump is being depressed. * * Output: true iff object selected for dragging */ bool Game_window::start_dragging ( int x, int y // Position in window. ) { delete dragging; dragging = new Dragging_info(x, y); if (dragging->okay) return (true); // Success, so far. delete dragging; dragging = 0; return false; } /* * Mouse moved while dragging. */ bool Game_window::drag ( int x, int y // Mouse position in window. ) { return dragging ? dragging->moved(x, y) : false; } /* * Mouse was released, so drop object. * Return true iff the dropping mouseclick has been handled. * (by buttonpress, drag) * Output: MUST set dragging = 0. */ bool Game_window::drop_dragged ( int x, int y, // Mouse pos. bool moved // has mouse moved from starting pos? ) { if (!dragging) return false; bool handled = dragging->drop(x, y, moved); delete dragging; dragging = 0; return handled; } /* * Try to drop at a given lift. Note: None of the drag state variables * may be used here, as it's also called from the outside. * * Output: true if successful. */ bool Game_window::drop_at_lift ( Game_object *to_drop, int x, int y, // Pixel coord. in window. int at_lift ) { x += at_lift*4 - 1; // Take lift into account, round. y += at_lift*4 - 1; int tx = (scrolltx + x/c_tilesize)%c_num_tiles; int ty = (scrollty + y/c_tilesize)%c_num_tiles; int cx = tx/c_tiles_per_chunk; int cy = ty/c_tiles_per_chunk; Map_chunk *chunk = map->get_chunk(cx, cy); int lift; // Can we put it here? Shape_info& info = to_drop->get_info(); int xtiles = info.get_3d_xtiles(), ytiles = info.get_3d_ytiles(); int max_drop, move_flags; if (cheat.in_hack_mover()) { max_drop = at_lift - cheat.get_edit_lift(); // max_drop = max_drop < 0 ? 0 : max_drop; if (max_drop < 0) // Below lift we're editing? return false; move_flags = MOVE_WALK|MOVE_MAPEDIT; } else { // Allow drop of 5; max_drop = 5; move_flags = MOVE_WALK; } if (!Map_chunk::is_blocked(info.get_3d_height(), at_lift, tx - xtiles + 1, ty - ytiles + 1, xtiles, ytiles, lift, move_flags, max_drop) && (cheat.in_hack_mover() || // Check for path to location. Fast_pathfinder_client::is_grabable( main_actor->get_tile(), Tile_coord(tx, ty, lift)))) { to_drop->set_invalid(); to_drop->move(tx, ty, lift); #ifdef DEBUG cout << "Dropping object at (" << tx << ", " << ty << ", " << lift << ")"<activate_eggs(to_drop, tx, ty, lift, tx, ty); if (to_drop == main_actor) { center_view(to_drop->get_tile()); paint(); } return (true); } return (false); } exult-1.2/actorio.cc0000644000175000001440000004425010026506273010147 /* * actorio.cc - I/O for the Actor class. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "gamewin.h" #include "gamemap.h" #include "game.h" #include "monsters.h" #include "utils.h" #include "egg.h" #include "chunks.h" #include "schedule.h" #include "objiter.h" #include "databuf.h" #include "npctime.h" using std::ios; using std::cout; using std::endl; using std::istream; using std::ostream; /* * Read in actor from a given file. */ void Actor::read ( DataSource* nfile, // 'npc.dat', generally. int num, // NPC #, or -1. bool has_usecode, // 1 if a 'type1' NPC. bool& fix_unused // Old savegame, so 'unused' isn't // valid. Possibly set here. //June9,02: +++++Fix_unused should go away in a few months. ) { npc_num = num; // This is used to get around parts of the files that we don't know // what the uses are. 'fix_first' is used fix issues in the originals // files that cause problems for the extra info we save. bool fix_first = Game::is_new_game(); init(); // Clear rest of stuff. unsigned locx = nfile->read1(); // Get chunk/tile coords. unsigned locy = nfile->read1(); // Read & set shape #, frame #. unsigned short shnum = nfile->read2(); if (num == 0 && Game::get_game_type() != BLACK_GATE && (shnum & 0x3ff) < 12) set_shape((shnum & 0x3ff) | 0x400); else set_shape(shnum & 0x3ff); set_frame(shnum >> 10); int iflag1 = nfile->read2(); // Inventory flag. // We're going to use these bits. // iflag1:0 == has_contents. // iflag1:1 == sched. usecode follows, // possibly empty. // iflag1:2 == usecode # assigned by // ES, so always use it. bool read_sched_usecode = !fix_first && (iflag1&2); if (!fix_first && (iflag1&4)) usecode_assigned = true; int schunk = nfile->read1(); // Superchunk #. nfile->read1(); // Skip next byte. int usefun = nfile->read2(); // Get usecode function #. set_lift(usefun >> 12); // Lift is high 4 bits. usecode = usefun & 0xfff; // if (!npc_num) // Avatar is always first. // usecode = 0x400; // Need this for BG. (Not sure if SI.) if (npc_num >= 0 && npc_num < 256) usecode = 0x400 + npc_num; // Watch for new NPC's added. else if ((!has_usecode && !usecode_assigned && usecode != 0x400 + npc_num) || usecode == 0xfff) usecode = -1; // Let's try this. // Guessing: !! (Want to get signed.) int health_val = static_cast(static_cast(nfile->read1())); set_property(static_cast(Actor::health), health_val); nfile->skip(3); // Skip 3 bytes. int iflag2 = nfile->read2(); // The 'used-in-game' flag. if (iflag2 == 0 && num >= 0 && !fix_unused) { if (num == 0) // Old (bad) savegame? fix_unused = true; else unused = true; #ifdef DEBUG cout << "NPC #" << num << " is unused" << endl; #endif } bool has_contents = fix_first ? (iflag1 && !unused) : (iflag1&1); // Read first set of flags const int rflags = nfile->read2(); if ((rflags >> 0x7) & 1) set_flag (Obj_flags::asleep); if ((rflags >> 0x8) & 1) set_flag (Obj_flags::charmed); if ((rflags >> 0x9) & 1) set_flag (Obj_flags::cursed); if ((rflags >> 0xB) & 1) set_flag (Obj_flags::in_party); if ((rflags >> 0xC) & 1) set_flag (Obj_flags::paralyzed); if ((rflags >> 0xD) & 1) set_flag (Obj_flags::poisoned); if ((rflags >> 0xE) & 1) set_flag (Obj_flags::protection); if (!fix_first && ((rflags >> 0xF) & 1)) set_flag (Obj_flags::dead); // Guess if (((rflags >> 0xA) & 1)) set_flag (Obj_flags::on_moving_barge); alignment = (rflags >> 3)&3; // Unknown, using for is_temporary (only when not fix_first) if ((rflags >> 0x6) & 1 && !fix_first) set_flag (Obj_flags::is_temporary); /* Not used by exult Unknown in U7tech if ((rflags >> 0x5) & 1) set_flag (Obj_flags::unknown); */ // Get char. atts. // In BG - Strength (0-5), skin colour(6-7) // In SI - Strength (0-4), skin colour(5-6), freeze (7) int strength_val = nfile->read1(); if (Game::get_game_type() == BLACK_GATE) { set_property(static_cast(Actor::strength), strength_val & 0x3F); if (num == 0) { if (Game::get_avskin() >= 0 && Game::get_avskin() <= 3) set_skin_color (Game::get_avskin()); else set_skin_color (((strength_val >> 6)-1) & 0x3); } else set_skin_color (3); } else { set_property(static_cast(Actor::strength), strength_val & 0x1F); if (num == 0) { if (Game::get_avskin() >= 0 && Game::get_avskin() <= 2) set_skin_color (Game::get_avskin()); else set_skin_color ((strength_val >> 5) & 0x3); } else set_skin_color (-1); if ((strength_val << 7) & 1) set_flag (Obj_flags::freeze); } if (is_dying() && // Now we know health, strength. npc_num > 0) // DON'T do this for Avatar! set_flag(Obj_flags::dead); // Fixes older savegames. // Dexterity set_property(static_cast(Actor::dexterity), nfile->read1()); // Intelligence (0-4), read(5), Tournament (6), polymorph (7) int intel_val = nfile->read1(); set_property(static_cast(Actor::intelligence), intel_val & 0x1F); if ((intel_val >> 5) & 1) set_flag (Obj_flags::read); // Tournament. if ((intel_val >> 6) & 1) set_flag (Obj_flags::si_tournament); if ((intel_val >> 7) & 1) set_flag (Obj_flags::polymorph); // Combat skill (0-6), Petra (7) int combat_val = nfile->read1(); set_property(static_cast(Actor::combat), combat_val & 0x7F); if ((combat_val << 7) & 1) set_flag (Obj_flags::petra); schedule_type = nfile->read1(); int amode = nfile->read1(); // Default attack mode // Just stealing 2 spare bits: combat_protected = (amode&(1<<4)) != 0; user_set_attack = (amode&(1<<5)) != 0; attack_mode = (Attack_mode) (amode&0xf); nfile->skip(3); //Unknown // If NPC 0: MaxMagic (0-4), TempHigh (5-7) and Mana(0-4), TempLow (5-7) // Else: ID# (0-4) ???, TempHigh (5-7) and Mat (0), No Spell Casting (1), Zombie (3), TempLow (5-7) int magic_val = nfile->read1(); int mana_val = nfile->read1(); if (num == 0) { int magic = magic_val&0x1f, mana = mana_val&0x1f; set_property(static_cast(Actor::magic), magic); // Need to make sure that mana is less than magic if (mana < magic) set_property(static_cast(Actor::mana), mana); else set_property(static_cast(Actor::mana), magic); set_flag (Obj_flags::met); } else { set_ident(magic_val&0x1F); if ((mana_val >> 0) & 1) set_flag (Obj_flags::met); if ((mana_val >> 1) & 1) set_flag(Obj_flags::no_spell_casting); if ((mana_val >> 2) & 1) set_flag (Obj_flags::si_zombie); } set_temperature (((magic_val >> 2) & 0x38) + ((mana_val >> 5) & 7)); // nfile->skip(1 ); // Index2???? (refer to U7tech.txt) face_num = nfile->read1(); if (!face_num && npc_num > 0) // Fix older savegames. face_num = npc_num; nfile->skip(2 ); // Unknown set_property(static_cast(Actor::exp), nfile->read4()); set_property(static_cast(Actor::training), nfile->read1()); nfile->skip (2); // Primary Attacker nfile->skip (2); // Secondary Attacker oppressor = nfile->read2(); // Oppressor NPC id. nfile->skip (4); //I-Vr ??? (refer to U7tech.txt) schedule_loc.tx = nfile->read2(); //S-Vr Where npc is supposed to schedule_loc.ty = nfile->read2(); //be for schedule) // Type flags 2 int tflags = nfile->read2(); // First time round, all the flags are garbage if (fix_first) set_type_flags (1 << Actor::tf_walk); else set_type_flags (tflags); if (num == 0 && Game::get_avsex() == 0) { clear_type_flag (Actor::tf_sex); } else if (num == 0 && Game::get_avsex() == 1) { set_type_flag (Actor::tf_sex); } nfile->skip (5); // Unknown next_schedule = nfile->read1(); // Acty ????? what is this?? nfile->skip (1); // SN ????? (refer to U7tech.txt) nfile->skip (2); // V1 ????? (refer to U7tech.txt) nfile->skip (2); // V2 ????? (refer to U7tech.txt) // 16 Bit Shape Numbers, allows for shapes > 1023 shnum = nfile->read2(); if (!fix_first && shnum) { if (GAME_BG && !sman->can_use_multiracial() && shnum > 1024 && npc_num == 0) set_actor_shape(); else set_shape(shnum); // 16 Bit Shape Number shnum = (sint16) nfile->read2(); // 16 Bit Polymorph Shape Number if (get_flag (Obj_flags::polymorph)) { // Try to fix messed-up flag. if (shnum != get_shapenum()) set_polymorph(shnum); else clear_flag(Obj_flags::polymorph); } } else { nfile->skip (2); set_polymorph_default(); } // More Exult stuff if (!fix_first) { uint32 f; // Flags f = nfile->read4(); flags |= f; if (get_flag(Obj_flags::invisible)) /* Force timer. */ need_timers()->start_invisibility(); // SIFlags f = nfile->read2(); siflags |= f; // Flags2 But don't set polymorph. bool polym = get_flag(Obj_flags::polymorph)!= false; f = nfile->read4(); flags2 |= f; if (!polym && get_flag(Obj_flags::polymorph)) clear_flag(Obj_flags::polymorph); } else { // Flags nfile->skip (4); // SIFlags nfile->skip (2); // Flags2 nfile->skip (4); } // Skip 15 nfile->skip (15); // Get (signed) food level. int food_read = static_cast(static_cast(nfile->read1())); if (fix_first) food_read = 18; set_property(static_cast(Actor::food_level), food_read); // Skip 7 nfile->skip(7); char namebuf[17]; nfile->read(namebuf, 16); for (int i = 0; i < 16; i++) if (namebuf[i] == 0) i = 16; else if (namebuf[i] < ' ' || namebuf[i] >= 127) { namebuf[0] = 0; break; } namebuf[16] = 0; // Be sure it's 0-delimited. // cout << "Actor " << namebuf << " has alignment " << align << endl; if (num == 0 && Game::get_avname()) { name = Game::get_avname(); } else name = namebuf; // Store copy of it. // Get abs. chunk. coords. of schunk. int scy = 16*(schunk/12); int scx = 16*(schunk%12); if (has_contents) // Inventory? Read. gwin->get_map()->read_ireg_objects(nfile, scx, scy, this); if (read_sched_usecode) // Read in scheduled usecode. gwin->get_map()->read_special_ireg(nfile, this); int cx = locx >> 4; // Get chunk indices within schunk. int cy = locy >> 4; // Get tile #'s. int tilex = locx & 0xf; int tiley = locy & 0xf; set_shape_pos(tilex, tiley); Map_chunk *olist = gmap->get_chunk_safely(scx + cx, scy + cy); set_invalid(); // Not in world yet. if (olist && !is_dead() && // Valid & alive? Put into chunk list. !unused) { move((scx + cx)*c_tiles_per_chunk + tilex, (scy + cy)*c_tiles_per_chunk + tiley, get_lift()); // olist->add(this); // switched_chunks(0, olist); // Put in chunk's NPC list. } // Only do ready best weapon if we are in BG, this is the first time // and we are the Avatar or Iolo if (Game::get_game_type() == BLACK_GATE && Game::get_avname() && (num == 0 || num == 1)) ready_best_weapon(); #if defined(DEBUG) && 0 cout << get_npc_num() << " Creating "; if (name.empty()) cout << get_name(); else cout << name; cout << ", shape = " << get_shapenum() << ", frame = " << get_framenum() << ", usecode = " << usefun << endl; cout << "Chunk coords are (" << scx + cx << ", " << scy + cy << "), lift is " << get_lift() << endl; cout << "Type Flags: "; if (get_type_flag(tf_fly)) cout << "fly "; if (get_type_flag(tf_swim)) cout << "swim "; if (get_type_flag(tf_walk)) cout << "walk "; if (get_type_flag(tf_ethereal)) cout << "ethereal "; if (get_type_flag(tf_in_party)) cout << "in party "; cout << endl; #endif } /* * Write out to given file. */ void Actor::write ( DataSource* nfile // Generally 'npc.dat'. ) { int i; unsigned char buf4[4]; // Write coords., shape, frame. int old_shape = get_shapenum(); // Backup shape because we might change it set_shape( get_shape_real() ); // Change the shape out non polymorph one Game_object::write_common_ireg(buf4); nfile->write(reinterpret_cast(buf4), sizeof(buf4)); set_shape( old_shape ); // Revert the shape to what it was // Inventory flag. // Bit0 = has_contents (our use). // Bit1 = our savegame, with sched. // usecode script following this. // iflag1:2 == usecode # assigned by // ES, so always use it. int iflag1 = objects.is_empty() ? 0 : 1; iflag1 |= 2; // We're always doing write_scheduled() if (usecode_assigned) // # assigned by EStudio? iflag1 |= 4; // Set bit 2. nfile->write2(iflag1); // Superchunk #. nfile->write1((get_cy()/16)*12 + get_cx()/16); nfile->write1(0); // Unknown. // Usecode. int usefun = get_usecode() & 0xfff; // Lift is in high 4 bits. usefun |= ((get_lift()&15) << 12); nfile->write2(usefun); nfile->write1(get_property(Actor::health)); nfile->write1(0); // Unknown 3 bytes. nfile->write2(0); nfile->write2(unused ? 0 : 1); // Write 0 if unused. //Write first set of flags int iout = 0; if (get_flag (Obj_flags::asleep)) iout |= 1 << 0x7; if (get_flag (Obj_flags::charmed)) iout |= 1 << 0x8; if (get_flag (Obj_flags::cursed)) iout |= 1 << 0x9; if (get_flag (Obj_flags::in_party)) iout |= 1 << 0xB; if (get_flag (Obj_flags::paralyzed)) iout |= 1 << 0xC; if (get_flag (Obj_flags::poisoned)) iout |= 1 << 0xD; if (get_flag (Obj_flags::protection)) iout |= 1 << 0xE; // Guess if (get_flag (Obj_flags::on_moving_barge)) iout |= 1 << 0xA; // Alignment is bits 3-4. // Unknownm using for is_temp if (get_flag (Obj_flags::is_temporary)) iout |= 1 << 0x6; iout |= ((alignment&3) << 3); nfile->write2(iout); // Write char. attributes. iout = get_property(Actor::strength); if (Game::get_game_type() != BLACK_GATE && npc_num == 0) iout |= (get_skin_color () & 3) << 5; else if (npc_num == 0) iout |= ((get_skin_color()+1) & 3) << 6; if (get_flag (Obj_flags::freeze)) iout |= 1 << 7; nfile->write1(iout); nfile->write1(get_property(Actor::dexterity)); iout = get_property(Actor::intelligence); if (get_flag (Obj_flags::read)) iout |= 1 << 5; // Tournament if (get_flag (Obj_flags::si_tournament)) iout |= 1 << 6; if (get_flag (Obj_flags::polymorph)) iout |= 1 << 7; nfile->write1(iout); iout = get_property(Actor::combat); if (get_flag (Obj_flags::petra)) iout |= 1 << 7; nfile->write1(iout); nfile->write1(get_schedule_type()); unsigned char amode = attack_mode | (combat_protected ? (1<<4) : 0) | (user_set_attack ? (1<<5) : 0); nfile->write1(amode); nfile->write1(0); // Skip 3. nfile->write2(0); // Magic int mana_val = 0; int magic_val = 0; if (get_npc_num() == 0) { mana_val = get_property(static_cast(Actor::mana)); magic_val = get_property(static_cast(Actor::magic)); } else { magic_val = get_ident() & 0x1F; if (get_flag (Obj_flags::met)) mana_val |= 1; if (get_flag (Obj_flags::no_spell_casting)) mana_val |= 1 << 1; if (get_flag (Obj_flags::si_zombie)) mana_val |= 1 << 2; } // Tempertures mana_val |= (get_temperature () & 0x1F) << 5; magic_val |= (get_temperature () & 0x38) << 2; nfile->write1 (magic_val); nfile->write1 (mana_val); nfile->write1((face_num >= 0 && face_num <= 255) ? face_num : 0); nfile->write2(0); // Skip 2 nfile->write4(get_property(Actor::exp)); nfile->write1(get_property(Actor::training)); // 0x40 unknown. nfile->write2(0); // Skip 2*2 nfile->write2(0); nfile->write2(oppressor); // Oppressor. nfile->write4(0); // Skip 2*2 nfile->write2(schedule_loc.tx); //S-Vr Where npc is supposed to nfile->write2(schedule_loc.ty); //be for schedule) //nfile->write4(0); nfile->write2(get_type_flags()); // Typeflags nfile->write4(0); // Skip 5 nfile->write1(0); nfile->write1(next_schedule); // Acty ????? what is this?? nfile->write1(0); // Skip 1 nfile->write2(0); // Skip 2 nfile->write2(0); // Skip 2 // 16 Bit Shapes if (get_flag (Obj_flags::polymorph)) { nfile->write2(shape_save); // 16 Bit Shape Num nfile->write2(get_shapenum()); // 16 Bit Polymorph Shape } else { nfile->write2(get_shapenum()); // 16 Bit Shape Num nfile->write2(0); // 16 Bit Polymorph Shape } // Flags nfile->write4(flags); // SIFlags nfile->write2(siflags); // flags2 nfile->write4(flags2); // Skip 15 for (i = 0; i < 15; i++) nfile->write1(0); // Food nfile->write1(get_property (Actor::food_level)); // Skip 7 for (i = 0; i < 7; i++) nfile->write1(0); char namebuf[17]; // Write 16-byte name. std::memset(namebuf, 0, 16); if (name.empty()) { std::string namestr = Game_object::get_name(); std::strncpy(namebuf, namestr.c_str(), 16); } else std::strncpy(namebuf, name.c_str(), 16); nfile->write(namebuf, 16); write_contents(nfile); // Write what he holds. namebuf[16] = 0; // Write scheduled usecode. Game_map::write_scheduled(nfile, this, true); } /* * Write out to given file. */ void Monster_actor::write ( DataSource* nfile // Generally 'npc.dat'. ) { if (Actor::is_dead()) // Not alive? return; Actor::write(nfile); // Now write. } /* * Write Inventory */ /* * Write contents (if there is any). */ void Actor::write_contents ( DataSource* out ) { if (!objects.is_empty()) // Now write out what's inside. { const int num_spots = static_cast(sizeof(spots)/sizeof(spots[0])); sint8 i; for (i = 0; i < num_spots; ++i) { // Spot Increment if (spots[i]) { // Write 2 byte index id out->write1(0x02); out->write2(static_cast(i)); spots[i]->write_ireg(out); } } Game_object *obj; Object_iterator next(objects); while ((obj = next.get_next()) != 0) { for (i = 0; i < num_spots; ++i) if (spots[i] == obj) break; if (i == num_spots) { // Write 2 byte index id (-1 = no slot) i = -1; out->write1(0x02); out->write2(static_cast(i)); obj->write_ireg(out); } } out->write1(0x01); // A 01 terminates the list. } } exult-1.2/configure0000755000175000001440000160173610061527027010117 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" # Sed expression to map a string onto a valid variable name. as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="exult.cc" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION EXEEXT OBJEXT ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh INSTALL_STRIP_PROGRAM AWK SET_MAKE AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH DEPDIR MACOSX_TRUE MACOSX_FALSE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC am__include am__quote CCDEPMODE CPP LEX LEXLIB LEX_OUTPUT_ROOT YACC LEXYACC_TRUE LEXYACC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE LN_S ECHO RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP EGREP LIBTOOL LIBTOOL_DEPS HAVE_PNG_TRUE HAVE_PNG_FALSE CXXCPP LIBOBJS HAVE_SNPRINTF_TRUE HAVE_SNPRINTF_FALSE x_libraries SDL_CONFIG SDL_CFLAGS SDL_LIBS HAVE_TIMIDITY_BIN BUILD_TOOLS_TRUE BUILD_TOOLS_FALSE BUILD_COMPILER_TRUE BUILD_COMPILER_FALSE DATA_FILES_TRUE DATA_FILES_FALSE GLADE_INCLUDES GLADE_LIBS FT2CONFIG FREETYPE2_LIBS FREETYPE2_INCLUDES BUILD_STUDIO_TRUE BUILD_STUDIO_FALSE GIMP_PLUGIN_TRUE GIMP_PLUGIN_FALSE GIMPTOOL GIMP_PLUGIN_PREFIX GIMP_INCLUDES GIMP_LIBS WINDOWING_SYSTEM KMID_INCLUDES KMID_LIBS EXE_TARGET EXULT_DATADIR SYSLIBS ICON_FILE DEBUG_FLAGS ZLIB_LIBS OPENGL_LIBS WARNINGS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX ac_cv_env_CXX_set=${CXX+set} ac_cv_env_CXX_value=$CXX ac_env_CXXFLAGS_set=${CXXFLAGS+set} ac_env_CXXFLAGS_value=$CXXFLAGS ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} ac_cv_env_CXXFLAGS_value=$CXXFLAGS ac_env_CXXCPP_set=${CXXCPP+set} ac_env_CXXCPP_value=$CXXCPP ac_cv_env_CXXCPP_set=${CXXCPP+set} ac_cv_env_CXXCPP_value=$CXXCPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors --enable-shared=PKGS build shared libraries default=no --enable-static=PKGS build static libraries default=yes --enable-fast-install=PKGS optimize for fast installation default=yes --disable-libtool-lock avoid locking (might break parallel builds) --disable-sdltest Do not try to compile and run a test SDL program --enable-timidity Use timidity default yes --enable-zip-support Enable zipped savegame support default yes --enable-opengl Enable OpenGL rendering support EXPERIMENTAL --enable-exult-studio-support Enable ExultStudio support default yes --enable-alternate-allocator Use alternate memory allocator default no --enable-storage-initialisation Clear storage when allocated default no --enable-storage-poisoning Poison storage when allocated default no --enable-debug Enable debug messages default no --enable-optimized-debug Enable optimized debug build default no --enable-sdl-parachute Use SDL parachute default yes --enable-warnings Enable all warnings default no --enable-awful-warnings Enable warnings for violations of Scott Meyers' Effective C++ style guidelines default no --enable-paranoid-warnings Enable paranoid warnings default no --enable-long-long-warnings Enable long long warnings- needed for Compaq's cxx with GNU ld default no --enable-std-namespace Honour the std namespace. default no --enable-repo Repo type template instantiation. default no --enable-external-templates external template instantiation. default no --enable-mmx Use MMX optimisations default no --enable-3dnow Use 3DNOW optimisations default no --disable-tools Only build the main program --enable-compiler Build the usecode compiler default yes --enable-data Create the data files default yes --enable-exult-studio Build Exult Studio default no --enable-gimp-plugin Build the GIMP plugin default no Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-cxx=COMMAND Explicitly specify the C++ compiler to use --with-gnu-ld assume the C compiler uses GNU ld default=no --with-pic try to use only PIC/non-PIC objects default=use both --with-sdl-prefix=PFX Prefix where SDL is installed (optional) --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.57. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core core.* *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # --------------------------------------------------------------------- # System/version info # --------------------------------------------------------------------- PACKAGE=exult VER_MAJOR=1 VER_MINOR=2 VER_EXTRA= VERSION=$VER_MAJOR.$VER_MINOR$VER_EXTRA # check host/target systems # (build = system we're building on, host = system we're building for, # target = system the program we're building will build for) ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking target system type" >&5 echo $ECHO_N "checking target system type... $ECHO_C" >&6 if test "${ac_cv_target+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_target_alias=$target_alias test "x$ac_cv_target_alias" = "x" && ac_cv_target_alias=$ac_cv_host_alias ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_target" >&5 echo "${ECHO_T}$ac_cv_target" >&6 target=$ac_cv_target target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= am_backtick='`' { echo "$as_me:$LINENO: WARNING: ${am_backtick}missing' script is too old or missing" >&5 echo "$as_me: WARNING: ${am_backtick}missing' script is too old or missing" >&2;} fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi rm -f .deps 2>/dev/null mkdir .deps 2>/dev/null if test -d .deps; then DEPDIR=.deps else # MS-DOS does not allow filenames that begin with a dot. DEPDIR=_deps fi rmdir .deps 2>/dev/null # test to see if srcdir already configured if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # Define the identity of the package. PACKAGE=$PACKAGE VERSION=$VERSION # Autoconf 2.50 wants to disallow AM_ names. We explicitly allow # the ones we care about. # Autoconf 2.50 always computes EXEEXT. However we need to be # compatible with 2.13, for now. So we always define EXEEXT, but we # don't compute it. # Similar for OBJEXT -- only we only use OBJEXT if the user actually # requests that it be used. This is a bit dumb. : ${OBJEXT=o} # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} AMTAR=${AMTAR-"${am_missing_run}tar"} install_sh=${install_sh-"$am_aux_dir/install-sh"} INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define VER_MAJOR "$VER_MAJOR" _ACEOF cat >>confdefs.h <<_ACEOF #define VER_MINOR "$VER_MINOR" _ACEOF cat >>confdefs.h <<_ACEOF #define VER_EXTRA "$VER_EXTRA" _ACEOF ac_config_headers="$ac_config_headers config.h" # --------------------------------------------------------------------- # Host system settings # --------------------------------------------------------------------- SYSLIBS="" ICON_FILE="" EXE_TARGET="exult$EXEEXT" EXULT_DATADIR="$datadir/exult" ARCH="" # determine windowing system from 'host' echo "$as_me:$LINENO: checking \"windowing system\"" >&5 echo $ECHO_N "checking \"windowing system\"... $ECHO_C" >&6 case "$host_os" in linux*) WINDOWING_SYSTEM="-DXWIN" if test "$host_vendor" = "embeddix"; then echo "$as_me:$LINENO: result: Qtopia (Sharp Zaurus)" >&5 echo "${ECHO_T}Qtopia (Sharp Zaurus)" >&6 CXXFLAGS="$CXXFLAGS -fsigned-char -DDISABLE_X11 -DQWS -D__zaurus__ -DUSE_FMOPL_MIDI" enable_kmid="no" enable_timidity="no" enable_exult_studio_support="no" enable_exult_studio="no" enable_gimp_plugin="no" enable_debug="no" enable_data="yes" else echo "$as_me:$LINENO: result: X11 (GNU/Linux)" >&5 echo "${ECHO_T}X11 (GNU/Linux)" >&6 fi ;; beos*) WINDOWING_SYSTEM="-DBEOS" echo "$as_me:$LINENO: result: BeOS" >&5 echo "${ECHO_T}BeOS" >&6 SYSLIBS="-lbe -lmidi" enable_kmid="no" enable_timidity="no" ;; mingw32* ) WINDOWING_SYSTEM="-DWIN32" echo "$as_me:$LINENO: result: Win32 (mingw32)" >&5 echo "${ECHO_T}Win32 (mingw32)" >&6 SYSLIBS="-lwinmm -lstdc++" ICON_FILE="win32/exultico.o" enable_kmid="no" enable_timidity="no" ;; cygwin* ) WINDOWING_SYSTEM="-DWIN32" cat >>confdefs.h <<\_ACEOF #define CYGWIN 1 _ACEOF echo "$as_me:$LINENO: result: Win32 (cygwin)" >&5 echo "${ECHO_T}Win32 (cygwin)" >&6 CXXFLAGS="$CXXFLAGS -mno-cygwin" SYSLIBS="-lwinmm" ICON_FILE="win32/exultico.o" enable_kmid="no" enable_timidity="no" ;; openbsd* ) WINDOWING_SYSTEM="-DXWIN" cat >>confdefs.h <<\_ACEOF #define OPENBSD 1 _ACEOF echo "$as_me:$LINENO: result: X11 (OpenBSD)" >&5 echo "${ECHO_T}X11 (OpenBSD)" >&6 SYSLIBS="-L/usr/X11R6/lib -lX11 -lXext -lXxf86vm -lXxf86dga" ;; freebsd* ) WINDOWING_SYSTEM="-DXWIN" echo "$as_me:$LINENO: result: X11 (FreeBSD)" >&5 echo "${ECHO_T}X11 (FreeBSD)" >&6 CXXFLAGS="$CXXFLAGS -I/usr/X11R6/include" ;; solaris* ) WINDOWING_SYSTEM="-DXWIN" echo "$as_me:$LINENO: result: X11 (Solaris)" >&5 echo "${ECHO_T}X11 (Solaris)" >&6 SYSLIBS="-lsocket -lX11" ;; darwin*) WINDOWING_SYSTEM="-DMACOSX" cat >>confdefs.h <<\_ACEOF #define MACOSX 1 _ACEOF echo "$as_me:$LINENO: result: Mac OS X" >&5 echo "${ECHO_T}Mac OS X" >&6 SYSLIBS="-framework QuickTime" CXXFLAGS="$CXXFLAGS" EXULT_DATADIR="data" ARCH=macosx ;; *) WINDOWING_SYSTEM="-DXWIN" echo "$as_me:$LINENO: result: not sure... guessing X11" >&5 echo "${ECHO_T}not sure... guessing X11" >&6 ;; esac if test x$ARCH = xmacosx; then MACOSX_TRUE= MACOSX_FALSE='#' else MACOSX_TRUE='#' MACOSX_FALSE= fi # --------------------------------------------------------------------- # Compilers and other tools # --------------------------------------------------------------------- for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output" >&5 echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ ''\ '#include ' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands default-1" am_make=${MAKE-make} cat > confinc << 'END' doit: @echo done END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include='#' am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote='"' _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_CC_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE="depmode=$am_cv_CC_dependencies_compiler_type" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_LEX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LEX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then echo "$as_me:$LINENO: result: $LEX" >&5 echo "${ECHO_T}$LEX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$LEX" && break done test -n "$LEX" || LEX="${am_missing_run}flex" for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_LEX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LEX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then echo "$as_me:$LINENO: result: $LEX" >&5 echo "${ECHO_T}$LEX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test -z "$LEXLIB" then echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5 echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6 if test "${ac_cv_lib_fl_yywrap+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lfl $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char yywrap (); int main () { yywrap (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_fl_yywrap=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_fl_yywrap=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5 echo "${ECHO_T}$ac_cv_lib_fl_yywrap" >&6 if test $ac_cv_lib_fl_yywrap = yes; then LEXLIB="-lfl" else echo "$as_me:$LINENO: checking for yywrap in -ll" >&5 echo $ECHO_N "checking for yywrap in -ll... $ECHO_C" >&6 if test "${ac_cv_lib_l_yywrap+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ll $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char yywrap (); int main () { yywrap (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_l_yywrap=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_l_yywrap=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5 echo "${ECHO_T}$ac_cv_lib_l_yywrap" >&6 if test $ac_cv_lib_l_yywrap = yes; then LEXLIB="-ll" fi fi fi if test "x$LEX" != "x:"; then echo "$as_me:$LINENO: checking lex output file root" >&5 echo $ECHO_N "checking lex output file root... $ECHO_C" >&6 if test "${ac_cv_prog_lex_root+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # The minimal lex program is just a single line: %%. But some broken lexes # (Solaris, I think it was) want two %% lines, so accommodate them. cat >conftest.l <<_ACEOF %% %% _ACEOF { (eval echo "$as_me:$LINENO: \"$LEX conftest.l\"") >&5 (eval $LEX conftest.l) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5 echo "$as_me: error: cannot find output from $LEX; giving up" >&2;} { (exit 1); exit 1; }; } fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5 echo "${ECHO_T}$ac_cv_prog_lex_root" >&6 rm -f conftest.l LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5 echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6 if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c ac_save_LIBS=$LIBS LIBS="$LIBS $LEXLIB" cat >conftest.$ac_ext <<_ACEOF `cat $LEX_OUTPUT_ROOT.c` _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_lex_yytext_pointer=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS rm -f "${LEX_OUTPUT_ROOT}.c" fi echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5 echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6 if test $ac_cv_prog_lex_yytext_pointer = yes; then cat >>confdefs.h <<\_ACEOF #define YYTEXT_POINTER 1 _ACEOF fi fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_YACC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then echo "$as_me:$LINENO: result: $YACC" >&5 echo "${ECHO_T}$YACC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" if test -n "$YACC"; then LEXYACC_TRUE= LEXYACC_FALSE='#' else LEXYACC_TRUE='#' LEXYACC_FALSE= fi # Check whether --with-cxx or --without-cxx was given. if test "${with_cxx+set}" = set; then withval="$with_cxx" CXX="" fi; if test -z "$CXX"; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CXX" && break done test -n "$ac_ct_CXX" || ac_ct_CXX="g++" CXX=$ac_ct_CXX fi # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-g" echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi for ac_declaration in \ ''\ '#include ' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_CXX_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 CXXDEPMODE="depmode=$am_cv_CXX_dependencies_compiler_type" else ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $CCC $CXX do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in $CCC $CXX do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CXX" && break done test -n "$ac_ct_CXX" || ac_ct_CXX="g++" CXX=$ac_ct_CXX fi # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-g" echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi for ac_declaration in \ ''\ '#include ' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_CXX_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 CXXDEPMODE="depmode=$am_cv_CXX_dependencies_compiler_type" fi # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$ac_save_ifs" ;; esac else enable_shared=no fi; # Check whether --enable-static or --disable-static was given. if test "${enable_static+set}" = set; then enableval="$enable_static" p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$ac_save_ifs" ;; esac else enable_static=yes fi; # Check whether --enable-fast-install or --disable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval="$enable_fast_install" p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$ac_save_ifs" ;; esac else enable_fast_install=yes fi; # Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by GCC" >&5 echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then echo "$as_me:$LINENO: result: $LD" >&5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then lt_cv_prog_gnu_ld=yes else lt_cv_prog_gnu_ld=no fi fi echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 with_gnu_ld=$lt_cv_prog_gnu_ld echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 if test "${lt_cv_ld_reload_flag+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_ld_reload_flag='-r' fi echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 reload_flag=$lt_cv_ld_reload_flag test -n "$reload_flag" && reload_flag=" $reload_flag" echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 if test "${lt_cv_path_NM+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/${ac_tool_prefix}nm if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then lt_cv_path_NM="$tmp_nm -B" break elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then lt_cv_path_NM="$tmp_nm -p" break else lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags fi fi done IFS="$ac_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi NM="$lt_cv_path_NM" echo "$as_me:$LINENO: result: $NM" >&5 echo "${ECHO_T}$NM" >&6 echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 if test "${lt_cv_path_SED+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_executable_p="test -f" as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext" fi done done done # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. : ${TMPDIR=/tmp} { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=$TMPDIR/sed$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 { (exit 1); exit 1; } } _max=0 _count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for _sed in $_sed_list /usr/xpg4/bin/sed; do test ! -f ${_sed} && break cat /dev/null > "$tmp/sed.in" _count=0 echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in" # Check for GNU sed and select it if it is found. if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then lt_cv_path_SED=${_sed} break fi while true; do cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp" mv "$tmp/sed.tmp" "$tmp/sed.in" cp "$tmp/sed.in" "$tmp/sed.nl" echo >>"$tmp/sed.nl" ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break # 40000 chars as input seems more than enough test $_count -gt 10 && break _count=`expr $_count + 1` if test $_count -gt $_max; then _max=$_count lt_cv_path_SED=$_sed fi done done rm -rf "$tmp" fi if test "X$SED" != "X"; then lt_cv_path_SED=$SED else SED=$lt_cv_path_SED fi echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6 echo "$as_me:$LINENO: checking whether ln -s works" >&5 echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no, using $LN_S" >&5 echo "${ECHO_T}no, using $LN_S" >&6 fi echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 if test "${lt_cv_deplibs_check_method+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given egrep regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac ;; freebsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20*|hpux11*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux-gnu*) case $host_cpu in alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | s390* | x86_64*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$' else lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv5uw[78]* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; esac fi echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method # Check for command to grab the raw symbol name followed by C symbol from nm. echo "$as_me:$LINENO: checking command to parse $NM output" >&5 echo $ECHO_N "checking command to parse $NM output... $ECHO_C" >&6 if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris* | sysv5*) symcode='[BDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $host_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[ABCDGISTW]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = { EOF sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$no_builtin_flag" if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" if test -z "$lt_cv_sys_global_symbol_pipe"; then global_symbol_to_cdecl= global_symbol_to_c_name_address= else global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address" fi if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address"; then echo "$as_me:$LINENO: result: failed" >&5 echo "${ECHO_T}failed" >&6 else echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6 fi echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="/usr/bin:$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo "$as_me:$LINENO: checking for file" >&5 echo $ECHO_N "checking for file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="/usr/bin:$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi else MAGIC_CMD=: fi fi fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi enable_dlopen=no enable_win32_dll=no # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" fi; test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in *-*-irix6*) # Find out which ABI we are using. echo '#line 5940 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi rm -rf conftest* ;; *-*-linux*) # Test if the compiler is 64bit echo 'int i;' > conftest.$ac_ext lt_cv_cc_64bit_output=no if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *"ELF 64"*) lt_cv_cc_64bit_output=yes ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 if test "${lt_cv_cc_needs_belf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then lt_cv_cc_needs_belf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" need_locks="$enable_libtool_lock" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o if test x"$host" != x"$build"; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case $host_os in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Allow CC to be a program name with arguments. set dummy $CC compiler="$2" echo "$as_me:$LINENO: checking for objdir" >&5 echo $ECHO_N "checking for objdir... $ECHO_C" >&6 rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null echo "$as_me:$LINENO: result: $objdir" >&5 echo "${ECHO_T}$objdir" >&6 # Check whether --with-pic or --without-pic was given. if test "${with_pic+set}" = set; then withval="$with_pic" pic_mode="$withval" else pic_mode=default fi; test -z "$pic_mode" && pic_mode=default # We assume here that the value for lt_cv_prog_cc_pic will not be cached # in isolation, and that seeing it set (from the cache) indicates that # the associated values are set (in the cache) correctly too. echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "${lt_cv_prog_cc_pic+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_cc_pic= lt_cv_prog_cc_shlib= lt_cv_prog_cc_wl= lt_cv_prog_cc_static= lt_cv_prog_cc_no_builtin= lt_cv_prog_cc_can_build_shared=$can_build_shared if test "$GCC" = yes; then lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-static' case $host_os in aix*) # Below there is a dirty hack to force normal static linking with -ldl # The problem is because libdl dynamically linked with both libc and # libC (AIX C++ library), which obviously doesn't included in libraries # list by gcc. This cause undefined symbols with -static flags. # This hack allows C programs to be linked with "-static -ldl", but # not sure about C++ programs. lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_cv_prog_cc_pic='-fno-common' ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; sysv4*MP*) if test -d /usr/nec; then lt_cv_prog_cc_pic=-Kconform_pic fi ;; *) lt_cv_prog_cc_pic='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case $host_os in aix3* | aix4* | aix5*) lt_cv_prog_cc_wl='-Wl,' # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_cv_prog_cc_static='-Bstatic' else lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' fi ;; hpux9* | hpux10* | hpux11*) # Is there a better lt_cv_prog_cc_static that works with the bundled CC? lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" lt_cv_prog_cc_pic='+Z' ;; irix5* | irix6* | nonstopux*) lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; newsos6) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' ;; sco3.2v5*) lt_cv_prog_cc_pic='-Kpic' lt_cv_prog_cc_static='-dn' lt_cv_prog_cc_shlib='-belf' ;; solaris*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; sunos4*) lt_cv_prog_cc_pic='-PIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; uts4*) lt_cv_prog_cc_pic='-pic' lt_cv_prog_cc_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_cv_prog_cc_pic='-Kconform_pic' lt_cv_prog_cc_static='-Bstatic' fi ;; *) lt_cv_prog_cc_can_build_shared=no ;; esac fi fi if test -z "$lt_cv_prog_cc_pic"; then echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6 else echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic" >&5 echo "${ECHO_T}$lt_cv_prog_cc_pic" >&6 # Check to make sure the pic_flag actually works. echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_cv_prog_cc_pic works... $ECHO_C" >&6 if test "${lt_cv_prog_cc_pic_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then case $host_os in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then # they create non-PIC objects. So, if there were any warnings, we # assume that PIC is not supported. if test -s conftest.err; then lt_cv_prog_cc_pic_works=no else lt_cv_prog_cc_pic_works=yes fi ;; *) lt_cv_prog_cc_pic_works=yes ;; esac else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_prog_cc_pic_works=no fi rm -f conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" fi if test "X$lt_cv_prog_cc_pic_works" = Xno; then lt_cv_prog_cc_pic= lt_cv_prog_cc_can_build_shared=no else lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" fi echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic_works" >&5 echo "${ECHO_T}$lt_cv_prog_cc_pic_works" >&6 fi # Check for any special shared library compilation flags. if test -n "$lt_cv_prog_cc_shlib"; then { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&5 echo "$as_me: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&2;} if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$lt_cv_prog_cc_shlib[ ]" >/dev/null; then : else { echo "$as_me:$LINENO: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 echo "$as_me: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} lt_cv_prog_cc_can_build_shared=no fi fi echo "$as_me:$LINENO: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_cv_prog_cc_static works... $ECHO_C" >&6 if test "${lt_cv_prog_cc_static_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_cc_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then lt_cv_prog_cc_static_works=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi # Belt *and* braces to stop my trousers falling down: test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= echo "$as_me:$LINENO: result: $lt_cv_prog_cc_static_works" >&5 echo "${ECHO_T}$lt_cv_prog_cc_static_works" >&6 pic_flag="$lt_cv_prog_cc_pic" special_shlib_compile_flags="$lt_cv_prog_cc_shlib" wl="$lt_cv_prog_cc_wl" link_static_flag="$lt_cv_prog_cc_static" no_builtin_flag="$lt_cv_prog_cc_no_builtin" can_build_shared="$lt_cv_prog_cc_can_build_shared" # Check to see if options -o and -c are simultaneously supported by compiler echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_compiler_c_o+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else $rm -r conftest 2>/dev/null mkdir conftest cd conftest echo "int some_variable = 0;" > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no if { (eval echo configure:6487: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then lt_cv_compiler_c_o=no else lt_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&5 lt_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null fi compiler_c_o=$lt_cv_compiler_c_o echo "$as_me:$LINENO: result: $compiler_c_o" >&5 echo "${ECHO_T}$compiler_c_o" >&6 if test x"$compiler_c_o" = x"yes"; then # Check to see if we can write to a .lo echo "$as_me:$LINENO: checking if $compiler supports -c -o file.lo" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.lo... $ECHO_C" >&6 if test "${lt_cv_compiler_o_lo+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_compiler_o_lo=no save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -c -o conftest.lo" save_objext="$ac_objext" ac_objext=lo cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int some_variable = 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then lt_cv_compiler_o_lo=no else lt_cv_compiler_o_lo=yes fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext ac_objext="$save_objext" CFLAGS="$save_CFLAGS" fi compiler_o_lo=$lt_cv_compiler_o_lo echo "$as_me:$LINENO: result: $compiler_o_lo" >&5 echo "${ECHO_T}$compiler_o_lo" >&6 else compiler_o_lo=no fi # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi if test "$GCC" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 echo "int some_variable = 0;" > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" compiler_rtti_exceptions=no cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int some_variable = 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then compiler_rtti_exceptions=no else compiler_rtti_exceptions=yes fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" echo "$as_me:$LINENO: result: $compiler_rtti_exceptions" >&5 echo "${ECHO_T}$compiler_rtti_exceptions" >&6 if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi # See if the linker supports building shared libraries. echo "$as_me:$LINENO: checking whether the linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the linker ($LD) supports shared libraries... $ECHO_C" >&6 allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_into_libs=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= link_all_deplibs=unknown always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ test -f $output_objdir/impgen.exe || (cd $output_objdir && \ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ else $CC -o impgen impgen.c ; fi)~ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' # cygwin and mingw dlls have different entry points and sets of symbols # to exclude. # FIXME: what about values for MSVC? dll_entry=__cygwin_dll_entry@12 dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ case $host_os in mingw*) # mingw values dll_entry=_DllMainCRTStartup@12 dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ ;; esac # mingw and cygwin differ, and it's simplest to just exclude the union # of the two symbol sets. dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one (in ltdll.c) if test "x$lt_cv_need_dllmain" = "xyes"; then ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' else ltdll_obj= ltdll_cmds= fi # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. # Be careful not to strip the DATA tag left be newer dlltools. export_symbols_cmds="$ltdll_cmds"' $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is. # If DATA tags from a recent dlltool are present, honour them! archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname-def; else echo EXPORTS > $output_objdir/$soname-def; _lt_hint=1; cat $export_symbols | while read symbol; do set dummy \$symbol; case \$# in 2) echo " \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; 4) echo " \$2 \$3 \$4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;; *) echo " \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;; esac; _lt_hint=`expr 1 + \$_lt_hint`; done; fi~ '"$ltdll_cmds"' $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw* | pw32*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. hardcode_direct=yes archive_cmds='' hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then shared_flag='${wl}-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall can do strange things, so it is better to # generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. allow_undefined_flag='${wl}-berok' # This is a bit strange, but is similar to how AIX traditionally builds # it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' ;; darwin* | rhapsody*) case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on allow_undefined_flag='-flat_namespace -undefined suppress' ;; esac # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. Also zsh mangles # `"' quotes if we put them in here... so don't! archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)' # We need to add '_' to the symbols in $export_symbols first #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' hardcode_direct=yes hardcode_shlibpath_var=no whole_archive_flag_spec='-all_load $convenience' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case $host_os in hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' #Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes export_dynamic_flag_spec='${wl}-Bexport' ;; solaris*) # gcc --version < 3.0 without binutils cannot create self contained # shared libraries reliably, requiring libgcc.a to resolve some of # the object symbols generated in some cases. Libraries that use # assert need libgcc.a to resolve __eprintf, for example. Linking # a copy of libgcc.a into every shared library to guarantee resolving # such symbols causes other problems: According to Tim Van Holder # , C++ libraries end up with a separate # (to the application) exception stack for one thing. no_undefined_flag=' -z defs' if test "$GCC" = yes; then case `$CC --version 2>/dev/null` in [12].*) cat <&2 *** Warning: Releases of GCC earlier than version 3.0 cannot reliably *** create self contained shared libraries on Solaris systems, without *** introducing a dependency on libgcc.a. Therefore, libtool is disabling *** -no-undefined support, which will at least allow you to build shared *** libraries. However, you may find that when you link such libraries *** into an application without using GCC, you have to manually add *** \`gcc --print-libgcc-file-name\` to the link command. We urge you to *** upgrade to a newer version of GCC. Another option is to rebuild your *** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer. EOF no_undefined_flag= ;; esac fi # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5uw7* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs" >&5 echo "${ECHO_T}$ld_shlibs" >&6 test "$ld_shlibs" = no && can_build_shared=no # Check hardcoding attributes. echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action" >&5 echo "${ECHO_T}$hardcode_action" >&6 striplib= old_striplib= echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi reload_cmds='$LD$reload_flag -o $output$reload_objs' test -z "$deplibs_check_method" && deplibs_check_method=unknown # PORTME Fill in your ld.so characteristics echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib /usr/X11R6/lib" case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can # not hardcode correct soname into executable. Probably we can # add versioning support to collect2, so additional links can # be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}.so$major' fi shlibpath_var=LIBPATH fi hardcode_into_libs=yes ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin*) library_names_spec='$libname.dll.a' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog .libs/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' ;; yes,mingw*) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"` ;; yes,pw32*) library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll' ;; *) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; *) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) version_type=irix ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes case $host_cpu:$lt_cv_cc_64bit_output in powerpc64:yes | s390x:yes | sparc64:yes | x86_64:yes) sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /usr/X11R6/lib64" sys_lib_search_path_spec="/lib64 /usr/lib64 /usr/local/lib64 /usr/X11R6/lib64" ;; esac # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' # Find out which ABI we are using (multilib Linux x86_64 hack). libsuff= case "$host_cpu" in x86_64*) echo '#line 7678 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 ;; esac fi rm -rf conftest* ;; *) ;; esac sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case "$host_os" in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" hardcode_into_libs=yes ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no # Report the final consequences. echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6 echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6 echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; cygwin* | mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; *) echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 if test "${ac_cv_func_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else char (*f) () = shl_load; #endif #ifdef __cplusplus } #endif int main () { return f != shl_load; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6 if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); int main () { shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 if test "${ac_cv_func_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else char (*f) () = dlopen; #endif #ifdef __cplusplus } #endif int main () { return f != dlopen; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6 if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dld_link (); int main () { dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6 if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 if test "${lt_cv_archive_cmds_need_lc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else $rm conftest* echo 'static int dummy;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_cv_prog_cc_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$save_allow_undefined_flag else cat conftest.err 1>&5 fi fi echo "$as_me:$LINENO: result: $lt_cv_archive_cmds_need_lc" >&5 echo "${ECHO_T}$lt_cv_archive_cmds_need_lc" >&6 ;; esac fi need_lc=${lt_cv_archive_cmds_need_lc-yes} # The second clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then : else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi if test -f "$ltmain"; then trap "$rm \"${ofile}T\"; exit 1" 1 2 15 $rm -f "${ofile}T" echo creating $ofile # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS SED \ AR AR_FLAGS CC LD LN_S NM SHELL \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ old_striplib striplib file_magic_cmd export_symbols_cmds \ deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ global_symbol_to_c_name_address \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do case $var in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done cat <<__EOF__ > "${ofile}T" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996-2000 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="${SED} -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$need_lc # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # The default C compiler. CC=$lt_CC # Is the compiler the GNU C compiler? with_gcc=$GCC # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_pic_flag pic_mode=$pic_mode # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_compiler_c_o # Can we write directly to a .lo ? compiler_o_lo=$lt_compiler_o_lo # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "${ofile}T" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac case $host_os in cygwin* | mingw* | pw32* | os2*) cat <<'EOF' >> "${ofile}T" # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include /* for printf() */ # #include /* for open(), lseek(), read() */ # #include /* for O_RDONLY, O_BINARY */ # #include /* for strdup() */ # # /* O_BINARY isn't required (or even defined sometimes) under Unix */ # #ifndef O_BINARY # #define O_BINARY 0 # #endif # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (dll < 1) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) mv -f "${ofile}T" "$ofile" || \ (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") chmod +x "$ofile" fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion # --------------------------------------------------------------------- # Compilation environment # --------------------------------------------------------------------- # --------------------------------------------------------------------- # Check sizes of integer types. # Cross-compiling sizes set to 2,4,4,8. (May need to be changed...) # --------------------------------------------------------------------- echo "$as_me:$LINENO: checking for short" >&5 echo $ECHO_N "checking for short... $ECHO_C" >&6 if test "${ac_cv_type_short+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((short *) 0) return 0; if (sizeof (short)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_short=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_short=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_short" >&5 echo "${ECHO_T}$ac_cv_type_short" >&6 echo "$as_me:$LINENO: checking size of short" >&5 echo $ECHO_N "checking size of short... $ECHO_C" >&6 if test "${ac_cv_sizeof_short+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_short" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (short))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (short))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (short))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_short=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (short), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (short)); } unsigned long ulongval () { return (long) (sizeof (short)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (short))) < 0) { long i = longval (); if (i != ((long) (sizeof (short)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (short)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_short=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (short), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_short=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5 echo "${ECHO_T}$ac_cv_sizeof_short" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_SHORT $ac_cv_sizeof_short _ACEOF echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6 if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((int *) 0) return 0; if (sizeof (int)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6 echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6 if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_int" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (int)); } unsigned long ulongval () { return (long) (sizeof (int)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (int))) < 0) { long i = longval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_int=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6 if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((long *) 0) return 0; if (sizeof (long)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6 echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6 if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_long" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (long)); } unsigned long ulongval () { return (long) (sizeof (long)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (long))) < 0) { long i = longval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_long=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF echo "$as_me:$LINENO: checking for long long" >&5 echo $ECHO_N "checking for long long... $ECHO_C" >&6 if test "${ac_cv_type_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((long long *) 0) return 0; if (sizeof (long long)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_long_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long_long=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 echo "${ECHO_T}$ac_cv_type_long_long" >&6 echo "$as_me:$LINENO: checking size of long long" >&5 echo $ECHO_N "checking size of long long... $ECHO_C" >&6 if test "${ac_cv_sizeof_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_long_long" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long_long=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (long long)); } unsigned long ulongval () { return (long) (sizeof (long long)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (long long))) < 0) { long i = longval (); if (i != ((long) (sizeof (long long)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (long long)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_long_long=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long _ACEOF # --------------------------------------------------------------------- # Checks for header files. # --------------------------------------------------------------------- ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in dir; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi else echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in x; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi fi echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi for ac_header in limits.h sys/time.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/types.h sys/socket.h netdb.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/wait.h signal.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if false; then HAVE_PNG_TRUE= HAVE_PNG_FALSE='#' else HAVE_PNG_TRUE='#' HAVE_PNG_FALSE= fi for ac_header in png.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF if true; then HAVE_PNG_TRUE= HAVE_PNG_FALSE='#' else HAVE_PNG_TRUE='#' HAVE_PNG_FALSE= fi fi done echo "$as_me:$LINENO: checking for Alpha/Linux with DEC CXX" >&5 echo $ECHO_N "checking for Alpha/Linux with DEC CXX... $ECHO_C" >&6 if test "$cross_compiling" = yes; then echo "$as_me:$LINENO: result: cross compiling- assuming \"no\"" >&5 echo "${ECHO_T}cross compiling- assuming \"no\"" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main(int argc, char **argv) { #if defined (__DECCXX) && defined(__linux__) && defined(__alpha__) return 0; #endif return 1; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define ALPHA_LINUX_CXX 1 _ACEOF else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 if test -z "$CXXCPP"; then if test "${ac_cv_prog_CXXCPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi echo "$as_me:$LINENO: result: $CXXCPP" >&5 echo "${ECHO_T}$CXXCPP" >&6 ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu for ac_header in hash_map hash_set ext/hash_map ext/hash_set sstream do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # --------------------------------------------------------------------- # Checks for typedefs, structures, and compiler characteristics. # --------------------------------------------------------------------- echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset x; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; ccp = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++ccp; p = (char**) ccp; ccp = (char const *const *) p; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6 if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; no) cat >>confdefs.h <<\_ACEOF #define inline _ACEOF ;; *) cat >>confdefs.h <<_ACEOF #define inline $ac_cv_c_inline _ACEOF ;; esac echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6 if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((size_t *) 0) return 0; if (sizeof (size_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6 if test $ac_cv_type_size_t = yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned _ACEOF fi echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 if test "${ac_cv_header_time+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_time=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_time=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 echo "${ECHO_T}$ac_cv_header_time" >&6 if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF #define TIME_WITH_SYS_TIME 1 _ACEOF fi echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6 if test "${ac_cv_struct_tm+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { struct tm *tp; tp->tm_sec; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_struct_tm=time.h else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_struct_tm=sys/time.h fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 echo "${ECHO_T}$ac_cv_struct_tm" >&6 if test $ac_cv_struct_tm = sys/time.h; then cat >>confdefs.h <<\_ACEOF #define TM_IN_SYS_TIME 1 _ACEOF fi if test "$ac_cv_c_compiler_gnu" = "yes"; then CFLAGS="$CFLAGS -Wall" fi # --------------------------------------------------------------------- # Checks for library functions # --------------------------------------------------------------------- echo "$as_me:$LINENO: checking for working memcmp" >&5 echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6 if test "${ac_cv_func_memcmp_working+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_working=no else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = 0x40, c1 = 0x80, c2 = 0x81; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) exit (1); /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) exit (1); } exit (0); } ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_memcmp_working=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_memcmp_working=no fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5 echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6 test $ac_cv_func_memcmp_working = no && LIBOBJS="$LIBOBJS memcmp.$ac_objext" for ac_func in atexit dup2 getcwd isascii memchr memmove memset mkdir pow select socket strcasecmp strchr strstr strtol strtoul do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for getaddrinfo()" >&5 echo $ECHO_N "checking for getaddrinfo()... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETDB_H #include #endif int main () { struct addrinfo a; //getaddrinfo(0, 0, 0, 0); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_getaddrinfo=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getaddrinfo=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5 echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6 if test x$ac_cv_func_getaddrinfo = xyes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_GETADDRINFO 1 _ACEOF fi echo "$as_me:$LINENO: checking for mkstemp()" >&5 echo $ECHO_N "checking for mkstemp()... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_UNISTD_H #include #endif #include int main () { mkstemp(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_mkstemp=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_mkstemp=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_cv_func_mkstemp" >&5 echo "${ECHO_T}$ac_cv_func_mkstemp" >&6 if test x$ac_cv_func_mkstemp = xyes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_MKSTEMP 1 _ACEOF fi echo "$as_me:$LINENO: checking for snprintf()" >&5 echo $ECHO_N "checking for snprintf()... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { snprintf(0,0,0,0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_snprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_snprintf=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_cv_func_snprintf" >&5 echo "${ECHO_T}$ac_cv_func_snprintf" >&6 if test x$ac_cv_func_snprintf = xyes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_SNPRINTF 1 _ACEOF if true; then HAVE_SNPRINTF_TRUE= HAVE_SNPRINTF_FALSE='#' else HAVE_SNPRINTF_TRUE='#' HAVE_SNPRINTF_FALSE= fi else if false; then HAVE_SNPRINTF_TRUE= HAVE_SNPRINTF_FALSE='#' else HAVE_SNPRINTF_TRUE='#' HAVE_SNPRINTF_FALSE= fi fi # do we need special X11 libraries? echo "$as_me:$LINENO: checking for special X11 libraries" >&5 echo $ECHO_N "checking for special X11 libraries... $ECHO_C" >&6 if test x$x_libraries = xNONE; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 unset x_libraries else x_libraries="-L$x_libraries -lX11 -lXext" echo "$as_me:$LINENO: result: $x_libraries" >&5 echo "${ECHO_T}$x_libraries" >&6 fi # --------------------------------------------------------------------- # SDL # --------------------------------------------------------------------- SDL_VERSION=1.2.0 # Check whether --with-sdl-prefix or --without-sdl-prefix was given. if test "${with_sdl_prefix+set}" = set; then withval="$with_sdl_prefix" sdl_prefix="$withval" else sdl_prefix="" fi; # Check whether --with-sdl-exec-prefix or --without-sdl-exec-prefix was given. if test "${with_sdl_exec_prefix+set}" = set; then withval="$with_sdl_exec_prefix" sdl_exec_prefix="$withval" else sdl_exec_prefix="" fi; # Check whether --enable-sdltest or --disable-sdltest was given. if test "${enable_sdltest+set}" = set; then enableval="$enable_sdltest" else enable_sdltest=yes fi; if test x$sdl_exec_prefix != x ; then sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config fi fi if test x$sdl_prefix != x ; then sdl_args="$sdl_args --prefix=$sdl_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_prefix/bin/sdl-config fi fi PATH="$prefix/bin:$prefix/usr/bin:$PATH" # Extract the first word of "sdl-config", so it can be a program name with args. set dummy sdl-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_SDL_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $SDL_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SDL_CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_path_SDL_CONFIG" && ac_cv_path_SDL_CONFIG="no" ;; esac fi SDL_CONFIG=$ac_cv_path_SDL_CONFIG if test -n "$SDL_CONFIG"; then echo "$as_me:$LINENO: result: $SDL_CONFIG" >&5 echo "${ECHO_T}$SDL_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi min_sdl_version=$SDL_VERSION echo "$as_me:$LINENO: checking for SDL - version >= $min_sdl_version" >&5 echo $ECHO_N "checking for SDL - version >= $min_sdl_version... $ECHO_C" >&6 no_sdl="" if test "$SDL_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" rm -f conf.sdltest if test "$cross_compiling" = yes; then echo $ac_n "cross compiling; assumed OK... $ac_c" else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include "SDL.h" char* my_strdup (char *str) { char *new_str; if (str) { new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); strcpy (new_str, str); } else new_str = NULL; return new_str; } int main (int argc, char *argv[]) { int major, minor, micro; char *tmp_version; /* This hangs on some systems (?) system ("touch conf.sdltest"); */ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = my_strdup("$min_sdl_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); printf("*** to point to the correct copy of sdl-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) no_sdl=yes fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 : else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 if test "$SDL_CONFIG" = "no" ; then echo "*** The sdl-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL_CONFIG environment variable to the" echo "*** full path to sdl-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include "SDL.h" int main(int argc, char *argv[]) { return 0; } #undef main #define main K_and_R_C_main int main () { return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" { { echo "$as_me:$LINENO: error: *** SDL version $SDL_VERSION not found!" >&5 echo "$as_me: error: *** SDL version $SDL_VERSION not found!" >&2;} { (exit 1); exit 1; }; } fi rm -f conf.sdltest echo "$as_me:$LINENO: checking for Mix_QuickLoad_RAW in -lSDL_mixer" >&5 echo $ECHO_N "checking for Mix_QuickLoad_RAW in -lSDL_mixer... $ECHO_C" >&6 if test "${ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL_mixer $SDL_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char Mix_QuickLoad_RAW (); int main () { Mix_QuickLoad_RAW (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW" >&5 echo "${ECHO_T}$ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW" >&6 if test $ac_cv_lib_SDL_mixer_Mix_QuickLoad_RAW = yes; then SDL_LIBS="$SDL_LIBS -lSDL_mixer" else { { echo "$as_me:$LINENO: error: *** SDL_mixer version 1.2.4 or later not found!" >&5 echo "$as_me: error: *** SDL_mixer version 1.2.4 or later not found!" >&2;} { (exit 1); exit 1; }; } fi # --------------------------------------------------------------------- # Optional components # --------------------------------------------------------------------- # Timidity MIDI driver echo "$as_me:$LINENO: checking whether to enable timidity" >&5 echo $ECHO_N "checking whether to enable timidity... $ECHO_C" >&6 # Check whether --enable-timidity or --disable-timidity was given. if test "${enable_timidity+set}" = set; then enableval="$enable_timidity" else enable_timidity=yes fi; if test x$enable_timidity = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 # Extract the first word of "timidity", so it can be a program name with args. set dummy timidity; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_HAVE_TIMIDITY_BIN+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$HAVE_TIMIDITY_BIN"; then ac_cv_prog_HAVE_TIMIDITY_BIN="$HAVE_TIMIDITY_BIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HAVE_TIMIDITY_BIN="found it" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_HAVE_TIMIDITY_BIN" && ac_cv_prog_HAVE_TIMIDITY_BIN="not found" fi fi HAVE_TIMIDITY_BIN=$ac_cv_prog_HAVE_TIMIDITY_BIN if test -n "$HAVE_TIMIDITY_BIN"; then echo "$as_me:$LINENO: result: $HAVE_TIMIDITY_BIN" >&5 echo "${ECHO_T}$HAVE_TIMIDITY_BIN" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "$HAVE_TIMIDITY_BIN" = "found it"; then cat >>confdefs.h <<\_ACEOF #define HAVE_TIMIDITY_BIN 1 _ACEOF fi else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # zipped savegame support # Check whether --enable-zip-support or --disable-zip-support was given. if test "${enable_zip_support+set}" = set; then enableval="$enable_zip_support" else enable_zip_support=yes fi; if test x$enable_zip_support = xyes ; then if test "${ac_cv_header_zlib_h+set}" = set; then echo "$as_me:$LINENO: checking for zlib.h" >&5 echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6 if test "${ac_cv_header_zlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 echo "${ECHO_T}$ac_cv_header_zlib_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking zlib.h usability" >&5 echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking zlib.h presence" >&5 echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for zlib.h" >&5 echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6 if test "${ac_cv_header_zlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_zlib_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 echo "${ECHO_T}$ac_cv_header_zlib_h" >&6 fi if test $ac_cv_header_zlib_h = yes; then : else enable_zip_support=no fi fi echo "$as_me:$LINENO: checking for zipped savegame support" >&5 echo $ECHO_N "checking for zipped savegame support... $ECHO_C" >&6 if test x$enable_zip_support = xyes ; then # disabled for now (non-portable): # link statically against zlib if using gcc # if test x$GCC = xyes ; then # ZLIB_LIBS="-Wl,-Bstatic -lz -Wl,-Bdynamic" # else ZLIB_LIBS="-lz" # fi cat >>confdefs.h <<\_ACEOF #define HAVE_ZIP_SUPPORT 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # OpenGL rendering # Check whether --enable-opengl or --disable-opengl was given. if test "${enable_opengl+set}" = set; then enableval="$enable_opengl" else enable_opengl=no fi; echo "$as_me:$LINENO: checking for OpenGL rendering support" >&5 echo $ECHO_N "checking for OpenGL rendering support... $ECHO_C" >&6 if test x$enable_opengl = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_OPENGL 1 _ACEOF # Mac OS X gets OpenGL through a framework (which appears to be pulled in by SDL) if test x$ARCH != xmacosx; then OPENGL_LIBS="-lGL" fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # --------------------------------------------------------------------- # support for Exult Studio # --------------------------------------------------------------------- echo "$as_me:$LINENO: checking whether to enable support for Exult Studio" >&5 echo $ECHO_N "checking whether to enable support for Exult Studio... $ECHO_C" >&6 # Check whether --enable-exult-studio-support or --disable-exult-studio-support was given. if test "${enable_exult_studio_support+set}" = set; then enableval="$enable_exult_studio_support" else enable_exult_studio_support=yes fi; if test "$WINDOWING_SYSTEM" != -DXWIN ; then enable_exult_studio_support=no fi if test x$enable_exult_studio_support = xyes ; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define USE_EXULTSTUDIO 1 _ACEOF else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # --------------------------------------------------------------------- # Memory allocation scheme # --------------------------------------------------------------------- echo "$as_me:$LINENO: checking checking memory allocation scheme" >&5 echo $ECHO_N "checking checking memory allocation scheme... $ECHO_C" >&6 # For the alternate allocator # Check whether --enable-alternate-allocator or --disable-alternate-allocator was given. if test "${enable_alternate_allocator+set}" = set; then enableval="$enable_alternate_allocator" else enable_alternate_allocator=no fi; if test x$enable_alternate_allocator = xyes; then cat >>confdefs.h <<\_ACEOF #define WANT_ALTERNATE_ALLOCATOR 1 _ACEOF fi # For storage initialisation # Check whether --enable-storage-initialisation or --disable-storage-initialisation was given. if test "${enable_storage_initialisation+set}" = set; then enableval="$enable_storage_initialisation" else enable_storage_initialisation=no fi; if test x$enable_storage_initialisation = xyes; then cat >>confdefs.h <<\_ACEOF #define WANT_ALTERNATE_ALLOCATOR 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define INITIALISE_ALLOCATED_BLOCKS 0 _ACEOF fi # For storage poisoning # Check whether --enable-storage-poisoning or --disable-storage-poisoning was given. if test "${enable_storage_poisoning+set}" = set; then enableval="$enable_storage_poisoning" else enable_storage_poisoning=no fi; if test x$enable_storage_poisoning = xyes; then if test x$enable_storage_initialisation = xyes; then echo "$as_me:$LINENO: result: poisoned. (Disabling storage initialisation. Can't poison and init to zero.)" >&5 echo "${ECHO_T}poisoned. (Disabling storage initialisation. Can't poison and init to zero.)" >&6 fi cat >>confdefs.h <<\_ACEOF #define WANT_ALTERNATE_ALLOCATOR 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define POISON_ALLOCATED_BLOCKS 1 _ACEOF fi # output result if test x$enable_storage_poisoning = xyes; then if test x$enable_storage_initialisation = xno; then echo "$as_me:$LINENO: result: poisoned" >&5 echo "${ECHO_T}poisoned" >&6 fi else if test x$enable_storage_initialisation = xyes; then echo "$as_me:$LINENO: result: initialized" >&5 echo "${ECHO_T}initialized" >&6 else if test x$enable_alternate_allocator = xyes; then echo "$as_me:$LINENO: result: alternate" >&5 echo "${ECHO_T}alternate" >&6 else echo "$as_me:$LINENO: result: normal" >&5 echo "${ECHO_T}normal" >&6 fi fi fi # --------------------------------------------------------------------- # Debugging options # --------------------------------------------------------------------- # basic debugging mode # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" else enable_debug=no fi; echo "$as_me:$LINENO: checking whether to enable debugging mode" >&5 echo $ECHO_N "checking whether to enable debugging mode... $ECHO_C" >&6 if test x$enable_debug = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define DEBUG 1 _ACEOF DEBUG_FLAGS="-g" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 DEBUG_FLAGS="-O2" fi # optimized debugging mode # Check whether --enable-optimized-debug or --disable-optimized-debug was given. if test "${enable_optimized_debug+set}" = set; then enableval="$enable_optimized_debug" else enable_optimized_debug=no fi; echo "$as_me:$LINENO: checking whether to do an optimized debug build" >&5 echo $ECHO_N "checking whether to do an optimized debug build... $ECHO_C" >&6 if test x$enable_optimized_debug = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define DEBUG 1 _ACEOF DEBUG_FLAGS="-g -O2 -fno-default-inline -fno-inline" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # SDL parachute? # Check whether --enable-sdl-parachute or --disable-sdl-parachute was given. if test "${enable_sdl_parachute+set}" = set; then enableval="$enable_sdl_parachute" else enable_sdl_parachute=yes fi; echo "$as_me:$LINENO: checking if we should disable the SDL parachute" >&5 echo $ECHO_N "checking if we should disable the SDL parachute... $ECHO_C" >&6 if test x$enable_sdl_parachute = xno; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define NO_SDL_PARACHUTE 1 _ACEOF else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Usecode debugger #AC_ARG_ENABLE(usecode-debugger, [ --enable-usecode-debugger Support for usecode debugging [default no]],,enable_usecode_debugger=no) #AC_MSG_CHECKING(whether to enable the usecode debugger) #if test x$enable_usecode_debugger = xyes; then # AC_MSG_RESULT(yes) # AC_DEFINE(USECODE_DEBUGGER, 1, [Enable Usecode debugging]) #else # AC_MSG_RESULT(no) #fi # --------------------------------------------------------------------- # Warning level # --------------------------------------------------------------------- # determine warning level echo "$as_me:$LINENO: checking warning level" >&5 echo $ECHO_N "checking warning level... $ECHO_C" >&6 WARNING_LEVEL="normal" # more warnings # Check whether --enable-warnings or --disable-warnings was given. if test "${enable_warnings+set}" = set; then enableval="$enable_warnings" else enable_warnings=no fi; if test x$enable_warnings = xyes; then DEBUG_FLAGS="$DEBUG_FLAGS -Wall -O -Wunused -Wuninitialized -Woverloaded-virtual -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Winline" WARNING_LEVEL="all" fi # Weep into your beer warnings # Check whether --enable-awful-warnings or --disable-awful-warnings was given. if test "${enable_awful_warnings+set}" = set; then enableval="$enable_awful_warnings" else enable_awful_warnings=no fi; if test x$enable_awful_warnings = xyes; then DEBUG_FLAGS="$DEBUG_FLAGS -Weffc++" if test x$WARNING_LEVEL = xall; then WARNING_LEVEL="all, including Scott Meyers' 'effective C++'" else WARNING_LEVEL="Scott Meyers' 'effective C++'" fi fi # Check whether --enable-paranoid-warnings or --disable-paranoid-warnings was given. if test "${enable_paranoid_warnings+set}" = set; then enableval="$enable_paranoid_warnings" else enable_paranoid_warnings=no fi; if test x$enable_paranoid_warnings = xyes; then WARNINGS="-Wall -W -Wcast-qual -Wwrite-strings -Wconversion -Wredundant-decls -Winline -Wdisabled-optimization -fcheck-new -Wctor-dtor-privacy -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual" # DEBUG_FLAGS="$DEBUG_FLAGS -Wall -O -Wunused -Wuninitialized -Woverloaded-virtual -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Winline" WARNING_LEVEL="paranoid" fi # Output result echo "$as_me:$LINENO: result: $WARNING_LEVEL" >&5 echo "${ECHO_T}$WARNING_LEVEL" >&6 # Ignore long-long warnings (for SDL header files...) # Check whether --enable-long-long-warnings or --disable-long-long-warnings was given. if test "${enable_long_long_warnings+set}" = set; then enableval="$enable_long_long_warnings" fi; echo "$as_me:$LINENO: checking if we should disable long-long warnings" >&5 echo $ECHO_N "checking if we should disable long-long warnings... $ECHO_C" >&6 if test x$enable_long_long_warnings = xyes; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 DEBUG_FLAGS="$DEBUG_FLAGS -Wno-long-long" fi # Heavy namespaces. Most installations probably can't take this option # Check whether --enable-std-namespace or --disable-std-namespace was given. if test "${enable_std_namespace+set}" = set; then enableval="$enable_std_namespace" else enable_std_namespace=no fi; echo "$as_me:$LINENO: checking if we should honour the std namespace" >&5 echo $ECHO_N "checking if we should honour the std namespace... $ECHO_C" >&6 if test x$enable_std_namespace = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 DEBUG_FLAGS="$DEBUG_FLAGS -fhonor-std" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # repo # Check whether --enable-repo or --disable-repo was given. if test "${enable_repo+set}" = set; then enableval="$enable_repo" else enable_repo=no fi; echo "$as_me:$LINENO: checking if we should use repo type template instantiation" >&5 echo $ECHO_N "checking if we should use repo type template instantiation... $ECHO_C" >&6 if test x$enable_repo = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 DEBUG_FLAGS="$DEBUG_FLAGS -frepo" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # external templates (alt) # Check whether --enable-external-templates or --disable-external-templates was given. if test "${enable_external_templates+set}" = set; then enableval="$enable_external_templates" else enable_external_templates=no fi; echo "$as_me:$LINENO: checking if we should use (alternate) external template instantiation" >&5 echo $ECHO_N "checking if we should use (alternate) external template instantiation... $ECHO_C" >&6 if test x$enable_external_templates = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 DEBUG_FLAGS="$DEBUG_FLAGS -falt-external-templates" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Architecture dependent optimisations echo "$as_me:$LINENO: checking if we should optimise for MMX" >&5 echo $ECHO_N "checking if we should optimise for MMX... $ECHO_C" >&6 # Check whether --enable-timidity or --disable-timidity was given. if test "${enable_timidity+set}" = set; then enableval="$enable_timidity" else enable_mmx=no fi; if test x$enable_mmx = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 CXXFLAGS="$CXXFLAGS -mmmx" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Architecture dependent optimisations echo "$as_me:$LINENO: checking if we should optimise for 3DNOW" >&5 echo $ECHO_N "checking if we should optimise for 3DNOW... $ECHO_C" >&6 # Check whether --enable-timidity or --disable-timidity was given. if test "${enable_timidity+set}" = set; then enableval="$enable_timidity" else enable_3dnow=no fi; if test x$enable_3dnow = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 CXXFLAGS="$CXXFLAGS -m3dnow" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # -------------------- # External features # -------------------- # Build any external programs? # Check whether --enable-tools or --disable-tools was given. if test "${enable_tools+set}" = set; then enableval="$enable_tools" else enable_tools=yes fi; echo "$as_me:$LINENO: checking whether to build only the main program" >&5 echo $ECHO_N "checking whether to build only the main program... $ECHO_C" >&6 if test x$enable_tools = xno; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 if false; then BUILD_TOOLS_TRUE= BUILD_TOOLS_FALSE='#' else BUILD_TOOLS_TRUE='#' BUILD_TOOLS_FALSE= fi enable_gtk_interface=no enable_gimp_plugin=no enable_compiler=no else if true; then BUILD_TOOLS_TRUE= BUILD_TOOLS_FALSE='#' else BUILD_TOOLS_TRUE='#' BUILD_TOOLS_FALSE= fi echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Build compiler? # Check whether --enable-compiler or --disable-compiler was given. if test "${enable_compiler+set}" = set; then enableval="$enable_compiler" else enable_compiler=yes fi; echo "$as_me:$LINENO: checking whether to build the usecode compiler" >&5 echo $ECHO_N "checking whether to build the usecode compiler... $ECHO_C" >&6 if test x$enable_compiler = xno; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 if false; then BUILD_COMPILER_TRUE= BUILD_COMPILER_FALSE='#' else BUILD_COMPILER_TRUE='#' BUILD_COMPILER_FALSE= fi else echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 if true; then BUILD_COMPILER_TRUE= BUILD_COMPILER_FALSE='#' else BUILD_COMPILER_TRUE='#' BUILD_COMPILER_FALSE= fi fi # Build data files? # Check whether --enable-data or --disable-data was given. if test "${enable_data+set}" = set; then enableval="$enable_data" else enable_data=yes fi; echo "$as_me:$LINENO: checking whether to build the data files" >&5 echo $ECHO_N "checking whether to build the data files... $ECHO_C" >&6 if test x$enable_data = xno; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 if false; then DATA_FILES_TRUE= DATA_FILES_FALSE='#' else DATA_FILES_TRUE='#' DATA_FILES_FALSE= fi else if true; then DATA_FILES_TRUE= DATA_FILES_FALSE='#' else DATA_FILES_TRUE='#' DATA_FILES_FALSE= fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 fi # pkg-config echo "$as_me:$LINENO: checking for pkg-config" >&5 echo $ECHO_N "checking for pkg-config... $ECHO_C" >&6 if test "x`pkg-config --version`" = "x"; then echo "$as_me:$LINENO: result: no pkg-config" >&5 echo "${ECHO_T}no pkg-config" >&6 else echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6 echo "$as_me:$LINENO: checking for GTK+/GLADE development files" >&5 echo $ECHO_N "checking for GTK+/GLADE development files... $ECHO_C" >&6 if pkg-config --atleast-version 2.0 libglade-2.0; then have_glade=yes echo "$as_me:$LINENO: result: yes..." >&5 echo "${ECHO_T}yes..." >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_GLADE 1 _ACEOF GLADE_INCLUDES=`pkg-config --cflags libglade-2.0` GLADE_LIBS=`pkg-config --libs libglade-2.0` else have_glade=no echo "$as_me:$LINENO: result: no gtk+/libglade" >&5 echo "${ECHO_T}no gtk+/libglade" >&6 fi fi # Freetype2 (optional, used in ExultStudio, shapes/fontgen.cc) # Extract the first word of "freetype-config", so it can be a program name with args. set dummy freetype-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_FT2CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $FT2CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_FT2CONFIG="$FT2CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_FT2CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi FT2CONFIG=$ac_cv_path_FT2CONFIG if test -n "$FT2CONFIG"; then echo "$as_me:$LINENO: result: $FT2CONFIG" >&5 echo "${ECHO_T}$FT2CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test -n "$FT2CONFIG"; then cat >>confdefs.h <<\_ACEOF #define HAVE_FREETYPE2 1 _ACEOF FREETYPE2_LIBS=`freetype-config --libs` FREETYPE2_INCLUDES=`freetype-config --cflags` fi # exult-studio # Check whether --enable-exult-studio or --disable-exult-studio was given. if test "${enable_exult_studio+set}" = set; then enableval="$enable_exult_studio" else enable_exult_studio=no fi; echo "$as_me:$LINENO: checking whether to build Exult Studio" >&5 echo $ECHO_N "checking whether to build Exult Studio... $ECHO_C" >&6 if test x$enable_exult_studio = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 if test x$have_glade = xno; then echo "Umm, but we don't have any libglade stuff." echo "Try again, either with libglade, or with --disable-exult-studio" exit 1 fi if true; then BUILD_STUDIO_TRUE= BUILD_STUDIO_FALSE='#' else BUILD_STUDIO_TRUE='#' BUILD_STUDIO_FALSE= fi else if false; then BUILD_STUDIO_TRUE= BUILD_STUDIO_FALSE='#' else BUILD_STUDIO_TRUE='#' BUILD_STUDIO_FALSE= fi echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # GIMP plugin if false; then GIMP_PLUGIN_TRUE= GIMP_PLUGIN_FALSE='#' else GIMP_PLUGIN_TRUE='#' GIMP_PLUGIN_FALSE= fi # Check whether --enable-gimp-plugin or --disable-gimp-plugin was given. if test "${enable_gimp_plugin+set}" = set; then enableval="$enable_gimp_plugin" else enable_gimp_plugin=no fi; echo "$as_me:$LINENO: checking whether to build the GIMP plugin" >&5 echo $ECHO_N "checking whether to build the GIMP plugin... $ECHO_C" >&6 if test x$enable_gimp_plugin = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 echo "$as_me:$LINENO: checking for gimptool" >&5 echo $ECHO_N "checking for gimptool... $ECHO_C" >&6 for ac_prog in gimptool-2.0 gimptool-1.3 gimptool-1.2 gimptool do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_GIMPTOOL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$GIMPTOOL"; then ac_cv_prog_GIMPTOOL="$GIMPTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_GIMPTOOL="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi GIMPTOOL=$ac_cv_prog_GIMPTOOL if test -n "$GIMPTOOL"; then echo "$as_me:$LINENO: result: $GIMPTOOL" >&5 echo "${ECHO_T}$GIMPTOOL" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$GIMPTOOL" && break done if test -z "$GIMPTOOL"; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else echo "$as_me:$LINENO: checking for GIMP version" >&5 echo $ECHO_N "checking for GIMP version... $ECHO_C" >&6 gimp_version=`$GIMPTOOL --version | awk 'BEGIN { FS = "."; } { print $1 * 1000 + $2*100+$3;}'` if test "$gimp_version" -ge 1312; then echo "$as_me:$LINENO: result: found >= 1.3.12" >&5 echo "${ECHO_T}found >= 1.3.12" >&6 if true; then GIMP_PLUGIN_TRUE= GIMP_PLUGIN_FALSE='#' else GIMP_PLUGIN_TRUE='#' GIMP_PLUGIN_FALSE= fi CPPFLAGS="$save_cppflags" GIMP_PLUGIN_PREFIX=`$GIMPTOOL --gimpplugindir` GIMP_PLUGIN_PREFIX="$GIMP_PLUGIN_PREFIX/plug-ins" cat >>confdefs.h <<\_ACEOF #define HAVE_GIMP 1 _ACEOF GIMP_INCLUDES=`$GIMPTOOL --cflags` GIMP_LIBS=`$GIMPTOOL --libs` elif test "$gimp_version" -ge 1200 -a \ "$gimp_version" -lt 1300; then echo "$as_me:$LINENO: result: found 1.2.x" >&5 echo "${ECHO_T}found 1.2.x" >&6 if true; then GIMP_PLUGIN_TRUE= GIMP_PLUGIN_FALSE='#' else GIMP_PLUGIN_TRUE='#' GIMP_PLUGIN_FALSE= fi CPPFLAGS="$save_cppflags" GIMP_PLUGIN_PREFIX=`$GIMPTOOL --gimpplugindir` GIMP_PLUGIN_PREFIX="$GIMP_PLUGIN_PREFIX/plug-ins" cat >>confdefs.h <<\_ACEOF #define HAVE_GIMP 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define HAVE_GIMP_1_2 1 _ACEOF GIMP_INCLUDES=`$GIMPTOOL --cflags` GIMP_LIBS=`$GIMPTOOL --libs` else echo "$as_me:$LINENO: result: found < 1.3.12 - disabling plugin" >&5 echo "${ECHO_T}found < 1.3.12 - disabling plugin" >&6 fi fi else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # ------------------ # Generate output # ------------------ ac_config_files="$ac_config_files exult.spec Info.plist Makefile audio/Makefile audio/midi_drivers/Makefile conf/Makefile files/Makefile files/zip/Makefile gumps/Makefile pathfinder/Makefile flic/Makefile tools/Makefile data/Makefile docs/Makefile desktop/Makefile objs/Makefile imagewin/Makefile shapes/Makefile usecode/Makefile usecode/compiler/Makefile usecode/ucxt/Makefile usecode/ucxt/Docs/Makefile usecode/ucxt/data/Makefile usecode/ucxt/include/Makefile usecode/ucxt/src/Makefile mapedit/Makefile server/Makefile debian/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" # Sed expression to map a string onto a valid variable name. as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.57. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.57, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "exult.spec" ) CONFIG_FILES="$CONFIG_FILES exult.spec" ;; "Info.plist" ) CONFIG_FILES="$CONFIG_FILES Info.plist" ;; "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "audio/Makefile" ) CONFIG_FILES="$CONFIG_FILES audio/Makefile" ;; "audio/midi_drivers/Makefile" ) CONFIG_FILES="$CONFIG_FILES audio/midi_drivers/Makefile" ;; "conf/Makefile" ) CONFIG_FILES="$CONFIG_FILES conf/Makefile" ;; "files/Makefile" ) CONFIG_FILES="$CONFIG_FILES files/Makefile" ;; "files/zip/Makefile" ) CONFIG_FILES="$CONFIG_FILES files/zip/Makefile" ;; "gumps/Makefile" ) CONFIG_FILES="$CONFIG_FILES gumps/Makefile" ;; "pathfinder/Makefile" ) CONFIG_FILES="$CONFIG_FILES pathfinder/Makefile" ;; "flic/Makefile" ) CONFIG_FILES="$CONFIG_FILES flic/Makefile" ;; "tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "data/Makefile" ) CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; "docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "desktop/Makefile" ) CONFIG_FILES="$CONFIG_FILES desktop/Makefile" ;; "objs/Makefile" ) CONFIG_FILES="$CONFIG_FILES objs/Makefile" ;; "imagewin/Makefile" ) CONFIG_FILES="$CONFIG_FILES imagewin/Makefile" ;; "shapes/Makefile" ) CONFIG_FILES="$CONFIG_FILES shapes/Makefile" ;; "usecode/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/Makefile" ;; "usecode/compiler/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/compiler/Makefile" ;; "usecode/ucxt/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/ucxt/Makefile" ;; "usecode/ucxt/Docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/ucxt/Docs/Makefile" ;; "usecode/ucxt/data/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/ucxt/data/Makefile" ;; "usecode/ucxt/include/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/ucxt/include/Makefile" ;; "usecode/ucxt/src/Makefile" ) CONFIG_FILES="$CONFIG_FILES usecode/ucxt/src/Makefile" ;; "mapedit/Makefile" ) CONFIG_FILES="$CONFIG_FILES mapedit/Makefile" ;; "server/Makefile" ) CONFIG_FILES="$CONFIG_FILES server/Makefile" ;; "debian/Makefile" ) CONFIG_FILES="$CONFIG_FILES debian/Makefile" ;; "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@target@,$target,;t t s,@target_cpu@,$target_cpu,;t t s,@target_vendor@,$target_vendor,;t t s,@target_os@,$target_os,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@AMTAR@,$AMTAR,;t t s,@install_sh@,$install_sh,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@DEPDIR@,$DEPDIR,;t t s,@MACOSX_TRUE@,$MACOSX_TRUE,;t t s,@MACOSX_FALSE@,$MACOSX_FALSE,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@CPP@,$CPP,;t t s,@LEX@,$LEX,;t t s,@LEXLIB@,$LEXLIB,;t t s,@LEX_OUTPUT_ROOT@,$LEX_OUTPUT_ROOT,;t t s,@YACC@,$YACC,;t t s,@LEXYACC_TRUE@,$LEXYACC_TRUE,;t t s,@LEXYACC_FALSE@,$LEXYACC_FALSE,;t t s,@CXX@,$CXX,;t t s,@CXXFLAGS@,$CXXFLAGS,;t t s,@ac_ct_CXX@,$ac_ct_CXX,;t t s,@CXXDEPMODE@,$CXXDEPMODE,;t t s,@LN_S@,$LN_S,;t t s,@ECHO@,$ECHO,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@EGREP@,$EGREP,;t t s,@LIBTOOL@,$LIBTOOL,;t t s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t s,@HAVE_PNG_TRUE@,$HAVE_PNG_TRUE,;t t s,@HAVE_PNG_FALSE@,$HAVE_PNG_FALSE,;t t s,@CXXCPP@,$CXXCPP,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@HAVE_SNPRINTF_TRUE@,$HAVE_SNPRINTF_TRUE,;t t s,@HAVE_SNPRINTF_FALSE@,$HAVE_SNPRINTF_FALSE,;t t s,@x_libraries@,$x_libraries,;t t s,@SDL_CONFIG@,$SDL_CONFIG,;t t s,@SDL_CFLAGS@,$SDL_CFLAGS,;t t s,@SDL_LIBS@,$SDL_LIBS,;t t s,@HAVE_TIMIDITY_BIN@,$HAVE_TIMIDITY_BIN,;t t s,@BUILD_TOOLS_TRUE@,$BUILD_TOOLS_TRUE,;t t s,@BUILD_TOOLS_FALSE@,$BUILD_TOOLS_FALSE,;t t s,@BUILD_COMPILER_TRUE@,$BUILD_COMPILER_TRUE,;t t s,@BUILD_COMPILER_FALSE@,$BUILD_COMPILER_FALSE,;t t s,@DATA_FILES_TRUE@,$DATA_FILES_TRUE,;t t s,@DATA_FILES_FALSE@,$DATA_FILES_FALSE,;t t s,@GLADE_INCLUDES@,$GLADE_INCLUDES,;t t s,@GLADE_LIBS@,$GLADE_LIBS,;t t s,@FT2CONFIG@,$FT2CONFIG,;t t s,@FREETYPE2_LIBS@,$FREETYPE2_LIBS,;t t s,@FREETYPE2_INCLUDES@,$FREETYPE2_INCLUDES,;t t s,@BUILD_STUDIO_TRUE@,$BUILD_STUDIO_TRUE,;t t s,@BUILD_STUDIO_FALSE@,$BUILD_STUDIO_FALSE,;t t s,@GIMP_PLUGIN_TRUE@,$GIMP_PLUGIN_TRUE,;t t s,@GIMP_PLUGIN_FALSE@,$GIMP_PLUGIN_FALSE,;t t s,@GIMPTOOL@,$GIMPTOOL,;t t s,@GIMP_PLUGIN_PREFIX@,$GIMP_PLUGIN_PREFIX,;t t s,@GIMP_INCLUDES@,$GIMP_INCLUDES,;t t s,@GIMP_LIBS@,$GIMP_LIBS,;t t s,@WINDOWING_SYSTEM@,$WINDOWING_SYSTEM,;t t s,@KMID_INCLUDES@,$KMID_INCLUDES,;t t s,@KMID_LIBS@,$KMID_LIBS,;t t s,@EXE_TARGET@,$EXE_TARGET,;t t s,@EXULT_DATADIR@,$EXULT_DATADIR,;t t s,@SYSLIBS@,$SYSLIBS,;t t s,@ICON_FILE@,$ICON_FILE,;t t s,@DEBUG_FLAGS@,$DEBUG_FLAGS,;t t s,@ZLIB_LIBS@,$ZLIB_LIBS,;t t s,@OPENGL_LIBS@,$OPENGL_LIBS,;t t s,@WARNINGS@,$WARNINGS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo $f;; *) # Relative if test -f "$f"; then # Build tree echo $f elif test -f "$srcdir/$f"; then # Source tree echo $srcdir/$f else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo $f;; *) # Relative if test -f "$f"; then # Build tree echo $f elif test -f "$srcdir/$f"; then # Source tree echo $srcdir/$f else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi # Run the commands associated with the file. case $ac_file in config.h ) # update the timestamp echo timestamp >"./stamp-h1" ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in default-1 ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do case "$mf" in Makefile|GNUmakefile) dirpart=.;; */Makefile|*/GNUmakefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;; *) continue;; esac grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`echo "$file" | sed -e 's|/[^/]*$||'` $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1 # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi echo echo Exult v$VERSION echo echo SDL ....................... : `$SDL_CONFIG --version` if test x$have_glade = xyes; then echo GLIB ...................... : `pkg-config --modversion glib-2.0` echo GTK+ ...................... : `pkg-config --modversion gtk+-2.0` echo libGlade .................. : `pkg-config --modversion libglade-2.0` echo fi echo Build tools................ : $enable_tools echo Build ExultStudio.......... : $enable_exult_studio echo echo "Now type 'make' to build Exult" exult-1.2/gamerend.cc0000644000175000001440000003520310040664671010272 /* * gamerend.cc - Rendering methods. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #ifndef HAVE_SNPRINTF extern int snprintf(char *, size_t, const char *, /*args*/ ...); namespace std { using ::snprintf; } #else #endif #include "gamewin.h" #include "gamerend.h" #include "gameclk.h" #include "gamemap.h" #include "actors.h" #include "chunks.h" #include "objiter.h" #include "Gump_manager.h" #include "Gump.h" #include "effects.h" #include "cheat.h" #include "drag.h" /* * Paint just the map with given top-left-corner tile. */ void Game_window::paint_map_at_tile ( int x, int y, int w, int h, // Clip to this area. int toptx, int topty, int skip_above // Don't display above this lift. ) { int savescrolltx = scrolltx, savescrollty = scrollty; int saveskip = skip_lift; scrolltx = toptx; scrollty = topty; skip_lift = skip_above; map->read_map_data(); // Gather in all objs., etc. win->set_clip(x, y, w, h); render->paint_map(0, 0, get_width(), get_height()); win->clear_clip(); scrolltx = savescrolltx; scrollty = savescrollty; skip_lift = saveskip; } /* * Figure offsets on screen. */ inline int Figure_screen_offset ( int ch, // Chunk # int scroll // Top/left tile of screen. ) { // Watch for wrapping. int t = ch*c_tiles_per_chunk - scroll; if (t < -c_num_tiles/2) t += c_num_tiles; t %= c_num_tiles; return t*c_tilesize; } /* * Show the outline around a chunk. */ inline void Paint_chunk_outline ( Game_window *gwin, int pixel, // Pixel value to use. int cx, int cy, // Chunk coords. int tnum, // Terrain #. int xoff, int yoff // Where chunk was painted. ) { gwin->get_win()->fill8(pixel, c_chunksize, 1, xoff, yoff); gwin->get_win()->fill8(pixel, 1, c_chunksize, xoff, yoff); char text[40]; // Show chunk #. snprintf(text, sizeof(text), "(%d,%d)T%d", cx, cy, tnum); Shape_manager::get_instance()->paint_text(2, text, xoff + 2, yoff + 2); } /* * Paint tile grid. */ static void Paint_grid ( Game_window *gwin, Xform_palette& xform // For transparency. ) { Image_window8 *win = gwin->get_win(); // Paint grid at edit height. int xtiles = gwin->get_width()/c_tilesize, ytiles = gwin->get_height()/c_tilesize; int lift = cheat.get_edit_lift(); int liftpixels = lift*(c_tilesize/2) + 1; for (int y = 0; y < ytiles; y++) win->fill_translucent8(0, xtiles*c_tilesize, 1, -liftpixels, y*c_tilesize - liftpixels, xform); for (int x = 0; x < xtiles; x++) win->fill_translucent8(0, 1, ytiles*c_tilesize, x*c_tilesize - liftpixels, -liftpixels, xform); } /* * Just paint terrain. This is for terrain_editing mode. */ void Game_render::paint_terrain_only ( int start_chunkx, int start_chunky, int stop_chunkx, int stop_chunky ) { Game_window *gwin = Game_window::get_instance(); Game_map *map = gwin->map; Shape_manager *sman = Shape_manager::get_instance(); int cx, cy; // Chunk #'s. // Paint all the flat scenery. for (cy = start_chunky; cy != stop_chunky; cy = INCR_CHUNK(cy)) { int yoff = Figure_screen_offset(cy, gwin->scrollty); for (cx = start_chunkx; cx != stop_chunkx; cx = INCR_CHUNK(cx)) { int xoff = Figure_screen_offset(cx, gwin->scrolltx); Map_chunk *chunk = map->get_chunk(cx, cy); chunk->get_terrain()->render_all(cx, cy); if (cheat.in_map_editor()) Paint_chunk_outline(gwin, sman->get_special_pixel(HIT_PIXEL), cx, cy, map->get_terrain_num(cx, cy), xoff, yoff); } } // Paint tile grid if desired. if (cheat.show_tile_grid()) Paint_grid(gwin, sman->get_xform(10)); } /* * Paint just the map and its objects (no gumps, effects). * (The caller should set/clear clip area.) * * Output: # light-sources found. */ int Game_render::paint_map ( int x, int y, int w, int h // Rectangle to cover. ) { Game_window *gwin = Game_window::get_instance(); Game_map *map = gwin->map; Shape_manager *sman = gwin->shape_man; render_seq++; // Increment sequence #. gwin->painted = 1; int scrolltx = gwin->scrolltx, scrollty = gwin->scrollty; int light_sources = 0; // Count light sources found. // Get chunks to start with, starting // 1 tile left/above. int start_chunkx = (scrolltx + x/c_tilesize - 1)/c_tiles_per_chunk; // Wrap around. start_chunkx = (start_chunkx + c_num_chunks)%c_num_chunks; int start_chunky = (scrollty + y/c_tilesize - 1)/c_tiles_per_chunk; start_chunky = (start_chunky + c_num_chunks)%c_num_chunks; // End 8 tiles to right. int stop_chunkx = 1 + (scrolltx + (x + w + c_tilesize - 2)/c_tilesize + c_tiles_per_chunk/2)/c_tiles_per_chunk; int stop_chunky = 1 + (scrollty + (y + h + c_tilesize - 2)/c_tilesize + c_tiles_per_chunk/2)/c_tiles_per_chunk; // Wrap around the world: stop_chunkx = (stop_chunkx + c_num_chunks)%c_num_chunks; stop_chunky = (stop_chunky + c_num_chunks)%c_num_chunks; if (!gwin->skip_lift) // Special mode for editing? { paint_terrain_only(start_chunkx, start_chunky, stop_chunkx, stop_chunky); return 10; // Pretend there's lots of light! } int cx, cy; // Chunk #'s. // Paint all the flat scenery. for (cy = start_chunky; cy != stop_chunky; cy = INCR_CHUNK(cy)) { int yoff = Figure_screen_offset(cy, scrollty); for (cx = start_chunkx; cx != stop_chunkx; cx = INCR_CHUNK(cx)) { int xoff = Figure_screen_offset(cx, scrolltx); paint_chunk_flats(cx, cy, xoff, yoff); if (cheat.in_map_editor()) Paint_chunk_outline(gwin, sman->get_special_pixel(HIT_PIXEL), cx, cy, map->get_terrain_num(cx, cy), xoff, yoff); } } // Now the flat RLE terrain. for (cy = start_chunky; cy != stop_chunky; cy = INCR_CHUNK(cy)) { int yoff = Figure_screen_offset(cy, scrollty); for (cx = start_chunkx; cx != stop_chunkx; cx = INCR_CHUNK(cx)) { int xoff = Figure_screen_offset(cx, scrolltx); paint_chunk_flat_rles(cx, cy, xoff, yoff); if (cheat.in_map_editor()) Paint_chunk_outline(gwin, sman->get_special_pixel(HIT_PIXEL), cx, cy, map->get_terrain_num(cx, cy), xoff, yoff); } } // Draw the chunks' objects // diagonally NE. int tmp_stopy = DECR_CHUNK(start_chunky); for (cy = start_chunky; cy != stop_chunky; cy = INCR_CHUNK(cy)) { for (int dx = start_chunkx, dy = cy; dx != stop_chunkx && dy != tmp_stopy; dx = INCR_CHUNK(dx), dy = DECR_CHUNK(dy)) light_sources += paint_chunk_objects(dx, dy); } for (cx = (start_chunkx + 1)%c_num_chunks; cx != stop_chunkx; cx = INCR_CHUNK(cx)) { for (int dx = cx, dy = (stop_chunky - 1 + c_num_chunks)%c_num_chunks; dx != stop_chunkx && dy != tmp_stopy; dx = INCR_CHUNK(dx), dy = DECR_CHUNK(dy)) light_sources += paint_chunk_objects(dx, dy); } /// Dungeon Blackness (but disable in map editor mode) if (gwin->in_dungeon >= gwin->skip_above_actor && !cheat.in_map_editor()) paint_blackness (start_chunkx, start_chunky, stop_chunkx, stop_chunky, gwin->ice_dungeon?73:0); // Outline selected objects. const Game_object_vector& sel = cheat.get_selected(); int render_skip = gwin->get_render_skip_lift(); for (Game_object_vector::const_iterator it = sel.begin(); it != sel.end(); ++it) { Game_object *obj = *it; if (!obj->get_owner() && obj->get_lift() < render_skip) obj->paint_outline(HIT_PIXEL); } // Paint tile grid if desired. if (cheat.in_map_editor() && cheat.show_tile_grid()) Paint_grid(gwin, sman->get_xform(10)); return light_sources; } /* * Paint a rectangle in the window by pulling in vga chunks. */ void Game_window::paint ( int x, int y, int w, int h // Rectangle to cover. ) { if (!win->ready()) return; win->set_clip(x, y, w, h); // Clip to this area. int light_sources = render->paint_map(x, y, w, h); effects->paint(); // Draw sprites. if (gump_man->modal_gump_mode())// Modal gumps? { // Draw text, then gumps. effects->paint_text(); gump_man->paint(); } else { // Draw gumps unless in dont_move mode. if (!main_actor_dont_move()) gump_man->paint(); effects->paint_text(); // Draw text over gumps. } if (dragging) dragging->paint(); // Paint what user is dragging. win->clear_clip(); // Complete repaint? if (!x && !y && w == get_width() && h == get_height() && main_actor) { // Look for lights. Actor *party[9]; // Get party, including Avatar. int cnt = get_party(party, 1); int carried_light = 0; for (int i = 0; !carried_light && i < cnt; i++) carried_light = party[i]->has_light_source(); // Also check light spell. if (special_light && clock->get_total_minutes() >special_light) { // Just expired. special_light = 0; clock->set_palette(); } // Set palette for lights. clock->set_light_source(carried_light + (light_sources > 0), in_dungeon); } } /* * Paint whole window. */ void Game_window::paint() { map->read_map_data(); // Gather in all objs., etc. set_all_dirty(); paint_dirty(); } /* * Paint the flat (non-rle) shapes in a chunk. */ void Game_render::paint_chunk_flats ( int cx, int cy, // Chunk coords (0 - 12*16). int xoff, int yoff // Pixel offset of top-of-screen. ) { Game_window *gwin = Game_window::get_instance(); Map_chunk *olist = gwin->map->get_chunk(cx, cy); // Paint flat tiles. #ifdef HAVE_OPENGL if (GL_manager::get_instance()) // OpenGL rendering? { Chunk_terrain *terrain = olist->get_terrain(); if (terrain) terrain->get_glflats()->paint(xoff, yoff); } else #endif { Image_buffer8 *cflats = olist->get_rendered_flats(); if (cflats) gwin->win->copy8(cflats->get_bits(), c_chunksize, c_chunksize, xoff, yoff); } } /* * Paint the flat RLE (terrain) shapes in a chunk. */ void Game_render::paint_chunk_flat_rles ( int cx, int cy, // Chunk coords (0 - 12*16). int xoff, int yoff // Pixel offset of top-of-screen. ) { Game_window *gwin = Game_window::get_instance(); Map_chunk *olist = gwin->map->get_chunk(cx, cy); Flat_object_iterator next(olist);// Do flat RLE objects. Game_object *obj; while ((obj = next.get_next()) != 0) obj->paint(); } /* * Paint a chunk's objects, left-to-right, top-to-bottom. * * Output: # light sources found. */ int Game_render::paint_chunk_objects ( int cx, int cy // Chunk coords (0 - 12*16). ) { Game_object *obj; Game_window *gwin = Game_window::get_instance(); Map_chunk *olist = gwin->map->get_chunk(cx, cy); int light_sources = // Also check for light sources. gwin->is_in_dungeon() ? olist->get_dungeon_lights() : olist->get_non_dungeon_lights(); skip = gwin->get_render_skip_lift(); Nonflat_object_iterator next(olist); while ((obj = next.get_next()) != 0) if (obj->render_seq != render_seq) paint_object(obj); skip = 31; // Back to a safe #. return light_sources; } /* * Render an object after first rendering any that it depends on. */ void Game_render::paint_object ( Game_object *obj ) { int lift = obj->get_lift(); if (lift >= skip) return; obj->render_seq = render_seq; int cnt = obj->get_dependency_count(); for (int i = 0; i < cnt; i++) { Game_object *dep = obj->get_dependency(i); if (dep && dep->render_seq != render_seq) paint_object(dep); } obj->paint(); // Finally, paint this one. } /* * Paint 'dirty' rectangle. */ void Game_window::paint_dirty() { // Update the gumps before painting, unless in dont_move mode (may change dirty area) if (!main_actor_dont_move()) gump_man->update_gumps(); Rectangle box = clip_to_win(dirty); if (box.w > 0 && box.h > 0) paint(box); // (Could create new dirty rects.) clear_dirty(); } /* * Dungeon Blacking * * This is really simple. If there is a dungeon roof over our head we * black out every tile on screen that doens't have a roof at the height * of the roof that is directly over our head. The tiles are blacked out * at the height of the the roof. * * I've done some simple optimizations. Generally all the blackness will * cover entire chunks. So, instead of drawing each tile individually, I * work out home many tiles in a row that need to be blacked out, and then * black them all out at the same time. */ void Game_render::paint_blackness(int start_chunkx, int start_chunky, int stop_chunkx, int stop_chunky, int index) { Game_window *gwin = Game_window::get_instance(); // Calculate the offset due to the lift (4x the lift). const int off = gwin->in_dungeon << 2; // For each chunk that might be renderable for (int cy = start_chunky; cy != stop_chunky; cy = INCR_CHUNK(cy)) { for (int cx = start_chunkx; cx != stop_chunkx; cx = INCR_CHUNK(cx)) { // Coord of the left edge const int xoff = Figure_screen_offset(cx, gwin->scrolltx) - off; // Coord of the top edge int y = Figure_screen_offset(cy, gwin->scrollty) - off; // Need the chunk cache (needs to be setup!) Map_chunk *mc = gwin->map->get_chunk(cx, cy); if (!mc->has_dungeon()) { gwin->win->fill8(index, c_tilesize*c_tiles_per_chunk, c_tilesize*c_tiles_per_chunk, xoff, y); continue; } // For each line in the chunk for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++) { // Start and width of the area to black out int x = xoff; int w = 0; // For each tile in the line for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++) { // If the tile is blocked by 'roof' if (!mc->is_dungeon(tilex, tiley)) { // Add to the width of the area w += c_tilesize; } // If not blocked and have area, else if (w) { // Draw blackness gwin->win->fill8(index, w, c_tilesize, x, y); // Set the start of the area to the next tile x += w + c_tilesize; // Clear the width w = 0; } // Not blocked, and no area else { // Increment the start of the area to the next tile x += c_tilesize; } } // If we have an area, paint it. if (w) gwin->win->fill8(index, w, c_tilesize, x, y); // Increment the y coord for the next line y += c_tilesize; } } } } exult-1.2/alpha_kludges.h0000755000175000001440000000433407241106536011161 /* * alpha_kludges.h Copyright (C) 2000 The Exult Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* System-specific kludges */ /* OK, right now AXP-Linux-cxx specific kludges only */ #ifndef ALPHA_KLUDGES_H #define ALPHA_KLUDGES_H #ifndef HAVE_HASH_MAP # define DONT_HAVE_HASH_MAP #endif #ifndef HAVE_HASH_SET # define DONT_HAVE_HASH_SET #endif /*------------------------*/ /* DEC cxx on Alpha/Linux */ /*------------------------*/ #if defined(__DECCXX) && defined(__linux__) #undef HAVE_HASH_MAP #undef HAVE_HASH_SET #undef DONT_HAVE_HASH_MAP #undef DONT_HAVE_HASH_SET #define DONT_HAVE_HASH_SET #define DONT_HAVE_HASH_MAP namespace std { #include } typedef std::size_t size_t; namespace std { #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include } #include #include #include using std::FILE; //using std::iostream; #include #include namespace std{ using ::ostream; using ::istream; using ::ofstream; using ::ifstream; using ::cout; using ::cin; using ::cerr; using ::clog; using ::endl; using ::ios; using ::vector; using ::dec; using ::hex; using ::setfill; using ::setw; }; //using std::strcmp; //using std::FILE; #else #error "alpha_kludges.h should not have been included!" #endif /* !__DECCXX && Linux*/ #endif /* !ALPHA_KLUDGES_H */ exult-1.2/exult_constants.h0000644000175000001440000000620707724430450011612 /* * exult_constants.h - Some constants/macros that are used all over the code. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EXULT_CONSTANTS_H #define EXULT_CONSTANTS_H #include /* * Sizes: */ const int c_tilesize = 8; // A tile (shape) is 8x8 pixels. const int c_tiles_per_chunk = 16; // A chunk is 16x16 tiles. const int c_chunksize = 16 * 8; // A chunk has 16 8x8 shapes. const int c_num_schunks = 12; const int c_num_chunks = 12*16; // Total # of chunks in each dir. const int c_chunks_per_schunk = 16; // # chunks in each superchunk. const int c_tiles_per_schunk = 16*16; // # tiles in each superchunk. // Total # tiles in each dir.: const int c_num_tiles = c_tiles_per_chunk*c_num_chunks; const int c_fade_in_time = 30; // Time for fade in const int c_fade_out_time = 30; // Time for fade out const int c_std_delay = 200; // Standard animation delay. May want to // make this settable! const int c_any_shapenum = -359; const int c_any_qual = -359; const int c_any_framenum = -359; /* * Empty string */ extern const std::string c_empty_string; #define MOVE_NODROP (1<<3) #define MOVE_FLY (1<<4) #define MOVE_LEVITATE (MOVE_FLY|MOVE_NODROP) #define MOVE_WALK (1<<5) #define MOVE_SWIM (1<<6) #define MOVE_ALL_TERRAIN ((1<<5)|(1<<6)) #define MOVE_ETHEREAL (1<<7) #define MOVE_ALL (MOVE_FLY|MOVE_WALK|MOVE_SWIM|MOVE_ETHEREAL) #define MOVE_MAPEDIT (1<<8) // Wrapping: #define INCR_CHUNK(x) (((x) + 1)%c_num_chunks) #define DECR_CHUNK(x) (((x) - 1 + c_num_chunks)%c_num_chunks) #define INCR_TILE(x) (((x) + 1)%c_num_tiles) inline int DECR_TILE(int x, int amt = 1) { return (x - amt + c_num_tiles)%c_num_tiles; } // Return x - y with wrapping. inline int SUB_TILE(int x, int y) { int delta = x - y; return delta < -c_num_tiles/2 ? delta + c_num_tiles : delta >= c_num_tiles/2 ? delta - c_num_tiles : delta; } // Debug #ifdef DEBUG # define COUT(x) do { std::cout << x << std::endl; std::cout.flush(); } while (0) # define CERR(x) do { std::cerr << x << std::endl; std::cerr.flush(); } while (0) #else # define COUT(x) do { } while(0) # define CERR(x) do { } while(0) #endif // Two very useful macros that one should use instead of pure delete; they will additionally // set the old object pointer to 0, thus helping prevent double deletes (not that "delete 0" // is a no-op. #define FORGET_OBJECT(x) do { delete x; x = 0; } while(0) #define FORGET_ARRAY(x) do { delete [] x; x = 0; } while(0) #endif exult-1.2/lists.h0000644000175000001440000000443007724430450007507 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LISTS_H_ #define _LISTS_H_ // TODO: merge lists.h and vec.h into one file?! #include #include "exceptions.h" class Actor; template class Exult_queue { public: typedef typename std::list::size_type size_type; typedef typename std::list::const_iterator const_iterator; protected: std::list data; public: // exception class for illegal operations on an empty queue class empty_queue_exception : public exult_exception { public: empty_queue_exception () : exult_exception("attempt to read an empty queue") { } }; // number of elements size_type size() const { return data.size(); } // queue empty? bool empty() const { return data.empty(); } // insert element into the queue void push (const T& obj) { data.push_back(obj); } // insert element at the front of the queue void push_front (const T& obj) { data.push_front(obj); } // pop element out of the queue and return its value T pop () { if (data.empty()) throw empty_queue_exception(); T obj(data.front()); data.pop_front(); return obj; } // return value of next element T& front () { if (data.empty()) throw empty_queue_exception(); return data.back(); } // remove an element from the queue void remove(const T& obj) { data.remove(obj); } // clear the queue void clear() { data.clear(); } // iterators: const_iterator begin() const { return data.begin(); } const_iterator end() const { return data.end(); } }; typedef Exult_queue Actor_queue; #endif exult-1.2/tqueue.cc0000644000175000001440000001316207724430450010021 /* * tqueue.cc - A queue of time-based events for animation. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "tqueue.h" #include #include /* * Be sure no copies are still in queue when deleted. */ Time_sensitive::~Time_sensitive ( ) { #if 0 /*+++++++For finding bugs. */ if (queue_cnt > 0) { char *p = 0; char c = *p; // Force crash. } #endif } /* * Remove all entries. */ void Time_queue::clear ( ) { Temporal_sequence::iterator it; while ((it=data.begin()) != data.end()) { Queue_entry ent = *it; Time_sensitive *obj = ent.handler; data.erase(it); obj->queue_cnt--; } } /* * Add an entry to the queue. */ void Time_queue::add ( uint32 t, // When entry is to be activated. Time_sensitive *obj, // Object to be added. long ud // User data. ) { obj->queue_cnt++; // It's going in, no matter what. Queue_entry newent; if (paused && !obj->always) // Paused? // Messy, but we need to fix time. t -= SDL_GetTicks() - pause_time; newent.set(t,obj,ud); if(!data.size()) { data.push_back(newent); return; } for(Temporal_sequence::iterator it=data.begin(); it!=data.end(); ++it) { if(newent<*it) { data.insert(it,newent); return; } } data.push_back(newent); } bool operator <(const Queue_entry &q1,const Queue_entry &q2) { if(q1.timehandler==obj) { obj->queue_cnt--; data.erase(it); return 1; } } return (0); // Not found. } /* * Remove first entry containing a given object and data. * * Output: 1 if found, else 0. */ int Time_queue::remove ( Time_sensitive *obj, long udata ) { if(data.size()==0) return 0; for(Temporal_sequence::iterator it=data.begin(); it!=data.end(); ++it) { if(it->handler==obj && it->udata == udata) { obj->queue_cnt--; data.erase(it); return 1; } } return (0); // Not found. } /* * See if a given entry is in the queue. * * Output: 1 if found, else 0. */ int Time_queue::find ( Time_sensitive *obj ) { if(data.size()==0) return 0; for(Temporal_sequence::iterator it=data.begin(); it!=data.end(); ++it) { if(it->handler==obj) return 1; } return 0; } /* * Find when an entry is due. * * Output: delay in msecs. when due, or -1 if not in queue. */ long Time_queue::find_delay ( Time_sensitive *obj, uint32 curtime ) { if(data.size()==0) return -1; for(Temporal_sequence::iterator it=data.begin(); it!=data.end(); ++it) { if(it->handler==obj) { if (pause_time) // Watch for case when paused. curtime = pause_time; long delay = it->time - curtime; return delay >= 0 ? delay : 0; } } return -1; } /* * Remove & activate entries that are due, starting with head (already * known to be due). */ void Time_queue::activate0 ( uint32 curtime // Current time. ) { if(data.size()==0) return; Queue_entry ent; do { ent=data.front(); Time_sensitive *obj = ent.handler; long udata = ent.udata; data.pop_front(); // Remove from chain. obj->queue_cnt--; obj->handle_event(curtime, udata); } while (data.size() && !(curtime < data.front().time)); } /* * Remove & activate entries marked 'always'. This is called when * the queue is paused. */ void Time_queue::activate_always ( uint32 curtime // Current time. ) { if(data.size()==0) return; Queue_entry ent; for(Temporal_sequence::iterator it=data.begin(); it!=data.end() && !(curtime < (*it).time); ) { Temporal_sequence::iterator next = it; ++next; // Get ->next in case we erase. ent = *it; Time_sensitive *obj = ent.handler; if (obj->always) { obj->queue_cnt--; long udata = ent.udata; data.erase(it); obj->handle_event(curtime, udata); } it = next; } } /* * Resume after a pause. */ void Time_queue::resume ( uint32 curtime ) { if (!paused || --paused > 0) // Only unpause when stack empty. return; // Not paused. int diff = curtime - pause_time; pause_time = 0; if (diff < 0) // Should not happen. return; for(Temporal_sequence::iterator it=data.begin(); it!=data.end(); ++it) { if (!(*it).handler->always) it->time += diff; // Push entries ahead. } } /* * Get next element in queue. */ int Time_queue_iterator::operator() ( Time_sensitive *& obj, // Main object. long& data // Data that was added with it. ) { while (iter != tqueue->data.end() && this_obj && (*iter).handler != this_obj) ++iter; if (iter == tqueue->data.end()) return (0); obj = (*iter).handler; // Return fields. data = (*iter).udata; ++iter; // On to the next. return (1); } exult-1.2/npctime.cc0000644000175000001440000002511210054030531010130 /* * Npctime.cc - Timed-even handlers for NPC's. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "npctime.h" #include "gamewin.h" #include "gameclk.h" #include "actors.h" #include "items.h" #include "schedule.h" #include "game.h" #ifndef UNDER_CE using std::rand; #endif extern bool god_mode; /* * Base class for keeping track of things like poison, protection, hunger. */ class Npc_timer : public Time_sensitive, public Game_singletons { protected: Npc_timer_list *list; // Where NPC stores ->this. uint32 get_minute(); // Get game minutes. public: Npc_timer(Npc_timer_list *l, int start_delay = 0); virtual ~Npc_timer(); }; /* * Handle starvation. */ class Npc_hunger_timer : public Npc_timer { uint32 last_time; // Last game minute when penalized. public: Npc_hunger_timer(Npc_timer_list *l) : Npc_timer(l, 5000) { last_time = get_minute(); } virtual ~Npc_hunger_timer(); // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Handle poison. */ class Npc_poison_timer : public Npc_timer { uint32 end_time; // Time when it wears off. public: Npc_poison_timer(Npc_timer_list *l); virtual ~Npc_poison_timer(); // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Handle sleep. */ class Npc_sleep_timer : public Npc_timer { uint32 end_time; // Time when it wears off. public: Npc_sleep_timer(Npc_timer_list *l) : Npc_timer(l) { // Lasts 5-10 seconds.. end_time = Game::get_ticks() + 5000 + rand()%5000; } virtual ~Npc_sleep_timer() { list->sleep = 0; } // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Invisibility timer. */ class Npc_invisibility_timer : public Npc_timer { uint32 end_time; // Time when it wears off. public: Npc_invisibility_timer(Npc_timer_list *l) : Npc_timer(l) { // Lasts 60-80 seconds.. end_time = Game::get_ticks() + 60000 + rand()%20000; } virtual ~Npc_invisibility_timer() { list->invisibility = 0; } // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Protection timer. */ class Npc_protection_timer : public Npc_timer { uint32 end_time; // Time when it wears off. public: Npc_protection_timer(Npc_timer_list *l) : Npc_timer(l) { // Lasts 60-80 seconds.. end_time = Game::get_ticks() + 60000 + rand()%20000; } virtual ~Npc_protection_timer() { list->protection = 0; } // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Timer for flags that don't need any other checks. */ class Npc_flag_timer : public Npc_timer { int flag; // Flag # in Obj_flags. uint32 end_time; // Time when it wears off. Npc_flag_timer **listloc; // Where it's stored in Npc_timer_list. public: Npc_flag_timer(Npc_timer_list *l, int f, Npc_flag_timer **loc) : Npc_timer(l), flag(f), listloc(loc) { // Lasts 60-120 seconds.. end_time = Game::get_ticks() + 60000 + rand()%60000; } virtual ~Npc_flag_timer() { *listloc = 0; } // Handle events: void handle_event(unsigned long curtime, long udata); }; /* * Delete list. */ Npc_timer_list::~Npc_timer_list ( ) { delete hunger; delete poison; delete sleep; delete invisibility; delete protection; delete might; delete curse; delete paralyze; } /* * Start hunger (if not already there). */ void Npc_timer_list::start_hunger ( ) { if (!hunger) // Not already there? hunger = new Npc_hunger_timer(this); } /* * Start poison. */ void Npc_timer_list::start_poison ( ) { if (poison) // Remove old one. delete poison; poison = new Npc_poison_timer(this); } /* * Start sleep. */ void Npc_timer_list::start_sleep ( ) { if (sleep) // Remove old one. delete sleep; sleep = new Npc_sleep_timer(this); } /* * Start invisibility. */ void Npc_timer_list::start_invisibility ( ) { if (invisibility) // Remove old one. delete invisibility; invisibility = new Npc_invisibility_timer(this); } /* * Start protection. */ void Npc_timer_list::start_protection ( ) { if (protection) // Remove old one. delete protection; protection = new Npc_protection_timer(this); } /* * Start might. */ void Npc_timer_list::start_might ( ) { if (might) // Remove old one. delete might; might = new Npc_flag_timer(this, Obj_flags::might, &might); } /* * Start curse. */ void Npc_timer_list::start_curse ( ) { if (curse) // Remove old one. delete curse; curse = new Npc_flag_timer(this, Obj_flags::cursed, &curse); } /* * Start paralyze. */ void Npc_timer_list::start_paralyze ( ) { if (paralyze) // Remove old one. delete paralyze; paralyze = new Npc_flag_timer(this, Obj_flags::paralyzed, ¶lyze); } /* * Get game minute from start. */ uint32 Npc_timer::get_minute ( ) { Game_window *gwin = Game_window::get_instance(); return 60*gclock->get_total_hours() + gclock->get_minute(); } /* * Start timer. */ Npc_timer::Npc_timer ( Npc_timer_list *l, int start_delay // Time in msecs. before starting. ) : list(l) { gwin->get_tqueue()->add(Game::get_ticks() + start_delay, this, 0L); } /* * Be sure we're no longer in the time queue. */ Npc_timer::~Npc_timer ( ) { if (in_queue()) { Time_queue *tq = Game_window::get_instance()->get_tqueue(); tq->remove(this); } } /* * Done with hunger timer. */ Npc_hunger_timer::~Npc_hunger_timer ( ) { list->hunger = 0; } /* * Time to penalize for hunger. */ void Npc_hunger_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; // No longer a party member? if (!npc->is_in_party() || // or no longer hungry? npc->get_property(static_cast(Actor::food_level)) >= 0 || npc->is_dead()) // Obviously. { delete this; return; } uint32 minute = get_minute(); // Once/hour. if (minute >= last_time + 60) { int hp = rand()%3; if (rand()%4) npc->say(first_starving, first_starving + 2); npc->reduce_health(hp); // npc->set_property(static_cast(Actor::health), // npc->get_property(static_cast(Actor::health)) - hp); last_time = minute; } gwin->get_tqueue()->add(curtime + 30000, this, 0L); } /* * Initialize poison timer. */ Npc_poison_timer::Npc_poison_timer ( Npc_timer_list *l ) : Npc_timer(l, 5000) { // Lasts 1-3 minutes. end_time = Game::get_ticks() + 60000 + rand()%120000; } /* * Done with poison timer. */ Npc_poison_timer::~Npc_poison_timer ( ) { list->poison = 0; } /* * Time to penalize for poison, or see if it's worn off. */ void Npc_poison_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; if (curtime >= end_time || // Long enough? Or cured? npc->get_flag(Obj_flags::poisoned) == 0 || npc->is_dead()) // Obviously. { npc->clear_flag(Obj_flags::poisoned); delete this; return; } int penalty = rand()%3; npc->reduce_health(penalty); // npc->set_property(static_cast(Actor::health), // npc->get_property(static_cast(Actor::health)) - penalty); // Check again in 10-20 secs. gwin->get_tqueue()->add(curtime + 10000 + rand()%10000, this, 0L); } /* * Time to see if we should wake up. */ void Npc_sleep_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; if (curtime >= end_time || // Long enough? Or cured? npc->get_flag(Obj_flags::asleep) == 0) { // Avoid waking Penumbra. if (npc->get_schedule_type() != Schedule::sleep && !npc->is_dead()) // Don't wake the dead. { npc->clear_flag(Obj_flags::asleep); int frnum = npc->get_framenum(); if ((frnum&0xf) == Actor::sleep_frame && // Slimes don't change. !npc->get_info().has_strange_movement()) // Stand up. npc->change_frame( Actor::standing | (frnum&0x30)); } delete this; return; } // Check again in 2 secs. gwin->get_tqueue()->add(curtime + 2000, this, 0L); } /* * Check for a given ring. */ inline int Wearing_ring ( Actor *actor, int shnum, // Ring shape to look for. int frnum ) { // See if wearing ring. Game_object *ring = actor->get_readied(Actor::lfinger); if (ring && ring->get_shapenum() == shnum && ring->get_framenum() == frnum) return 1; ring = actor->get_readied(Actor::rfinger); if (ring && ring->get_shapenum() == shnum && ring->get_framenum() == frnum) return 1; return 0; } /* * See if invisibility wore off. */ void Npc_invisibility_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; if (Wearing_ring(npc, 296, 0)) // (Works for SI and BG.) { // Wearing invisibility ring. delete this; // Don't need timer. return; } if (curtime >= end_time || // Long enough? Or cleared. npc->get_flag(Obj_flags::invisible) == 0) { npc->clear_flag(Obj_flags::invisible); if (!npc->is_dead()) gwin->add_dirty(npc); delete this; return; } // Check again in 2 secs. gwin->get_tqueue()->add(curtime + 2000, this, 0L); } /* * See if protection wore off. */ void Npc_protection_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; if (Wearing_ring(npc, 297, 0)) // ++++SI has an Amulet. { // Wearing protection ring. delete this; // Don't need timer. return; } if (curtime >= end_time || // Long enough? Or cleared. npc->get_flag(Obj_flags::protection) == 0) { npc->clear_flag(Obj_flags::protection); if (!npc->is_dead()) gwin->add_dirty(npc); delete this; return; } // Check again in 2 secs. gwin->get_tqueue()->add(curtime + 2000, this, 0L); } /* * Might/curse/paralyze wore off. */ void Npc_flag_timer::handle_event ( unsigned long curtime, long udata ) { Actor *npc = list->npc; if (curtime >= end_time || // Long enough? Or cleared. npc->get_flag(flag) == 0) { npc->clear_flag(flag); delete this; } else // Check again in 10 secs. gwin->get_tqueue()->add(curtime + 10000, this, 0L); } exult-1.2/mapedit/0000777000175000001440000000000010062225335007677 5exult-1.2/mapedit/TODO0000644000175000001440000000245607432413731010320 ExultStudio TODO ================ ======Feb. 7, 2002 (jsf):========= ExultStudio creates most of the .dat files now, but it (or other tools) still need to create the following in 'static': FACES.VGA GUMPS.VGA PAPERDOL.VGA SHAPES.VGA XFORM.TBL FONT0000.VGA POINTERS.SHP SPRITES.VGA FONTS.VGA TEXT.FLX =========================== This is a braindump of what I want to do with ExultStudio. I think the app should behave in a similar way to the Gimp, with a master window and additional windows for each aspect that is being browsed/modified. The Toolbar =========== The first step in getting ExultStudio into a useful state is to create a "super browser" of sorts. Point it at the game's "static" directory and it will classify all the files it finds there in a list. Clicking on a file brings up a specific browser for that file's type. The following browsers should be designed: Shape Palette NPC IFIX Usecode Chunk Superchunk Map Flex Flic Voc MIDI Weapon Shape ===== Handles: .shp .vga Drag to: Chunks, Flex, GIMP Drop from: Flex Palette ======= Handles: .pal Drag to: Shape Drop from: Flex Chunk ===== Handles: u7chunk Drag to: N/A Drop from: Shape Flex ==== Handles: .flx Drag to: All Drop from: All MIDI ==== Handles: .mid, .xmi Drag to: Flex Drop from: Flex ecc... exult-1.2/mapedit/paledit.h0000644000175000001440000000740707474062453011433 /** ** A GTK widget showing a palette's colors. ** ** Written: 12/24/2000 - JSF **/ #ifndef INCL_PALEDIT #define INCL_PALEDIT 1 /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "objbrowse.h" #include "rect.h" #include class Flex_file_info; class U7object; /* * Show a palette. */ class Palette_edit: public Object_browser { Flex_file_info *flex_info; // Where file data is stored. guchar *image; // Holds data to render. int width, height; // Dimensions of image. GtkWidget *draw; // GTK draw area to display them in. GdkGC *drawgc; // For drawing in 'draw'. std::vector palettes; // The palettes to display. int cur_pal; // Index of current palette. GtkColorSelectionDialog *colorsel;// Open color selector. GtkWidget *sbar; // Status bar. GtkWidget *pspin; // Spin button for palette #. GtkAdjustment *palnum_adj; // For palette #. guint sbar_sel; // Status bar context for selection. Rectangle selected_box; // Location of selected color. GtkWidget *insert_btn, *remove_btn, *up_btn, *down_btn; // Blit onto screen. virtual void show(int x, int y, int w, int h); virtual void show() { Palette_edit::show(0, 0, draw->allocation.width, draw->allocation.height);} void select(int new_sel); // Show new selection. virtual void load(); // Load from file data. virtual void render(); // Draw list. // Handle color-selector buttons. static int color_closed(GtkWidget *widget, GdkEvent *event, gpointer data); static void color_cancel(GtkWidget *widget, gpointer data); static void color_okay(GtkWidget *widget, gpointer data); void double_clicked(); // Handle double-click on a color. GtkWidget *create_controls(); // Controls at bottom of browser. void enable_controls(); // Enable/disable controls after sel. // has changed. void setup(); // Setup box. void new_palette(); // Create new palette. void update_flex(int pnum); // Update flex_info data. public: Palette_edit(Flex_file_info *flinfo); ~Palette_edit(); void show_palette(int palnum); // Show desired palette. // Turn off selection. void unselect(bool need_render = true); void move_palette(bool up); void add_palette(); void remove_palette(); // Configure when created/resized. static gint configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data); // Blit to screen. static gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); // Handle mouse press. static gint mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data); // Give dragged palette. static void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, gpointer data); // Someone else selected. static gint selection_clear(GtkWidget *widget, GdkEventSelection *event, gpointer data); static gint drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); static void palnum_changed(GtkAdjustment *adj, gpointer data); static void export_palette(char *fname, gpointer user_data); static void import_palette(char *fname, gpointer user_data); }; #endif exult-1.2/mapedit/combo.h0000644000175000001440000001562007713365507011106 /** ** Combo.h - A combination of multiple objects. ** ** Written: 4/26/02 - JSF **/ #ifndef INCL_COMBO_H #define INCL_COMBO_H 1 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "objbrowse.h" #include "shapedraw.h" #include "rect.h" class Shapes_vga_file; class Flex_file_info; /* * A single object: */ class Combo_member { short tx, ty, tz; // Location (tile) rel. to top-left. short shapenum, framenum; // Object in shapes.vga. public: friend class Combo; friend class Combo_editor; friend class Combo_chooser; Combo_member(short x, short y, short z, short sh, short fr) : tx(x), ty(y), tz(z), shapenum(sh), framenum(fr) { } // Return which makes better hot-spot. friend int hot_spot_compare(Combo_member& c0, Combo_member& c1); }; /* * A combination of objects. */ class Combo { Shapes_vga_file *shapes_file; // Where shapes come from. std::vector members; // Members of this combination. short hot_index; // Index of obj. whose 'hot spot' we'll // use. short starttx, startty; // Offset represented by top-left. std::string name; // Name given by user. Rectangle tilefoot; // Footprint in tiles. // Get footprint of given member. Rectangle get_member_footprint(int i); public: friend class Combo_editor; friend class Combo_chooser; Combo(Shapes_vga_file *svga); Combo(const Combo& c2); // Copy. ~Combo(); Combo_member *get(int i) { return i >= 0 && i < members.size() ? members[i] : 0; } // Add a new object. void add(int tx, int ty, int tz, int shnum, int frnum); void remove(int i); // Remove object #i. // Paint shapes in drawing area. void draw(Shape_draw *draw, int selected = -1, int xoff = 0, int yoff = 0); int find(int mx, int my); // Find at mouse position. // Serialize: unsigned char *write(int& datalen); unsigned char *read(unsigned char *buf, int bufsize); }; /* * The 'combo editor' window: */ class Combo_editor : public Shape_draw { GtkWidget *win; // Main window. Combo *combo; // Combo being edited. int selected; // Index of selected item in combo. bool setting_controls; // To avoid callbacks when setting. int file_index; // Entry # in 'combos.flx', or -1 if // new. // Set to edit existing combo. void set_combo(Combo *newcombo, int findex); public: friend class Combo_chooser; Combo_editor(Shapes_vga_file *svga, unsigned char *palbuf); ~Combo_editor(); void show(bool tf); // Show/hide. void render(GdkRectangle *area = 0); void set_controls(); // Set controls to selected entry. // Handle mouse. gint mouse_press(GdkEventButton *event); void set_order(); // Set selected to desired order. void set_position(); // Set selected to desired position. // Add object/shape picked from Exult. void add(unsigned char *data, int datalen); void remove(); // Remove selected. void save(); // Save it. bool is_visible() { return GTK_WIDGET_VISIBLE(win); } }; /********************************************************************** * Below are classes for the combo-browser. **********************************************************************/ /* * Store information about an individual combo shown in the list. */ class Combo_info { friend class Combo_chooser; int num; Rectangle box; // Box where drawn. Combo_info() { } void set(int n, int rx, int ry, int rw, int rh) { num = n; box = Rectangle(rx, ry, rw, rh); } }; /* * This class manages the list of combos. */ class Combo_chooser: public Object_browser, public Shape_draw { Flex_file_info *flex_info; // Where file data is stored. std::vector combos; // List of all combination-objects. GtkWidget *sbar; // Status bar. guint sbar_sel; // Status bar context for selection. int index0; // Index (combo) # of leftmost in // displayed list. Combo_info *info; // An entry for each combo drawn. int info_cnt; // # entries in info. void (*sel_changed)(); // Called when selection changes. // Blit onto screen. virtual void show(int x, int y, int w, int h); virtual void show() { Combo_chooser::show(0, 0, draw->allocation.width, draw->allocation.height);} void select(int new_sel); // Show new selection. virtual void load(); // Load from file data. virtual void render(); // Draw list. virtual void set_background_color(guint32 c) { Shape_draw::set_background_color(c); } virtual int get_selected_id() { return selected < 0 ? -1 : info[selected].num; } void scroll(int newindex); // Scroll. void scroll(bool upwards); void enable_controls(); // Enable/disable controls after sel. // has changed. public: Combo_chooser(Vga_file *i, Flex_file_info *flinfo, unsigned char *palbuf, int w, int h, Shape_group *g = 0); virtual ~Combo_chooser(); // Turn off selection. void unselect(bool need_render = true); int is_selected() // Is a combo selected? { return selected >= 0; } void set_selected_callback(void (*fun)()) { sel_changed = fun; } int get_count(); // Get # to show. int add(Combo *newcombo, int index); // Add new combo. void remove(); // Remove selected. void edit(); // Edit selected. // Configure when created/resized. static gint configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data); // Blit to screen. static gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); // Handle mouse press. static gint mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data); // Give dragged combo. static void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, gpointer data); // Someone else selected. static gint selection_clear(GtkWidget *widget, GdkEventSelection *event, gpointer data); static gint drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); // Handle scrollbar. static void scrolled(GtkAdjustment *adj, gpointer data); virtual void move(bool upwards);// Move current selected combo. virtual void search(const char *srch, int dir); #ifdef WIN32 static gint win32_drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #else static gint drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #endif }; #endif /* INCL_COMBO_H */ exult-1.2/mapedit/shapeedit.cc0000644000175000001440000007034010040666305012076 /** ** Shapeedit.cc - Shape-editing methods. ** ** Written: 6/8/01 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "studio.h" #include "servemsg.h" #include "exult_constants.h" #include "utils.h" #include "shapeinf.h" #include "monstinf.h" #include "u7drag.h" #include "shapefile.h" #include "shapedraw.h" using std::cout; using std::endl; /* * Widgets in one row of the 'equipment' dialog: */ struct Equip_row_widgets { Shape_draw *draw; // Where the shape is drawn. GtkWidget *shape, *name, *chance, *count; }; // Holds widgets from equip. dialog. static Equip_row_widgets equip_rows[10] = {0}; /* * Equip window's Okay, Apply buttons. */ C_EXPORT void on_equip_okay_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_equip_window(); ExultStudio::get_instance()->close_equip_window(); } C_EXPORT void on_equip_apply_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_equip_window(); } /* * Equip window's Cancel button. */ C_EXPORT void on_equip_cancel_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->close_equip_window(); } /* * Equip window's close button. */ C_EXPORT gboolean on_equip_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_equip_window(); return TRUE; } /* * Record # changed, so update what's displayed. */ C_EXPORT gboolean on_equip_recnum_changed ( GtkWidget *widget, gpointer user_data ) { int recnum = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(widget)); ExultStudio::get_instance()->init_equip_window(recnum); return TRUE; } /* * Draw shape in one of the Equip dialog rows. */ C_EXPORT gboolean on_equip_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->row. ) { ExultStudio::get_instance()->show_equip_shape( (Equip_row_widgets *) data, event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Shape # on one of the rows was changed. */ C_EXPORT gboolean on_equip_shape_changed ( GtkWidget *widget, gpointer data // ->row info. ) { Equip_row_widgets *eq = (Equip_row_widgets *) data; ExultStudio *studio = ExultStudio::get_instance(); studio->show_equip_shape(eq); int shape = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(eq->shape)); const char *nm = studio->get_shape_name(shape); gtk_label_set_text(GTK_LABEL(eq->name), nm ? nm : ""); return (TRUE); } /* * Callback for when a shape is dropped on one of the Equip draw areas. */ static void Equip_shape_dropped ( int file, // U7_SHAPE_SHAPES. int shape, int frame, void *udata // ->row. ) { Equip_row_widgets *eq = (Equip_row_widgets *) udata; if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024) { // Set shape #. gtk_spin_button_set_value(GTK_SPIN_BUTTON(eq->shape), shape); } } /* * Set up 'equipment' dialog's table, which has 10 identical rows. */ static void Setup_equip ( GtkTable *table, // Table to fill. Vga_file *vgafile, // Shapes. unsigned char *palbuf, // Palette for drawing shapes. Equip_row_widgets rows[10] // Filled in. ) { gtk_table_resize(table, 12, 17); gtk_widget_show (GTK_WIDGET(table)); // Labels at top: GtkWidget *label = gtk_label_new ("Shape"); gtk_widget_show (label); gtk_table_attach (table, label, 0, 3, 0, 1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); label = gtk_label_new ("Chance (%)"); gtk_widget_show (label); gtk_table_attach (table, label, 4, 5, 0, 1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); label = gtk_label_new ("Count"); gtk_widget_show (label); gtk_table_attach (table, label, 6, 7, 0, 1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); // Separators: GtkWidget *vsep = gtk_vseparator_new (); gtk_widget_show (vsep); gtk_table_attach (table, vsep, 3, 4, 0, 12, (GtkAttachOptions) (0), (GtkAttachOptions) (GTK_FILL), 2, 0); vsep = gtk_vseparator_new (); gtk_widget_show (vsep); gtk_table_attach (table, vsep, 5, 6, 0, 12, (GtkAttachOptions) (0), (GtkAttachOptions) (GTK_FILL), 2, 0); GtkWidget *hsep = gtk_hseparator_new (); gtk_widget_show (hsep); gtk_table_attach (table, hsep, 0, 7, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); // Create the rows. for (int row = 0; row < 10; row++) { // Create frame, shape drawing area. GtkWidget *frame = gtk_frame_new (NULL); gtk_widget_show (frame); gtk_table_attach (table, frame, 0, 1, row + 2, row + 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 3, 0); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); GtkWidget *drawingarea = gtk_drawing_area_new (); gtk_widget_show (drawingarea); gtk_container_add (GTK_CONTAINER(frame), drawingarea); gtk_widget_set_usize (drawingarea, 20, 40); if (vgafile && palbuf) { rows[row].draw = new Shape_draw(vgafile, palbuf, drawingarea); gtk_signal_connect(GTK_OBJECT(drawingarea), "expose-event", GTK_SIGNAL_FUNC(on_equip_draw_expose_event), &rows[row]); rows[row].draw->enable_drop(Equip_shape_dropped, &rows[row]); } // Shape #: GtkWidget *spin = gtk_spin_button_new (GTK_ADJUSTMENT( gtk_adjustment_new (1, 0, 1023, 1, 50, 50)), 1, 0); rows[row].shape = spin; gtk_widget_show(spin); gtk_table_attach (table, spin, 1, 2, row + 2, row + 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_signal_connect(GTK_OBJECT(spin), "changed", GTK_SIGNAL_FUNC(on_equip_shape_changed), &rows[row]); // Name: label = gtk_label_new("label1"); rows[row].name = label; gtk_widget_show (label); gtk_table_attach (table, label, 2, 3, row + 2, row + 3, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (label), 6.70552e-08, 0.5); // Chance: spin = gtk_spin_button_new(GTK_ADJUSTMENT( gtk_adjustment_new (1, 0, 100, 1, 10, 10)), 1, 0); rows[row].chance = spin; gtk_widget_show (spin); gtk_table_attach (table, spin, 4, 5, row + 2, row + 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); // Count: spin = gtk_spin_button_new (GTK_ADJUSTMENT( gtk_adjustment_new (1, 0, 100, 1, 10, 10)), 1, 0); rows[row].count = spin; gtk_widget_show(spin); gtk_table_attach (table, spin, 6, 7, row + 2, row + 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); } } /* * Set the fields to a given record. */ void ExultStudio::init_equip_window ( int recnum // Record # to start with (1-based). ) { // Fill in the record. Equip_record& rec = Monster_info::get_equip(recnum - 1); // Go through rows. for (int row = 0; row < 10; row++) { Equip_element& elem = rec.get(row); Equip_row_widgets& widgets = equip_rows[row]; int shnum = elem.get_shapenum(); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.shape), shnum); const char *nm = get_shape_name(shnum); gtk_label_set_text(GTK_LABEL(widgets.name), nm); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.chance), elem.get_probability()); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.count), elem.get_quantity()); } } /* * Store the fields to a given record. */ void ExultStudio::save_equip_window ( ) { int recnum = get_spin("equip_recnum"); // Get the record. Equip_record& rec = Monster_info::get_equip(recnum - 1); // Go through rows. for (int row = 0; row < 10; row++) { Equip_element& elem = rec.get(row); Equip_row_widgets& widgets = equip_rows[row]; elem.set(gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(widgets.shape)), gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(widgets.chance)), gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(widgets.count))); } shape_info_modified = true; } /* * Open the equip-editing window. */ void ExultStudio::open_equip_window ( int recnum // Record # to start with (1-based). ) { int ecnt = Monster_info::get_equip_cnt(); if (recnum <= 0 || recnum > ecnt) return; if (!equipwin) // First time? { equipwin = glade_xml_get_widget( app_xml, "equip_window" ); GtkWidget *table = glade_xml_get_widget(app_xml, "equip_table"); Setup_equip(GTK_TABLE(table), vgafile->get_ifile(), palbuf, equip_rows); } // This will cause the data to be set: set_spin("equip_recnum", recnum, 1, ecnt); gtk_widget_show(equipwin); // show_shinfo_shape(); // Be sure picture is updated. } /* * Close the equip window. */ void ExultStudio::close_equip_window ( ) { if (equipwin) gtk_widget_hide(equipwin); } /* * Paint the shape in one row of the Equip window draw area. */ void ExultStudio::show_equip_shape ( Equip_row_widgets *eq, int x, int y, int w, int h // Rectangle. w=-1 to show all. ) { if (!eq->draw) return; eq->draw->configure(); int shnum = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(eq->shape)); if (!shnum) // Don't draw shape 0. shnum = -1; eq->draw->draw_shape_centered(shnum, 0); if (w != -1) eq->draw->show(x, y, w, h); else eq->draw->show(); } /* * Shape window's Okay, Apply buttons. */ C_EXPORT void on_shinfo_okay_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_shape_window(); ExultStudio::get_instance()->close_shape_window(); } C_EXPORT void on_shinfo_apply_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_shape_window(); } /* * Shape window's Cancel button. */ C_EXPORT void on_shinfo_cancel_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->close_shape_window(); } /* * Shape window's close button. */ C_EXPORT gboolean on_shape_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_shape_window(); return TRUE; } /* * Draw shape in draw area. */ C_EXPORT gboolean on_shinfo_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { ExultStudio::get_instance()->show_shinfo_shape( event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Shape window's Equip-Edit button. */ C_EXPORT void on_open_equip_button_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio *s = ExultStudio::get_instance(); s->open_equip_window(s->get_spin("shinfo_monster_equip")); } /* * Frame # in shape-info window: */ C_EXPORT void on_shinfo_frame_changed (GtkSpinButton *button, gpointer user_data) { ExultStudio *s = ExultStudio::get_instance(); s->set_shape_notebook_frame( gtk_spin_button_get_value_as_int(button)); // Force repaint of shape. gtk_widget_queue_draw(glade_xml_get_widget(s->get_xml(), "shinfo_draw")); } /* * Special-shapes toggles: */ C_EXPORT void on_shinfo_weapon_check_toggled ( GtkToggleButton *btn, gpointer user_data ) { bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); ExultStudio::get_instance()->set_visible("shinfo_weapon_box", on); } C_EXPORT void on_shinfo_ammo_check_toggled ( GtkToggleButton *btn, gpointer user_data ) { bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); ExultStudio::get_instance()->set_visible("shinfo_ammo_box", on); } C_EXPORT void on_shinfo_armor_check_toggled ( GtkToggleButton *btn, gpointer user_data ) { bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); ExultStudio::get_instance()->set_visible("shinfo_armor_box", on); } C_EXPORT void on_shinfo_monster_check_toggled ( GtkToggleButton *btn, gpointer user_data ) { bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); ExultStudio::get_instance()->set_visible("shinfo_monster_box", on); } /* * Set frame-dependent fields in the shape-editing notebook. */ void ExultStudio::set_shape_notebook_frame ( int frnum // Frame # to set. ) { Shape_info *info = (Shape_info *) gtk_object_get_user_data(GTK_OBJECT(shapewin)); if (!info) return; set_spin("shinfo_xtiles", info->get_3d_xtiles(frnum)); set_spin("shinfo_ytiles", info->get_3d_ytiles(frnum)); unsigned char wx, wy; // Weapon-in-hand offset. info->get_weapon_offset(frnum, wx, wy); set_spin("shinfo_wihx", wx, 0, 255); // Negative??? set_spin("shinfo_wihy", wy, 0, 255); } /* * Fill in the shape-editing notebook. */ void ExultStudio::init_shape_notebook ( Shape_info& info, GtkWidget *book, // The notebook. int shnum, // Shape #. int frnum // Frame #. ) { static int classes[] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 9, 10, 11, 12, 0}; const int numclasses = sizeof(classes)/sizeof(classes[0]); int shclass = (unsigned int) info.get_shape_class(); set_optmenu("shinfo_shape_class", shclass < numclasses ? classes[shclass] : 0); set_shape_notebook_frame(frnum); set_spin("shinfo_ztiles", info.get_3d_height()); int spot = info.get_ready_type(); if (spot < 0) spot = 3; // Left hand if looks invalid. else if (spot == 100) spot = 18; // LR Hand. Not sure about this. else if (spot > 17) spot = 3; set_optmenu("shinfo_ready_spot", spot); set_spin("shinfo_weight", info.get_weight(), 0, 255); set_spin("shinfo_volume", info.get_volume(), 0, 255); // Bunch of flags: set_toggle("shinfo_sfx_check", info.has_sfx()); set_toggle("shinfo_strange_check", info.has_strange_movement()); set_toggle("shinfo_animated_check", info.is_animated()); set_toggle("shinfo_solid_check", info.is_solid()); set_toggle("shinfo_water_check", info.is_water()); // ++++Set poison for flats, field for non-flats. set_toggle("shinfo_poison_check", info.is_poisonous()); set_toggle("shinfo_field_check", info.is_field()); set_toggle("shinfo_door_check", info.is_door()); set_toggle("shinfo_barge_check", info.is_barge_part()); set_toggle("shinfo_transp_check", info.is_transparent()); set_toggle("shinfo_light_check", info.is_light_source()); set_toggle("shinfo_transl_check", info.has_translucency()); set_toggle("shinfo_obstaclex_check", info.is_xobstacle()); set_toggle("shinfo_obstacley_check", info.is_yobstacle()); set_toggle("shinfo_occludes_check", info.occludes()); // Extras. Weapon_info *winfo = info.get_weapon_info(); set_toggle("shinfo_weapon_check", winfo != 0); set_visible("shinfo_weapon_box", winfo != 0); if (winfo) // Setup weapon page. { set_spin("shinfo_weapon_damage", winfo->get_damage()); set_spin("shinfo_weapon_range", winfo->get_range()); set_optmenu("shinfo_weapon_type", winfo->get_damage_type()); int ammo = winfo->get_ammo_consumed(); int ammo_use = ammo > 0 ? 0 : winfo->uses_charges() ? 2 : winfo->is_thrown() ? 3 : 1; // 1 == "None". set_optmenu("shinfo_weapon_ammo", ammo_use); set_spin("shinfo_weapon_ammo_shape", ammo, ammo > 0); set_spin("shinfo_weapon_proj", winfo->get_projectile(), 0, 1023); set_optmenu("shinfo_weapon_uses", winfo->get_uses()); set_spin("shinfo_weapon_sfx", winfo->get_sfx(), 0, 1023); set_spin("shinfo_weapon_hitsfx", winfo->get_hitsfx(), 0, 1023); // Show usecode in hex. set_entry("shinfo_weapon_uc", winfo->get_usecode(), true); static char *powers[] = { "shinfo_weapon_pow0", "shinfo_weapon_pow1", "shinfo_weapon_pow2", "shinfo_weapon_pow3", "shinfo_weapon_pow4", "shinfo_weapon_pow5" }; set_bit_toggles(&powers[0], sizeof(powers)/sizeof(powers[0]), winfo->get_powers()); set_toggle("shinfo_weapon_explodes", winfo->explodes()); set_toggle("shinfo_weapon_returns", winfo->returns()); } Ammo_info *ainfo = info.get_ammo_info(); set_toggle("shinfo_ammo_check", ainfo != 0); set_visible("shinfo_ammo_box", ainfo != 0); if (ainfo) // Setup ammo page. { set_spin("shinfo_ammo_damage", ainfo->get_damage()); set_spin("shinfo_ammo_family", ainfo->get_family_shape()); set_optmenu("shinfo_ammo_type", ainfo->get_damage_type()); static char *powers[] = { "shinfo_ammo_pow0", "shinfo_ammo_pow1", "shinfo_ammo_pow2", "shinfo_ammo_pow3", "shinfo_ammo_pow4", "shinfo_ammo_pow5" }; set_bit_toggles(&powers[0], sizeof(powers)/sizeof(powers[0]), ainfo->get_powers()); // 'Explode'??? } Armor_info *arinfo = info.get_armor_info(); set_toggle("shinfo_armor_check", arinfo != 0); set_visible("shinfo_armor_box", arinfo != 0); if (arinfo) // Setup armor page. { static char *immun[] = {"shinfo_armor_immun0", "shinfo_armor_immun1", "shinfo_armor_immun2", "shinfo_armor_immun3" }; set_spin("shinfo_armor_value", arinfo->get_prot()); set_bit_toggles(&immun[0], sizeof(immun)/sizeof(immun[0]), arinfo->get_immune()); } Monster_info *minfo = info.get_monster_info(); set_toggle("shinfo_monster_check", minfo != 0); set_visible("shinfo_monster_box", minfo != 0); if (minfo) // Setup monster page. { set_spin("shinfo_monster_str", minfo->get_strength()); set_spin("shinfo_monster_dex", minfo->get_dexterity()); set_spin("shinfo_monster_intel", minfo->get_intelligence()); set_spin("shinfo_monster_cmb", minfo->get_combat()); set_spin("shinfo_monster_armor", minfo->get_armor()); set_spin("shinfo_monster_wpn", minfo->get_weapon()); set_spin("shinfo_monster_reach", minfo->get_reach()); set_spin("shinfo_monster_equip", minfo->get_equip_offset()); set_optmenu("shinfo_monster_align", minfo->get_alignment()); static char *vuln[] = { "shinfo_monster_vuln0", "shinfo_monster_vuln1", "shinfo_monster_vuln2", "shinfo_monster_vuln3" }; static char *immun[] = {"shinfo_monster_immun0", "shinfo_monster_immun1", "shinfo_monster_immun2", "shinfo_monster_immun3" }; set_bit_toggles(&vuln[0], sizeof(vuln)/sizeof(vuln[0]), minfo->get_vulnerable()); set_bit_toggles(&immun[0], sizeof(immun)/sizeof(immun[0]), minfo->get_immune()); set_toggle("shinfo_monster_splits", minfo->splits()); set_toggle("shinfo_monster_cant_die", minfo->cant_die()); set_toggle("shinfo_monster_cant_yell", minfo->cant_yell()); set_toggle("shinfo_monster_cant_bleed", minfo->cant_bleed()); set_toggle("shinfo_monster_poison_safe", minfo->poison_safe()); static char *flags[] = {"shinfo_monster_flag0", "shinfo_monster_flag1", "shinfo_monster_flag2", "shinfo_monster_flag3", "shinfo_monster_flag4" }; set_bit_toggles(&flags[0], sizeof(flags)/sizeof(flags[0]), minfo->get_flags()); } gtk_widget_show(book); } /* * Save the shape-editing notebook. */ void ExultStudio::save_shape_notebook ( Shape_info& info, int shnum, // Shape #. int frnum // Frame #. ) { static int classes[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14}; info.set_shape_class((Shape_info::Shape_class) classes[get_optmenu("shinfo_shape_class")]); info.set_3d(get_spin("shinfo_xtiles"), get_spin("shinfo_ytiles"), get_spin("shinfo_ztiles")); int spot = get_optmenu("shinfo_ready_spot"); if (spot == 18) // LR hand. spot = 100; info.set_ready_type(spot); info.set_weight_volume(get_spin("shinfo_weight"), get_spin("shinfo_volume")); info.set_weapon_offset(frnum, get_spin("shinfo_wihx"), get_spin("shinfo_wihy")); // Bunch of flags: info.set_sfx(get_toggle("shinfo_sfx_check")); info.set_strange_movement(get_toggle("shinfo_strange_check")); info.set_animated(get_toggle("shinfo_animated_check")); info.set_solid(get_toggle("shinfo_solid_check")); info.set_water(get_toggle("shinfo_water_check")); // ++++Set poison for flats, field for non-flats. info.set_field(get_toggle("shinfo_field_check") || get_toggle("shinfo_poison_check")); info.set_door(get_toggle("shinfo_door_check")); info.set_barge_part(get_toggle("shinfo_barge_check")); info.set_transparent(get_toggle("shinfo_transp_check")); info.set_light_source(get_toggle("shinfo_light_check")); info.set_translucency(get_toggle("shinfo_transl_check")); info.set_obstacle(get_toggle("shinfo_obstaclex_check"), get_toggle("shinfo_obstacley_check")); info.set_occludes(get_toggle("shinfo_occludes_check")); // Extras. if (!get_toggle("shinfo_weapon_check")) info.set_weapon_info(false); // Not a weapon. else { Weapon_info *winfo = info.set_weapon_info(true); winfo->set_damage( get_spin("shinfo_weapon_damage"), get_optmenu("shinfo_weapon_type")); winfo->set_range(get_spin("shinfo_weapon_range")); int ammo_use = get_optmenu("shinfo_weapon_ammo"); int ammo = ammo_use == 0 ? get_spin("shinfo_weapon_ammo_shape") : ammo_use == 2 ? -2 // Charges. : ammo_use == 3 ? -3 // Thrown. : -1; // None. winfo->set_ammo(ammo); winfo->set_projectile(get_spin("shinfo_weapon_proj")); winfo->set_uses(get_optmenu("shinfo_weapon_uses")); winfo->set_sfxs(get_spin("shinfo_weapon_sfx"), get_spin("shinfo_weapon_hitsfx")); // Get usecode in hex. winfo->set_usecode(get_num_entry("shinfo_weapon_uc")); static char *powers[] = { "shinfo_weapon_pow0", "shinfo_weapon_pow1", "shinfo_weapon_pow2", "shinfo_weapon_pow3", "shinfo_weapon_pow4", "shinfo_weapon_pow5" }; winfo->set_powers(get_bit_toggles(&powers[0], sizeof(powers)/sizeof(powers[0]))); // 'Explode'??? winfo->set_returns(get_toggle("shinfo_weapon_returns")); winfo->set_explodes(get_toggle("shinfo_weapon_explodes")); } if (!get_toggle("shinfo_ammo_check")) info.set_ammo_info(false); // Not ammo. else { Ammo_info *ainfo = info.set_ammo_info(true); ainfo->set_family_shape(get_spin("shinfo_ammo_family")); ainfo->set_damage(get_spin("shinfo_ammo_damage"), get_optmenu("shinfo_ammo_type")); static char *powers[] = { "shinfo_ammo_pow0", "shinfo_ammo_pow1", "shinfo_ammo_pow2", "shinfo_ammo_pow3", "shinfo_ammo_pow4", "shinfo_ammo_pow5" }; ainfo->set_powers(get_bit_toggles(&powers[0], sizeof(powers)/sizeof(powers[0]))); // 'Explode'??? } if (!get_toggle("shinfo_armor_check")) info.set_armor_info(false); // Not armor. else { Armor_info *arinfo = info.set_armor_info(true); static char *immun[] = {"shinfo_armor_immun0", "shinfo_armor_immun1", "shinfo_armor_immun2", "shinfo_armor_immun3" }; arinfo->set_prot(get_spin("shinfo_armor_value")); arinfo->set_immune(get_bit_toggles(&immun[0], sizeof(immun)/sizeof(immun[0]))); } if (!get_toggle("shinfo_monster_check")) info.set_monster_info(false); else { Monster_info *minfo = info.set_monster_info(true); minfo->set_stats( get_spin("shinfo_monster_str"), get_spin("shinfo_monster_dex"), get_spin("shinfo_monster_intel"), get_spin("shinfo_monster_cmb"), get_spin("shinfo_monster_armor"), get_spin("shinfo_monster_wpn"), get_spin("shinfo_monster_reach")); minfo->set_equip_offset(get_spin("shinfo_monster_equip")); minfo->set_alignment(get_optmenu("shinfo_monster_align")); static char *vuln[] = { "shinfo_monster_vuln0", "shinfo_monster_vuln1", "shinfo_monster_vuln2", "shinfo_monster_vuln3" }; static char *immun[] = {"shinfo_monster_immun0", "shinfo_monster_immun1", "shinfo_monster_immun2", "shinfo_monster_immun3" }; minfo->set_vulnerable(get_bit_toggles(&vuln[0], sizeof(vuln)/sizeof(vuln[0]))); minfo->set_immune(get_bit_toggles(&immun[0], sizeof(immun)/sizeof(immun[0]))); minfo->set_splits(get_toggle("shinfo_monster_splits")); minfo->set_cant_die(get_toggle("shinfo_monster_cant_die")); minfo->set_cant_yell(get_toggle("shinfo_monster_cant_yell")); minfo->set_cant_bleed(get_toggle("shinfo_monster_cant_bleed")); minfo->set_poison_safe( get_toggle("shinfo_monster_poison_safe")); static char *flags[] = {"shinfo_monster_flag0", "shinfo_monster_flag1", "shinfo_monster_flag2", "shinfo_monster_flag3", "shinfo_monster_flag4" }; minfo->set_flags(get_bit_toggles(&flags[0], sizeof(flags)/sizeof(flags[0]))); } shape_info_modified = true; } /* * Open the shape-editing window. */ void ExultStudio::open_shape_window ( int shnum, // Shape #. int frnum, // Frame #. Shape_file_info *file_info, // For image file shape is in. char *shname, // ->shape name, or null. Shape_info *info // Info. if in main object shapes. ) { if (!shapewin) // First time? shapewin = glade_xml_get_widget( app_xml, "shape_window" ); if (shape_draw) // Ifile might have changed. delete shape_draw; shape_draw = 0; Vga_file *ifile = file_info->get_ifile(); if (ifile && palbuf) { shape_draw = new Shape_draw(ifile, palbuf, glade_xml_get_widget(app_xml, "shinfo_draw")); // shape_draw->enable_drop(Shape_shape_dropped, this); } // Store ->'s. gtk_object_set_user_data(GTK_OBJECT(shapewin), info); gtk_object_set_data(GTK_OBJECT(shapewin), "file_info", file_info); // Shape/frame. set_entry("shinfo_shape", shnum, false, false); int nframes = ifile->get_num_frames(shnum); set_spin("shinfo_frame", frnum, 0, nframes - 1); // Store name, #frames. set_entry("shinfo_name", shname ? shname : ""); // set_spin("shinfo_num_frames", nframes); // Show xright, ybelow. Shape_frame *shape = ifile->get_shape(shnum, frnum); set_spin("shinfo_originx", shape->get_xright(), 0, shape->get_width()); set_spin("shinfo_originy", shape->get_ybelow(), 0, shape->get_height()); // Get info. notebook. GtkWidget *notebook = glade_xml_get_widget(app_xml, "shinfo_notebook"); if (info) init_shape_notebook(*info, notebook, shnum, frnum); else gtk_widget_hide(notebook); gtk_widget_show(shapewin); show_shinfo_shape(); // Be sure picture is updated. } /* * Save the shape-editing window. */ void ExultStudio::save_shape_window ( ) { int shnum = get_num_entry("shinfo_shape"); int frnum = get_num_entry("shinfo_frame"); Shape_info *info = (Shape_info *) gtk_object_get_user_data(GTK_OBJECT(shapewin)); Shape_file_info *file_info = (Shape_file_info *) gtk_object_get_data(GTK_OBJECT(shapewin), "file_info"); Vga_file *ifile = file_info->get_ifile(); if (info && // If 'shapes.vga', get name. shnum < 1024) // But only for the first 1024. { const gchar *nm = get_text_entry("shinfo_name"); if (!nm) nm = ""; char *oldname = get_shape_name(shnum); if (!oldname) oldname = ""; if (strcmp(nm, oldname) != 0) { // Name changed. if (shnum >= names.size()) names.resize(shnum + 1); delete names[shnum]; names[shnum] = nm ? newstrdup(nm) : 0; shape_names_modified = true; } } // Update origin. Shape_frame *shape = ifile->get_shape(shnum, frnum); int xright = get_spin("shinfo_originx"), ybelow = get_spin("shinfo_originy"); if (xright != shape->get_xright() || ybelow != shape->get_ybelow()) { // It changed. file_info->set_modified(); shape->set_offset(xright, ybelow); } if (info) save_shape_notebook(*info, shnum, frnum); } /* * Close the shape-editing window. */ void ExultStudio::close_shape_window ( ) { if (shapewin) gtk_widget_hide(shapewin); } /* * Paint the shape in the draw area. */ void ExultStudio::show_shinfo_shape ( int x, int y, int w, int h // Rectangle. w=-1 to show all. ) { if (!shape_draw) return; shape_draw->configure(); // Yes, this is kind of redundant... int shnum = get_num_entry("shinfo_shape"); int frnum = get_num_entry("shinfo_frame"); shape_draw->draw_shape_centered(shnum, frnum); if (w != -1) shape_draw->show(x, y, w, h); else shape_draw->show(); } exult-1.2/mapedit/objbrowse.h0000644000175000001440000000661507713365507012007 /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OBJBROWSE_H #define OBJBROWSE_H #include //#include class Shape_group; class Shape_file_info; class Object_browser { private: GtkWidget *widget; protected: int selected; // Index of user-selected entry, // counting from the top-left entry // currently rendered. int index0; // Index of top-leftmost in // displayed list. GtkWidget *vscroll; // Vertical scrollbar. GtkWidget *hscroll; // Horizontal scrollbar. Shape_group *group; // Non-null to use filter. GtkWidget *popup; // Popup menu in draw area. Shape_file_info *file_info; // Our creator (or null). GtkWidget *find_text; // For searching. GtkWidget *loc_down, *loc_up; // 'Locate' buttons. // 'Move' buttons: GtkWidget *move_down, *move_up; int config_width, config_height;// For storing prev. dims. void set_widget(GtkWidget *w); static bool search_name(const char *nm, const char *srch); public: Object_browser(Shape_group *grp = 0, Shape_file_info *fi = 0); virtual ~Object_browser(); GtkWidget *get_widget(); Shape_group *get_group() { return group; } int get_selected() // Return index of sel'd item, or -1. { return selected < 0 ? -1 : index0 + selected; } GtkWidget *get_find_text() // Get 'find' text widget. { return find_text; } virtual void load() // Load from file data. { } virtual void render() = 0; // Blit onto screen. virtual void show(int x, int y, int w, int h) = 0; virtual void show() = 0; virtual int get_selected_id() { return -1; } virtual bool server_response(int id, unsigned char *data, int datalen); virtual void end_terrain_editing(); virtual void set_background_color(guint32 c); // Menu items: static void on_browser_group_add( GtkMenuItem *item, gpointer udata); // Add 'Add to group...' submenu. void add_group_submenu(GtkWidget *popup); static void on_browser_file_save(GtkMenuItem *item, gpointer udata); static void on_browser_file_revert(GtkMenuItem *item, gpointer udata); virtual GtkWidget *create_popup(); // Popup menu. enum // Create controls at bottom. { // OR together what you want. find_controls = 1, locate_controls = 2, move_controls = 4 }; GtkWidget *create_controls(int controls); // Virtuals for controls. virtual void search(const char *srch, int dir) { } virtual void locate(bool upwards)// Locate terrain on game map. { } virtual void move(bool upwards) // Move current selected chunk. { } }; // File-selector utility: // Callback for file-selector 'ok': typedef void (*File_sel_okay_fun)(const char *, gpointer); GtkFileSelection *Create_file_selection ( const char *title, File_sel_okay_fun ok_handler, gpointer user_data ); #endif exult-1.2/mapedit/npcedit.cc0000644000175000001440000005454510043113442011557 /** ** Npcedit.cc - Npc-editing methods. ** ** Written: 6/8/01 - JSF **/ /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "studio.h" #include "u7drag.h" #include "servemsg.h" #include "objserial.h" #include "exult_constants.h" #include "utils.h" #include "shapefile.h" #include "shapedraw.h" #ifdef WIN32 #include "windrag.h" #endif using std::cout; using std::endl; /* * Open npc window. */ C_EXPORT void on_open_npc_activate ( GtkMenuItem *menuitem, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); studio->open_npc_window(); } /* * Npc window's Apply button. */ C_EXPORT void on_npc_apply_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_npc_window(); } /* * Npc window's Cancel button. */ C_EXPORT void on_npc_cancel_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->close_npc_window(); } /* * Npc window's close button. */ C_EXPORT gboolean on_npc_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_npc_window(); return TRUE; } /* * Draw shape in NPC shape area. */ C_EXPORT gboolean on_npc_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { ExultStudio::get_instance()->show_npc_shape( event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Npc shape # lost focus, so update shape displayed. */ C_EXPORT gboolean on_npc_shape_focus_out_event ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data ) { ExultStudio::get_instance()->show_npc_shape(); return FALSE; } /* * Callback for when a shape is dropped on the NPC draw area. */ static void Npc_shape_dropped ( int file, // U7_SHAPE_SHAPES. int shape, int frame, void *udata ) { if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024) ((ExultStudio *) udata)->set_npc_shape(shape, frame); } // Schedule names. /* * Draw face. */ C_EXPORT gboolean on_npc_face_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { ExultStudio::get_instance()->show_npc_face( event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Callback for when a shape is dropped on the NPC face area. */ static void Npc_face_dropped ( int file, // U7_SHAPE_FACES int shape, int frame, void *udata ) { if (file == U7_SHAPE_FACES && shape >= 0 && shape < 1024) ((ExultStudio *) udata)->set_npc_face(shape, frame); } // Schedule names. static char *sched_names[32] = { "Combat", "Horiz. Pace", "Vert. Pace", "Talk", "Dance", "Eat", "Farm", "Tend Shop", "Miner", "Hound", "Stand", "Loiter", "Wander", "Blacksmith", "Sleep", "Wait", "Sit", "Graze", "Bake", "Sew", "Shy", "Lab Work", "Thief", "Waiter", "Special", "Kid Games", "Eat at Inn", "Duel", "Preach", "Patrol", "Desk Work", "Follow"}; /* * Set a line in the schedule page. */ static void Set_schedule_line ( GladeXML *app_xml, int time, // 0-7. int type, // Activity (0-31, or -1 for none). int tx, int ty, int tz = 0 // Location. ) { char *lname = g_strdup_printf("npc_sched%d", time); GtkLabel *label = GTK_LABEL(glade_xml_get_widget(app_xml, lname)); g_free(lname); // User data = schedule #. gtk_object_set_user_data(GTK_OBJECT(label), (gpointer) type); gtk_label_set_text(label, type >= 0 && type < 32 ? sched_names[type] : "-----"); // Set location. char *locname = g_strdup_printf("sched_loc%d", time); GtkBox *box = GTK_BOX(glade_xml_get_widget(app_xml, locname)); g_free(locname); GList *list = g_list_first(box->children); GtkWidget *spin = ((GtkBoxChild *) list->data)->widget; gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), tx); list = g_list_next(list); spin = ((GtkBoxChild *) list->data)->widget; gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), ty); list = g_list_next(list); spin = ((GtkBoxChild *) list->data)->widget; // Current engine assumes tz==0. gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), 0); gtk_widget_set_sensitive(spin, FALSE); } /* * Get info. from line in the schedule page. * * Output: False if schedule isn't set. */ static bool Get_schedule_line ( GladeXML *app_xml, int time, // 0-7. Serial_schedule& sched // Filled in if 'true' returned. ) { char *lname = g_strdup_printf("npc_sched%d", time); GtkLabel *label = GTK_LABEL(glade_xml_get_widget(app_xml, lname)); g_free(lname); // User data = schedule #. sched.type = (int) gtk_object_get_user_data(GTK_OBJECT(label)); if (sched.type < 0 || sched.type > 31) return false; // Get location. char *locname = g_strdup_printf("sched_loc%d", time); GtkBox *box = GTK_BOX(glade_xml_get_widget(app_xml, locname)); g_free(locname); GList *list = g_list_first(box->children); GtkWidget *spin = ((GtkBoxChild *) list->data)->widget; sched.tx = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); list = g_list_next(list); spin = ((GtkBoxChild *) list->data)->widget; sched.ty = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); // list = g_list_next(list); // spin = ((GtkBoxChild *) list->data)->widget; // sched.tz = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); sched.time = time; return true; } /* * Open the npc-editing window. */ #ifdef WIN32 static void Drop_dragged_shape(int shape, int frame, int x, int y, void *data) { cout << "Dropped a shape: " << shape << "," << frame << " " << data << endl; Npc_shape_dropped(U7_SHAPE_SHAPES, shape, frame, data); } static void Drop_dragged_face(int shape, int frame, int x, int y, void *data) { cout << "Dropped a face: " << shape << "," << frame << " " << data << endl; Npc_face_dropped(U7_SHAPE_FACES, shape, frame, data); } #endif void ExultStudio::open_npc_window ( unsigned char *data, // Serialized npc, or null. int datalen ) { bool first_time = false; if (!npcwin) // First time? { first_time = true; npcwin = glade_xml_get_widget( app_xml, "npc_window" ); if (vgafile && palbuf) { npc_draw = new Shape_draw(vgafile->get_ifile(), palbuf, glade_xml_get_widget(app_xml, "npc_draw")); npc_draw->enable_drop(Npc_shape_dropped, this); } if (facefile && palbuf) { npc_face_draw = new Shape_draw(facefile->get_ifile(), palbuf, glade_xml_get_widget(app_xml, "npc_face_draw")); npc_face_draw->enable_drop(Npc_face_dropped, this); } npc_ctx = gtk_statusbar_get_context_id( GTK_STATUSBAR(glade_xml_get_widget( app_xml, "npc_status")), "Npc Editor"); for (int i = 0; i < 24/3; i++) // Init. schedules' user_data. Set_schedule_line(app_xml, i, -1, 0, 0, 0); } // Init. npc address to null. gtk_object_set_user_data(GTK_OBJECT(npcwin), 0); // Make 'apply', 'cancel' sensitive. set_sensitive("npc_apply_btn", true); set_sensitive("npc_cancel_btn", true); remove_statusbar("npc_status", npc_ctx, npc_status_id); if (data) { if (!init_npc_window(data, datalen)) return; } else init_new_npc(); gtk_widget_show(npcwin); #ifdef WIN32 if (first_time || !npcdnd) Windnd::CreateStudioDropDest(npcdnd, npchwnd, Drop_dragged_shape, NULL, Drop_dragged_face, (void*) this); #endif } /* * Close the npc-editing window. */ void ExultStudio::close_npc_window ( ) { if (npcwin) { gtk_widget_hide(npcwin); #ifdef WIN32 Windnd::DestroyStudioDropDest(npcdnd, npchwnd); #endif } } /* * Get one of the NPC 'property' spin buttons from the table in the NPC * dialog box. * * Output: true if successful, with spin, pnum returned. */ static bool Get_prop_spin ( GList *list, // Entry in table of properties. GtkSpinButton *& spin, // Spin button returned. int& pnum // Property number (0-11) returned. ) { GtkTableChild *ent = (GtkTableChild *) list->data; GtkBin *frame = GTK_BIN(ent->widget); spin = GTK_SPIN_BUTTON(frame->child); assert (spin != 0); const char *name = glade_get_widget_name(GTK_WIDGET(spin)); // Names: npc_prop_nn. if (strncmp(name, "npc_prop_", 9) != 0) return false; pnum = atoi(name + 9); return (pnum >= 0 && pnum < 12); } /* * Get one of the NPC flag checkbox's from the table in the NPC * dialog box. * * Output: true if successful, with cbox, fnum returned. */ static bool Get_flag_cbox ( GList *list, // Entry in table of flags. unsigned long *oflags, // Object flags. unsigned long *siflags, // Serpent Isle flags. unsigned long *type_flags, // Type (movement) flags. GtkCheckButton *& cbox, // Checkbox returned. unsigned long *& bits, // ->one of 3 flags above. int& fnum // Flag # (0-31) returned. ) { GtkTableChild *ent = (GtkTableChild *) list->data; cbox = GTK_CHECK_BUTTON(ent->widget); assert (cbox != 0); const char *name = glade_get_widget_name(GTK_WIDGET(cbox)); // Names: npc_flag_xx_nn, where // xx = si, of, tf. if (strncmp(name, "npc_flag_", 9) != 0) return false; // Which flag. if (strncmp(name + 9, "si", 2) == 0) bits = siflags; else if (strncmp(name + 9, "of", 2) == 0) bits = oflags; else if (strncmp(name + 9, "tf", 2) == 0) bits = type_flags; else return false; fnum = atoi(name + 9 + 3); return (fnum >= 0 && fnum < 32); } /* * Init. the npc editor for a new NPC. */ void ExultStudio::init_new_npc ( ) { int npc_num = -1; // Got to get what new NPC # will be. if (Send_data(server_socket, Exult_server::npc_info) == -1) cout << "Error sending data to server." << endl; // Should get immediate answer. unsigned char data[Exult_server::maxlength]; Exult_server::Msg_type id; Exult_server::wait_for_response(server_socket, 100); int len = Exult_server::Receive_data(server_socket, id, data, sizeof(data)); unsigned char *ptr = &data[0]; int npcs = Read2(ptr); int first_unused = Read2(ptr); npc_num = first_unused; set_entry("npc_num_entry", npc_num, true, false); // Usually, usecode = 0x400 + num. set_entry("npc_usecode_entry", 0x400 + npc_num, true, npc_num >=256 ? true : false); // Usually, face = npc_num. set_npc_face(npc_num, 0); set_entry("npc_name_entry", ""); set_entry("npc_ident_entry", 0); set_entry("npc_shape", -1); set_entry("npc_frame", 0); set_optmenu("npc_attack_mode", 0); set_optmenu("npc_alignment", 0); // Clear flag buttons. GtkTable *ftable = GTK_TABLE( glade_xml_get_widget(app_xml, "npc_flags_table")); // Set flag checkboxes. for (GList *list = g_list_first(ftable->children); list; list = g_list_next(list)) { GtkTableChild *ent = (GtkTableChild *) list->data; GtkCheckButton *cbox = GTK_CHECK_BUTTON(ent->widget); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbox), false); } // Set properties. GtkTable *ptable = GTK_TABLE( glade_xml_get_widget(app_xml, "npc_props_table")); for (GList *list = g_list_first(ptable->children); list; list = g_list_next(list)) { GtkSpinButton *spin; int pnum; if (Get_prop_spin(list, spin, pnum)) gtk_spin_button_set_value(spin, 12); } // Clear schedules. for (int i = 0; i < 24/3; i++) Set_schedule_line(app_xml, i, -1, 0, 0, 0); } /* * Init. the npc editor with data from Exult. * * Output: 0 if error (reported). */ int ExultStudio::init_npc_window ( unsigned char *data, int datalen ) { unsigned long addr; int tx, ty, tz; int shape, frame, face; std::string name; short npc_num, ident; int usecode; int properties[12]; short attack_mode, alignment; unsigned long oflags; // Object flags. unsigned long siflags; // Extra flags for SI. unsigned long type_flags; // Movement flags. short num_schedules; Serial_schedule schedules[8]; if (!Npc_actor_in(data, datalen, addr, tx, ty, tz, shape, frame, face, name, npc_num, ident, usecode, properties, attack_mode, alignment, oflags, siflags, type_flags, num_schedules, schedules)) { cout << "Error decoding npc" << endl; return 0; } // Store address with window. gtk_object_set_user_data(GTK_OBJECT(npcwin), (gpointer) addr); // Store name, ident, num. set_entry("npc_name_entry", name.c_str()); // (Not allowed to change npc#.). set_entry("npc_num_entry", npc_num, true, false); set_entry("npc_ident_entry", ident); // Shape/frame. set_entry("npc_shape", shape); set_entry("npc_frame", frame); set_npc_face(face, 0); // Usecode #. set_entry("npc_usecode_entry", usecode, true, npc_num >= 256 ? true : false); // Combat: set_optmenu("npc_attack_mode", attack_mode); set_optmenu("npc_alignment", alignment); // Set flag buttons. GtkTable *ftable = GTK_TABLE( glade_xml_get_widget(app_xml, "npc_flags_table")); // Set flag checkboxes. for (GList *list = g_list_first(ftable->children); list; list = g_list_next(list)) { GtkCheckButton *cbox; unsigned long *bits; int fnum; if (Get_flag_cbox(list, &oflags, &siflags, &type_flags, cbox, bits, fnum)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbox), (*bits&(1<children); list; list = g_list_next(list)) { GtkSpinButton *spin; int pnum; if (Get_prop_spin(list, spin, pnum)) gtk_spin_button_set_value(spin, properties[pnum]); } // Set schedules. for (int i = 0; i < 24/3; i++) // First init. to empty. Set_schedule_line(app_xml, i, -1, 0, 0, 0); for (int i = 0; i < num_schedules; i++) { Serial_schedule& sched = schedules[i]; int time = sched.time; // 0-7. if (time < 0 || time > 7) continue; // Invalid. Set_schedule_line(app_xml,time,sched.type, sched.tx, sched.ty); } return 1; } /* * Callback for when user clicked where NPC should be inserted. */ static void Npc_response ( Exult_server::Msg_type id, unsigned char *data, int datalen, void * /* client */ ) { ExultStudio *studio = ExultStudio::get_instance(); if (id == Exult_server::user_responded) studio->close_npc_window(); //+++++cancel?? } /* * Send updated NPC info. back to Exult. * * Output: 0 if error (reported). */ int ExultStudio::save_npc_window ( ) { cout << "In save_npc_window()" << endl; unsigned char data[Exult_server::maxlength]; // Get npc (null if creating new). unsigned long addr = (unsigned long) gtk_object_get_user_data( GTK_OBJECT(npcwin)); int tx = -1, ty = -1, tz = -1; // +++++For now. std::string name(get_text_entry("npc_name_entry")); short npc_num = get_num_entry("npc_num_entry"); short ident = get_num_entry("npc_ident_entry"); int shape = get_num_entry("npc_shape"); int frame = get_num_entry("npc_frame"); GtkWidget *fw = glade_xml_get_widget(app_xml, "npc_face_frame"); int face = (int) gtk_object_get_user_data(GTK_OBJECT(fw)); int usecode = get_num_entry("npc_usecode_entry"); short attack_mode = get_optmenu("npc_attack_mode"); short alignment = get_optmenu("npc_alignment"); unsigned long oflags = 0; // Object flags. unsigned long siflags = 0; // Extra flags for SI. unsigned long type_flags = 0; // Movement flags. if (shape < 0 || shape >= vgafile->get_ifile()->get_num_shapes()) { EStudio::Alert("You must set a valid shape #."); return 0; } // Set flag buttons. GtkTable *ftable = GTK_TABLE( glade_xml_get_widget(app_xml, "npc_flags_table")); // Get flags. for (GList *list = g_list_first(ftable->children); list; list = g_list_next(list)) { GtkCheckButton *cbox; unsigned long *bits; int fnum; if (Get_flag_cbox(list, &oflags, &siflags, &type_flags, cbox, bits, fnum)) if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbox))) *bits |= (1<children); list; list = g_list_next(list)) { GtkSpinButton *spin; int pnum; if (Get_prop_spin(list, spin, pnum)) properties[pnum] = gtk_spin_button_get_value_as_int(spin); } short num_schedules = 0; Serial_schedule schedules[8]; for (int i = 0; i < 8; i++) if (Get_schedule_line(app_xml, i, schedules[num_schedules])) num_schedules++; if (Npc_actor_out(server_socket, addr, tx, ty, tz, shape, frame, face, name, npc_num, ident, usecode, properties, attack_mode, alignment, oflags, siflags, type_flags, num_schedules, schedules) == -1) { cout << "Error sending npc data to server" <configure(); // Yes, this is kind of redundant... int shnum = get_num_entry("npc_shape"); int frnum = get_num_entry("npc_frame"); if (!shnum) // Don't draw shape 0. shnum = -1; npc_draw->draw_shape_centered(shnum, frnum); if (w != -1) npc_draw->show(x, y, w, h); else npc_draw->show(); } /* * Set NPC shape. */ void ExultStudio::set_npc_shape ( int shape, int frame ) { set_entry("npc_shape", shape); set_entry("npc_frame", frame); show_npc_shape(); } /* * Paint the face. */ void ExultStudio::show_npc_face ( int x, int y, int w, int h // Rectangle. w=-1 to show all. ) { if (!npc_face_draw) return; npc_face_draw->configure(); GtkWidget *frame = glade_xml_get_widget(app_xml, "npc_face_frame"); int shnum = (int) gtk_object_get_user_data(GTK_OBJECT(frame)); npc_face_draw->draw_shape_centered(shnum, 0); if (w != -1) npc_face_draw->show(x, y, w, h); else npc_face_draw->show(); } /* * Set NPC face. */ void ExultStudio::set_npc_face ( int shape, int frame ) { // set_entry("npc_shape", shape); // set_entry("npc_frame", frame); if (shape < 0) shape = 1; // Default to 1st after Avatar. GtkWidget *widget = glade_xml_get_widget(app_xml, "npc_face_frame"); gtk_object_set_user_data(GTK_OBJECT(widget), (gpointer) shape); char *label = g_strdup_printf("Face #%d", shape); gtk_frame_set_label(GTK_FRAME(widget), label); g_free(label); show_npc_face(); } /* * A choice was clicked in the 'schedule' dialog. */ void ExultStudio::schedule_btn_clicked ( GtkWidget *btn, // Button on the schedule dialog. gpointer data // Dialog itself. ) { ExultStudio *studio = ExultStudio::get_instance(); // Get name assigned in Glade. const char *name = glade_get_widget_name(btn); const char *numptr = name + 5; // Past "sched". int num = atoi(numptr); GtkWidget *schedwin = (GtkWidget *) data; GtkLabel *label = (GtkLabel *) gtk_object_get_user_data( GTK_OBJECT(schedwin)); // User data = schedule #. gtk_object_set_user_data(GTK_OBJECT(label), (gpointer) num); gtk_label_set_text(label, num >= 0 && num < 32 ? sched_names[num] : "-----"); cout << "Chose schedule " << num << endl; gtk_widget_hide(glade_xml_get_widget(studio->get_xml(), "schedule_dialog")); } /* * Set signal handler for each schedule button. */ static void Set_sched_btn ( GtkWidget *btn, gpointer data ) { gtk_signal_connect(GTK_OBJECT(btn), "clicked", GTK_SIGNAL_FUNC(ExultStudio::schedule_btn_clicked), data); } /* * Npc window's "set schedule" button. */ C_EXPORT void on_npc_set_sched ( GtkWidget *btn, // One of the 'set' buttons. gpointer user_data ) { static int first = 1; // To initialize signal handlers. const char *name = glade_get_widget_name(btn); const char *numptr = name + strlen(name) - 1; GladeXML *xml = ExultStudio::get_instance()->get_xml(); char lname[20]; // Set up label name. strcpy(lname, "npc_sched"); strcat(lname, numptr); // Same number as button. GtkLabel *label = GTK_LABEL(glade_xml_get_widget(xml, lname)); GtkContainer *btns = GTK_CONTAINER( glade_xml_get_widget(xml, "sched_btns")); GtkWidget *schedwin = glade_xml_get_widget(xml, "schedule_dialog"); if (!label || !btns || !schedwin) return; if (first) // First time? Set handlers. { first = 0; gtk_container_foreach(btns, Set_sched_btn, schedwin); } // Store label as dialog's data. gtk_object_set_user_data(GTK_OBJECT(schedwin), label); gtk_widget_show(schedwin); } /* * Received game position for schedule. */ static void Game_loc_response ( Exult_server::Msg_type id, unsigned char *data, int datalen, void *client ) { if (id != Exult_server::game_pos) return; // Get box with loc. spin btns. GtkBox *box = (GtkBox *) client; int tx = Read2(data); int ty = Read2(data); int tz = Read2(data); if (tz != 0) { EStudio::Alert("Non-zero height (%d) not yet supported", tz); return; } GList *list = g_list_first(box->children); GtkWidget *spin = ((GtkBoxChild *) list->data)->widget; gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), tx); list = g_list_next(list); spin = ((GtkBoxChild *) list->data)->widget; gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), ty); list = g_list_next(list); spin = ((GtkBoxChild *) list->data)->widget; gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), tz); } /* * One of the "Game" buttons to set location from current game position. */ C_EXPORT void on_sched_loc_clicked ( GtkWidget *btn, // One of the 'Game' buttons. gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); // Get location box. GtkBox *box = GTK_BOX(gtk_widget_get_parent(btn)); if (Send_data(studio->get_server_socket(), Exult_server::game_pos) == -1) cout << "Error sending message to server" << endl; else studio->set_msg_callback(Game_loc_response, box); } exult-1.2/mapedit/shapedraw.cc0000644000175000001440000001723007657400520012112 /** ** Shapedraw.cc - Manage a drawing area that shows one or more shapes. ** ** Written: 6/2/2001 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "shapedraw.h" #include "vgafile.h" #include "ibuf8.h" #include "u7drag.h" using std::cout; using std::endl; /* * Blit onto screen. */ void Shape_draw::show ( GdkDrawable *drawable, int x, int y, int w, int h // Area to blit. ) { int stride = iwin->get_line_width(); gdk_draw_indexed_image(drawable, drawgc, x, y, w, h, GDK_RGB_DITHER_NORMAL, iwin->get_bits() + y*stride + x, stride, palette); } /* * Draw one shape at a particular place. */ void Shape_draw::draw_shape ( Shape_frame *shape, int x, int y ) { shape->paint(iwin, x + shape->get_xleft(), y + shape->get_yabove()); } /* * Draw one shape at a particular place. */ void Shape_draw::draw_shape ( int shapenum, int framenum, int x, int y ) { if (shapenum < 0 || shapenum >= ifile->get_num_shapes()) return; Shape_frame *shape = ifile->get_shape(shapenum, framenum); if (shape) draw_shape(shape, x, y); } /* * Draw one shape's outline at a particular place. */ void Shape_draw::draw_shape_outline ( int shapenum, int framenum, int x, int y, unsigned char color // Color index for outline. ) { if (shapenum < 0 || shapenum >= ifile->get_num_shapes()) return; Shape_frame *shape = ifile->get_shape(shapenum, framenum); if (shape) { if (shape->is_rle()) shape->paint_rle_outline(iwin, x + shape->get_xleft(), y + shape->get_yabove(), color); else { int w = shape->get_width(), h = shape->get_height(); iwin->fill_line8(color, w, x, y); iwin->fill_line8(color, w, x, y + h - 1); iwin->fill8(color, 1, h, x, y); iwin->fill8(color, 1, h, x + w - 1, y); } } } /* * Draw a shape centered in the drawing area. */ void Shape_draw::draw_shape_centered ( int shapenum, // -1 to not draw shape. int framenum ) { iwin->fill8(255); // Background (transparent) color. if (shapenum < 0 || shapenum >= ifile->get_num_shapes()) return; Shape_frame *shape = ifile->get_shape(shapenum, framenum); if (!shape) return; // Get drawing area dimensions. gint winw = draw->allocation.width, winh = draw->allocation.height; draw_shape(shape, (winw - shape->get_width())/2, (winh - shape->get_height())/2); } /* * Create. */ Shape_draw::Shape_draw ( Vga_file *i, // Where they're kept. unsigned char *palbuf, // Palette, 3*256 bytes (rgb triples). GtkWidget *drw // Drawing area to use. ) : ifile(i), iwin(0), palette(0), draw(drw), drawgc(0), drop_callback(0), drop_user_data(0), dragging(false) { guint32 colors[256]; for (int i = 0; i < 256; i++) colors[i] = (palbuf[3*i]<<16)*4 + (palbuf[3*i+1]<<8)*4 + palbuf[3*i+2]*4; palette = gdk_rgb_cmap_new(colors, 256); } /* * Delete. */ Shape_draw::~Shape_draw ( ) { gdk_rgb_cmap_free(palette); delete iwin; } /* * Default render. */ void Shape_draw::render ( ) { } /* * Set background color and repaint. */ void Shape_draw::set_background_color ( guint32 c ) { palette->colors[255] = c; render(); show(); } /* * Configure the viewing window. */ void Shape_draw::configure ( ) { if (!draw->window) return; // Not ready yet. if (!iwin) // First time? { drawgc = gdk_gc_new(draw->window); // Foreground = yellow. gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (255<<8)); iwin = new Image_buffer8( draw->allocation.width, draw->allocation.height); } else if (iwin->get_width() != draw->allocation.width || iwin->get_height() != draw->allocation.height) { delete iwin; iwin = new Image_buffer8( draw->allocation.width, draw->allocation.height); } } /* * Shape was dropped. */ void Shape_draw::drag_data_received ( GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *seldata, guint info, guint time, gpointer udata // Should point to Shape_draw. ) { Shape_draw *draw = (Shape_draw *) udata; cout << "drag_data_received" << endl; if (draw->drop_callback && seldata->type == gdk_atom_intern(U7_TARGET_SHAPEID_NAME, 0) && seldata->format == 8 && seldata->length > 0) { int file, shape, frame; Get_u7_shapeid(seldata->data, file, shape, frame); (*draw->drop_callback)(file, shape, frame, draw->drop_user_data); } } /* * Set to accept drops from drag-n-drop of a shape. */ void Shape_draw::enable_drop ( Drop_callback callback, // Call this when shape dropped. void *udata // Passed to callback. ) { gtk_widget_realize(draw);//??????? #ifndef WIN32 drop_callback = callback; drop_user_data = udata; GtkTargetEntry tents[1]; tents[0].target = U7_TARGET_SHAPEID_NAME; tents[0].flags = 0; tents[0].info = U7_TARGET_SHAPEID; gtk_drag_dest_set(draw, GTK_DEST_DEFAULT_ALL, tents, 1, (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE)); gtk_signal_connect(GTK_OBJECT(draw), "drag_data_received", GTK_SIGNAL_FUNC(drag_data_received), this); #endif } /* * Set an icon for dragging FROM this area. */ void Shape_draw::set_drag_icon ( GdkDragContext *context, Shape_frame *shape // Shape to use for the icon. ) { int w = shape->get_width(), h = shape->get_height(), xright = shape->get_xright(), ybelow = shape->get_ybelow(); Image_buffer8 tbuf(w, h); // Create buffer to render to. tbuf.fill8(0xff); // Fill with 'transparent' pixel. unsigned char *tbits = tbuf.get_bits(); shape->paint(&tbuf, w - 1 - xright, h - 1 - ybelow); // Put shape on a pixmap. GdkPixmap *pixmap = gdk_pixmap_new(draw->window, w, h, -1); gdk_draw_indexed_image(pixmap, drawgc, 0, 0, w, h, GDK_RGB_DITHER_NORMAL, tbits, tbuf.get_line_width(), palette); int mask_stride = (w + 7)/8; // Round up to nearest byte. char *mdata = new char[mask_stride*h]; for (int y = 0; y < h; y++) // Do each row. // Do each byte. for (int b = 0; b < mask_stride; b++) { char bits = 0; unsigned char *vals = tbits + y*w + b*8; for (int i = 0; i < 8; i++) if (vals[i] != 0xff) bits |= (1<window, mdata, w, h); delete mdata; // This will be the shape dragged. gtk_drag_set_icon_pixmap(context, gdk_window_get_colormap(draw->window), pixmap, mask, w - 2 - xright, h - 2 - ybelow); gdk_pixmap_unref(pixmap); gdk_bitmap_unref(mask); } /* * Start dragging from here. * * Note: Sets 'dragging', which is only cleared by 'mouse_up()'. */ void Shape_draw::start_drag ( char *target, // Target (ie, U7_TARGET_SHAPEID_NAME). int id, // ID (ie, U7_TARGET_SHAPEID). GdkEvent *event // Event that started this. ) { if (dragging) return; dragging = true; GtkTargetEntry tents[1];// Set up for dragging. tents[0].target = target; tents[0].flags = 0; tents[0].info = id; GtkTargetList *tlist = gtk_target_list_new(&tents[0], 1); // ??+++ Do we need to free tlist? gtk_drag_begin(draw, tlist, (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE), 1, event); } exult-1.2/mapedit/chunklst.cc0000644000175000001440000007124007762470521011775 /** ** A GTK widget showing the chunks from 'u7chunks'. ** ** Written: 7/8/01 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef WIN32 #include "Windrag.h" #endif #include #ifdef XWIN #include #endif #include #include "chunklst.h" #include "vgafile.h" #include "ibuf8.h" #include "Flex.h" #include "u7drag.h" #include "exult_constants.h" #include "studio.h" #include "utils.h" #include "shapegroup.h" #include using std::cout; using std::endl; using std::strlen; using EStudio::Add_menu_item; using EStudio::Create_arrow_button; const int border = 2; // Border at bottom, sides of each // chunk. /* * Blit onto screen. */ void Chunk_chooser::show ( int x, int y, int w, int h // Area to blit. ) { Shape_draw::show(draw->window, x, y, w, h); if (selected >= 0) // Show selected. { Rectangle b = info[selected].box; // Draw yellow box. gdk_draw_rectangle(draw->window, drawgc, FALSE, b.x, b.y, b.w, b.h); } } /* * Send selected chunk# to Exult. */ void Chunk_chooser::tell_server ( ) { if (selected < 0) return; unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Write2(ptr, info[selected].num); ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server(Exult_server::set_edit_chunknum, buf, ptr - buf); } /* * Select an entry. This should be called after rendering * the chunk. */ void Chunk_chooser::select ( int new_sel ) { if (new_sel < 0 || new_sel >= info_cnt) return; // Bad value. selected = new_sel; tell_server(); // Tell Exult. enable_controls(); int chunknum = info[selected].num; // Remove prev. selection msg. // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); char buf[150]; // Show new selection. g_snprintf(buf, sizeof(buf), "Chunk %d", chunknum); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } /* * Render as many chunks as fit in the chunk chooser window. */ void Chunk_chooser::render ( ) { // Look for selected frame. int selchunk = -1, new_selected = -1; if (selected >= 0) // Save selection info. selchunk = info[selected].num; // Remove "selected" message. //gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); delete [] info; // Delete old info. list. // Get drawing area dimensions. gint winw = draw->allocation.width, winh = draw->allocation.height; // Provide more than enough room. info = new Chunk_info[256]; info_cnt = 0; // Count them. // Clear window first. iwin->fill8(255); // Background color. int index = index0; // 16x16 tiles, each 8x8 pixels. const int chunkw = 128, chunkh = 128; int total_cnt = get_count(); int y = border; // Show bottom if at least 1/2 vis. while (index < total_cnt && y + chunkh/2 + border <= winh) { int x = border; int cliph = y + chunkh <= winh ? chunkh : (winh - y); while (index < total_cnt && x + chunkw + border <= winw) { iwin->set_clip(x, y, chunkw, cliph); int chunknum = group ? (*group)[index] : index; render_chunk(chunknum, x, y); iwin->clear_clip(); // Store info. about where drawn. info[info_cnt].set(chunknum, x, y, chunkw, chunkh); if (chunknum == selchunk) // Found the selected chunk. new_selected = info_cnt; info_cnt++; index++; // Next chunk. x += chunkw + border; } y += chunkh + border; } if (new_selected == -1) unselect(false); else select(new_selected); } /* * Read in desired chunk if not already read. * * Output: ->chunk, stored in chunklist. */ unsigned char *Chunk_chooser::get_chunk ( int chunknum ) { unsigned char *data = chunklist[chunknum]; if (data) return data; // Already have it. // Get from server. unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; unsigned char *newptr = &buf[0]; Write2(ptr, chunknum); ExultStudio *studio = ExultStudio::get_instance(); int server_socket = studio->get_server_socket(); Exult_server::Msg_type id; // Expect immediate answer. int datalen; if (!studio->send_to_server(Exult_server::send_terrain, buf, ptr - buf) || !Exult_server::wait_for_response(server_socket, 100) || (datalen = Exult_server::Receive_data(server_socket, id, buf, sizeof(buf))) == -1 || id != Exult_server::send_terrain || Read2(newptr) != chunknum) { // No server? Get from file. data = new unsigned char[512]; chunklist[chunknum] = data; chunkfile.seekg(chunknum*512); chunkfile.read(reinterpret_cast(data), 512); if (!chunkfile.good()) { memset(data, 0, 512); cout << "Error reading chunk file" << endl; } } else set_chunk(buf, datalen); return chunklist[chunknum]; } /* * Update #chunks. */ void Chunk_chooser::update_num_chunks ( int new_num_chunks ) { num_chunks = new_num_chunks; GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(vscroll)); adj->upper = num_chunks; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); } /* * Set chunk with data from 'Exult'. * * NOTE: Don't call 'show()' or 'render()' here, since this gets called * from 'render()'. */ void Chunk_chooser::set_chunk ( unsigned char *data, // Message from server. int datalen ) { int tnum = Read2(data); // First the terrain #. int new_num_chunks = Read2(data); // Always sends total. datalen -= 4; if (datalen != 512) { cout << "Set_chunk: Wrong data length" << endl; return; } if (tnum < 0 || tnum >= new_num_chunks) { cout << "Set_chunk: Bad terrain # (" << tnum << ") received" << endl; return; } if (new_num_chunks != num_chunks) { // Update total #. if (new_num_chunks > num_chunks) chunklist.resize(new_num_chunks); update_num_chunks(new_num_chunks); } unsigned char *chunk = chunklist[tnum]; if (!chunk) // Not read yet? chunk = chunklist[tnum] = new unsigned char[512]; memcpy(chunk, data, 512); // Copy it in. } /* * Render one chunk. */ void Chunk_chooser::render_chunk ( int chunknum, // # to render. int xoff, int yoff // Where to draw it in iwin. ) { unsigned char *data = get_chunk(chunknum); int y = c_tilesize; for (int ty = 0; ty < c_tiles_per_chunk; ty++, y += c_tilesize) { int x = c_tilesize; for (int tx = 0; tx < c_tiles_per_chunk; tx++, x += c_tilesize) { unsigned char l = *data++; unsigned char h = *data++; int shapenum = l + 256*(h&0x3); int framenum = h >> 2; Shape_frame *s = ifile->get_shape(shapenum, framenum); if (s) s->paint(iwin, xoff + x - 1, yoff + y -1); } } } /* * Get # shapes we can display. */ int Chunk_chooser::get_count ( ) { return group ? group->size() : num_chunks; } /* * Configure the viewing window. */ gint Chunk_chooser::configure ( GtkWidget *widget, // The drawing area. GdkEventConfigure *event, gpointer data // ->Chunk_chooser ) { Chunk_chooser *chooser = (Chunk_chooser *) data; chooser->Shape_draw::configure(); chooser->render(); // Set new scroll amounts. int w = event->width, h = event->height; int per_row = (w - border)/(128 + border); int num_rows = (h - border)/(128 + border); int page_size = per_row*num_rows; GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE( chooser->vscroll)); adj->step_increment = per_row; adj->page_increment = page_size; adj->page_size = page_size; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); if (chooser->group) // Filtering? chooser->enable_drop(); // Can drop chunks here. return (TRUE); } /* * Handle an expose event. */ gint Chunk_chooser::expose ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Chunk_chooser. ) { Chunk_chooser *chooser = (Chunk_chooser *) data; chooser->show(event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Handle a mouse button press event. */ #ifdef WIN32 static bool win32_button = false; gint Chunk_chooser::win32_drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Chunk_chooser. ) { if (win32_button) { win32_button = false; // prepare the dragged data windragdata wdata; // This call allows us to recycle the data transfer initialization code. // It's clumsy, but far easier to maintain. drag_data_get(NULL, NULL, (GtkSelectionData *) &wdata, U7_TARGET_CHUNKID, 0, data); POINT pnt; GetCursorPos(&pnt); LPDROPSOURCE idsrc = (LPDROPSOURCE) new Windropsource(0, pnt.x, pnt.y); LPDATAOBJECT idobj = (LPDATAOBJECT) new Winstudioobj(wdata); DWORD dndout; HRESULT res = DoDragDrop(idobj, idsrc, DROPEFFECT_COPY, &dndout); if (FAILED(res)) { g_warning ("Oops! Something is wrong with OLE2 DnD.."); } delete idsrc; idobj->Release(); // Not sure if we really need this. However, it doesn't hurt either. } return true; }; #else gint Chunk_chooser::drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Shape_chooser. ) { Chunk_chooser *chooser = (Chunk_chooser *) data; if (!chooser->dragging && chooser->selected >= 0) chooser->start_drag(U7_TARGET_CHUNKID_NAME, U7_TARGET_CHUNKID, (GdkEvent *) event); return true; } #endif gint Chunk_chooser::mouse_press ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Chunk_chooser. ) { Chunk_chooser *chooser = (Chunk_chooser *) data; if (event->button == 4) { chooser->scroll(true); return(TRUE); } else if (event->button == 5) { chooser->scroll(false); return(TRUE); } int old_selected = chooser->selected; int i; // Search through entries. for (i = 0; i < chooser->info_cnt; i++) if (chooser->info[i].box.has_point( (int) event->x, (int) event->y)) { // Found the box? // if (i == old_selected) // return TRUE; // Indicate we can dra. #ifdef WIN32 // Here, we have to override GTK+'s Drag and Drop, which is non-OLE and // usually stucks outside the program window. I think it's because // the dragged shape only receives mouse motion events when the new mouse pointer // position is *still* inside the shape. So if you move the mouse too fast, // we are stuck. win32_button = true; #endif chooser->selected = i; chooser->locate_cx = chooser->locate_cy = -1; chooser->render(); chooser->show(); // Tell client. if (chooser->sel_changed) (*chooser->sel_changed)(); break; } if (i == chooser->info_cnt && event->button == 1) chooser->unselect(true);// Nothing under mouse. else if (event->button == 3) gtk_menu_popup(GTK_MENU(chooser->create_popup()), 0, 0, 0, 0, event->button, event->time); return (TRUE); } /* * Handle a mouse button-release event. */ static gint Mouse_release ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Shape_chooser. ) { Chunk_chooser *chooser = (Chunk_chooser *) data; chooser->mouse_up(); } /* * Someone wants the dragged chunk. */ void Chunk_chooser::drag_data_get ( GtkWidget *widget, // The view window. GdkDragContext *context, GtkSelectionData *seldata, // Fill this in. guint info, guint time, gpointer data // ->Chunk_chooser. ) { cout << "In DRAG_DATA_GET" << endl; Chunk_chooser *chooser = (Chunk_chooser *) data; if (chooser->selected < 0 || info != U7_TARGET_CHUNKID) return; // Not sure about this. guchar buf[30]; Chunk_info& shinfo = chooser->info[chooser->selected]; int len = Store_u7_chunkid(buf, shinfo.num); cout << "Setting selection data (" << shinfo.num << ')' << endl; #ifdef WIN32 windragdata *wdata = (windragdata *)seldata; wdata->assign(info, len, buf); #else // Make us owner of xdndselection. gtk_selection_owner_set(widget, gdk_atom_intern("XdndSelection", 0), time); // Set data. gtk_selection_data_set(seldata, gdk_atom_intern(U7_TARGET_CHUNKID_NAME, 0), 8, buf, len); #endif } /* * Another app. has claimed the selection. */ gint Chunk_chooser::selection_clear ( GtkWidget *widget, // The view window. GdkEventSelection *event, gpointer data // ->Chunk_chooser. ) { // Chunk_chooser *chooser = (Chunk_chooser *) data; cout << "SELECTION_CLEAR" << endl; return TRUE; } /* * Beginning of a drag. */ gint Chunk_chooser::drag_begin ( GtkWidget *widget, // The view window. GdkDragContext *context, gpointer data // ->Chunk_chooser. ) { cout << "In DRAG_BEGIN" << endl; Chunk_chooser *chooser = (Chunk_chooser *) data; if (chooser->selected < 0) return FALSE; // ++++Display a halt bitmap. #if 0 // Get ->chunk. Chunk_info& shinfo = chooser->info[chooser->selected]; Chunk_frame *chunk = chooser->ifile->get_chunk(shinfo.chunknum, shinfo.framenum); if (!chunk) return FALSE; int w = chunk->get_width(), h = chunk->get_height(), xright = chunk->get_xright(), ybelow = chunk->get_ybelow(); Image_buffer8 tbuf(w, h); // Create buffer to render to. tbuf.fill8(0xff); // Fill with 'transparent' pixel. unsigned char *tbits = tbuf.get_bits(); chunk->paint(&tbuf, w - 1 - xright, h - 1 - ybelow); // Put chunk on a pixmap. GdkPixmap *pixmap = gdk_pixmap_new(widget->window, w, h, -1); gdk_draw_indexed_image(pixmap, chooser->drawgc, 0, 0, w, h, GDK_RGB_DITHER_NORMAL, tbits, tbuf.get_line_width(), chooser->palette); int mask_stride = (w + 7)/8; // Round up to nearest byte. char *mdata = new char[mask_stride*h]; for (int y = 0; y < h; y++) // Do each row. // Do each byte. for (int b = 0; b < mask_stride; b++) { char bits = 0; unsigned char *vals = tbits + y*w + b*8; for (int i = 0; i < 8; i++) if (vals[i] != 0xff) bits |= (1<window, mdata, w, h); delete mdata; // This will be the chunk dragged. gtk_drag_set_icon_pixmap(context, gdk_window_get_colormap(widget->window), pixmap, mask, w - 2 - xright, h - 2 - ybelow); gdk_pixmap_unref(pixmap); gdk_bitmap_unref(mask); #endif return TRUE; } /* * Chunk was dropped here. */ void Chunk_chooser::drag_data_received ( GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *seldata, guint info, guint time, gpointer udata // Should point to Shape_draw. ) { Chunk_chooser *chooser = (Chunk_chooser *) udata; cout << "Chunk drag_data_received" << endl; if (seldata->type == gdk_atom_intern(U7_TARGET_CHUNKID_NAME, 0) && seldata->format == 8 && seldata->length > 0) { int cnum; Get_u7_chunkid(seldata->data, cnum); chooser->group->add(cnum); chooser->render(); // chooser->adjust_scrollbar(); ++++++Probably need to do this. } } /* * Set to accept drops from drag-n-drop of a chunk. */ void Chunk_chooser::enable_drop ( ) { if (drop_enabled) // More than once causes warning. return; drop_enabled = true; gtk_widget_realize(draw);//??????? #ifndef WIN32 GtkTargetEntry tents[1]; tents[0].target = U7_TARGET_CHUNKID_NAME; tents[0].flags = 0; tents[0].info = U7_TARGET_CHUNKID; gtk_drag_dest_set(draw, GTK_DEST_DEFAULT_ALL, tents, 1, (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE)); gtk_signal_connect(GTK_OBJECT(draw), "drag_data_received", GTK_SIGNAL_FUNC(drag_data_received), this); #endif } /* * Scroll to a new chunk/frame. */ void Chunk_chooser::scroll ( int newindex // Abs. index of leftmost to show. ) { int total = get_count(); if (index0 < newindex) // Going forwards? index0 = newindex < total ? newindex : total; else if (index0 > newindex) // Backwards? index0 = newindex >= 0 ? newindex : 0; render(); show(); } /* * Scroll up/down by one row. */ void Chunk_chooser::scroll ( bool upwards ) { GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(vscroll)); float delta = adj->step_increment; if (upwards) delta = -delta; adj->value += delta; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); scroll((gint) adj->value); } /* * Handle a scrollbar event. */ void Chunk_chooser::scrolled ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Chunk_chooser. ) { Chunk_chooser *chooser = (Chunk_chooser *) data; cout << "Scrolled to " << adj->value << '\n'; gint newindex = (gint) adj->value; chooser->scroll(newindex); } /* * Enable/disable controls after selection changed. */ void Chunk_chooser::enable_controls ( ) { if (selected == -1) // No selection. { gtk_widget_set_sensitive(loc_down, false); gtk_widget_set_sensitive(loc_up, false); if (!group) { gtk_widget_set_sensitive(move_down, false); gtk_widget_set_sensitive(move_up, false); } return; } gtk_widget_set_sensitive(loc_down, true); gtk_widget_set_sensitive(loc_up, true); if (!group) { gtk_widget_set_sensitive(move_down, info[selected].num < num_chunks - 1); gtk_widget_set_sensitive(move_up, info[selected].num > 0); } } /* * Handle popup menu items. */ static void on_insert_empty ( GtkMenuItem *item, gpointer udata ) { Chunk_chooser *chooser = (Chunk_chooser *) udata; chooser->insert(false); } static void on_insert_dup ( GtkMenuItem *item, gpointer udata ) { Chunk_chooser *chooser = (Chunk_chooser *) udata; chooser->insert(true); } static void on_delete ( GtkMenuItem *item, gpointer udata ) { Chunk_chooser *chooser = (Chunk_chooser *) udata; chooser->del(); } /* * Set up popup menu. */ GtkWidget *Chunk_chooser::create_popup ( ) { ExultStudio *studio = ExultStudio::get_instance(); Object_browser::create_popup(); // Create popup with groups, files. if (group != 0) // Filtering? Skip the rest. return popup; GtkWidget *mitem = Add_menu_item(popup, "New..."); GtkWidget *new_menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), new_menu); Add_menu_item(new_menu, "Empty", GTK_SIGNAL_FUNC(on_insert_empty), this); if (selected >= 0) { Add_menu_item(new_menu, "Duplicate", GTK_SIGNAL_FUNC(on_insert_dup), this); Add_menu_item(popup, "Delete", GTK_SIGNAL_FUNC(on_delete), this); } return popup; } /* * Create the list. */ Chunk_chooser::Chunk_chooser ( Vga_file *i, // Where they're kept. std::istream& cfile, // Chunks file (512bytes/entry). unsigned char *palbuf, // Palette, 3*256 bytes (rgb triples). int w, int h, // Dimensions. Shape_group *g // Filter, or null. ) : Object_browser(g), Shape_draw(i, palbuf, gtk_drawing_area_new()), chunkfile(cfile), info(0), info_cnt(0), sel_changed(0), locate_cx(-1), locate_cy(-1), drop_enabled(false), to_del(-1) { chunkfile.seekg(0, std::ios::end); // Figure total #chunks. num_chunks = chunkfile.tellg()/(c_tiles_per_chunk*c_tiles_per_chunk*2); chunklist.resize(num_chunks); // Init. list of ->'s to chunks. // Put things in a vert. box. GtkWidget *vbox = gtk_vbox_new(FALSE, 0); set_widget(vbox); // This is our "widget" gtk_widget_show(vbox); GtkWidget *hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); // A frame looks nice. GtkWidget *frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); // NOTE: draw is in Shape_draw. // Indicate the events we want. gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK); // Set "configure" handler. gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(configure), this); // Set "expose" handler. gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), this); // Set mouse click handler. gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(mouse_press), this); gtk_signal_connect(GTK_OBJECT(draw), "button_release_event", GTK_SIGNAL_FUNC(Mouse_release), this); // Mouse motion. gtk_signal_connect(GTK_OBJECT(draw), "drag_begin", GTK_SIGNAL_FUNC(drag_begin), this); #ifdef WIN32 // required to override GTK+ Drag and Drop gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(win32_drag_motion), this); #else gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(drag_motion), this); #endif gtk_signal_connect (GTK_OBJECT(draw), "drag_data_get", GTK_SIGNAL_FUNC(drag_data_get), this); gtk_signal_connect (GTK_OBJECT(draw), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear), this); gtk_container_add (GTK_CONTAINER (frame), draw); gtk_drawing_area_size(GTK_DRAWING_AREA(draw), w, h); gtk_widget_show(draw); // Want a scrollbar for the chunks. GtkObject *chunk_adj = gtk_adjustment_new(0, 0, num_chunks, 1, 4, 1.0); vscroll = gtk_vscrollbar_new(GTK_ADJUSTMENT(chunk_adj)); // Update window when it stops. gtk_range_set_update_policy(GTK_RANGE(vscroll), GTK_UPDATE_DELAYED); gtk_box_pack_start(GTK_BOX(hbox), vscroll, FALSE, TRUE, 0); // Set scrollbar handler. gtk_signal_connect(GTK_OBJECT(chunk_adj), "value_changed", GTK_SIGNAL_FUNC(scrolled), this); gtk_widget_show(vscroll); // At the bottom, status bar: GtkWidget *hbox1 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0); gtk_widget_show(hbox1); // At left, a status bar. sbar = gtk_statusbar_new(); sbar_sel = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "selection"); gtk_box_pack_start(GTK_BOX(hbox1), sbar, TRUE, TRUE, 0); gtk_widget_show(sbar); // Add locate/move controls to bottom. gtk_box_pack_start(GTK_BOX(vbox), create_controls(locate_controls|(!group ? move_controls : 0)), FALSE, FALSE, 0); } /* * Delete. */ Chunk_chooser::~Chunk_chooser ( ) { gtk_widget_destroy(get_widget()); delete [] info; int i; for (i = 0; i < num_chunks; i++)// Delete all the chunks. delete chunklist[i]; } /* * Handle response from server. * * Output: true if handled here. */ bool Chunk_chooser::server_response ( int id, unsigned char *data, int datalen ) { switch ((Exult_server::Msg_type) id) { case Exult_server::locate_terrain: locate_response(data, datalen); return true; case Exult_server::insert_terrain: insert_response(data, datalen); return true; case Exult_server::delete_terrain: delete_response(data, datalen); return true; case Exult_server::swap_terrain: swap_response(data, datalen); return true; case Exult_server::send_terrain: set_chunk(data, datalen); render(); show(); return true; default: return false; } } /* * Done with terrain editing. */ void Chunk_chooser::end_terrain_editing ( ) { // Clear out cache of chunks. for (int i = 0; i < num_chunks; i++) { delete chunklist[i]; chunklist[i] = 0; } render(); show(); } /* * Unselect. */ void Chunk_chooser::unselect ( bool need_render // 1 to render and show. ) { if (selected >= 0) { selected = -1; locate_cx = locate_cy = -1; if (need_render) { render(); show(); } if (sel_changed) // Tell client. (*sel_changed)(); } enable_controls(); // Enable/disable controls. char buf[150]; // Show new selection. if (info_cnt > 0) { // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); g_snprintf(buf, sizeof(buf), "Chunks %d to %d", info[0].num, info[info_cnt - 1].num); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } } /* * Locate terrain on game map. */ void Chunk_chooser::locate ( int dir // 1=downwards, -1=upwards, 0=from top. ) { if (selected < 0) return; // Shouldn't happen. bool upwards = false; unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; int tnum = info[selected].num; // Terrain #. int cx = locate_cx, cy = locate_cy; if (dir == 0) { cx = cy = -1; } else if (dir == -1) upwards = true; Write2(ptr, tnum); Write2(ptr, cx); // Current chunk, or -1. Write2(ptr, cy); *ptr++ = upwards ? 1 : 0; ExultStudio *studio = ExultStudio::get_instance(); if (!studio->send_to_server( Exult_server::locate_terrain, data, ptr - data)) to_del = -1; // In case we're deleting. } void Chunk_chooser::locate ( bool upwards ) { locate(upwards ? -1 : 1); } /* * Response from server to a 'locate'. */ void Chunk_chooser::locate_response ( unsigned char *data, int datalen ) { unsigned char *ptr = data; int tnum = Read2(ptr); if (selected < 0 || tnum != info[selected].num) { to_del = -1; return; // Not the current selection. } short cx = (short) Read2(ptr); // Get chunk found. short cy = (short) Read2(ptr); ptr++; // Skip upwards flag. if (!*ptr) { if (to_del >= 0 && to_del == tnum) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, tnum); ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server(Exult_server::delete_terrain, data, ptr - data); } else EStudio::Alert("Terrain %d not found.", tnum); } else { locate_cx = cx; // Save new chunk. locate_cy = cy; if (to_del >= 0) EStudio::Alert("Terrain %d is still in use", tnum); } to_del = -1; } /* * Insert a new chunk terrain into the list. */ void Chunk_chooser::insert ( bool dup ) { if (dup && selected < 0) return; // Shouldn't happen. unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; int tnum = selected >= 0 ? info[selected].num : -1; Write2(ptr, tnum); *ptr++ = dup ? 1 : 0; ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server( Exult_server::insert_terrain, data, ptr - data); } /* * Delete currently selected chunk if it's not being used. */ void Chunk_chooser::del ( ) { if (selected < 0) return; to_del = info[selected].num; locate(0); // See if it exists. } /* * Response from server to an 'insert'. */ void Chunk_chooser::insert_response ( unsigned char *data, int datalen ) { unsigned char *ptr = data; int tnum = (short) Read2(ptr); bool dup = *ptr++ ? true : false; bool okay = *ptr ? true : false; if (!*ptr) EStudio::Alert("Terrain insert failed."); else { // Insert in our list. unsigned char *data = new unsigned char[512]; if (dup && tnum >= 0 && tnum < num_chunks && chunklist[tnum]) memcpy(data, chunklist[tnum], 512); else memset(data, 0, 512); if (tnum >= 0 && tnum < num_chunks - 1) chunklist.insert(chunklist.begin() + tnum + 1, data); else // If -1, append to end. chunklist.push_back(data); update_num_chunks(num_chunks + 1); render(); show(); } } /* * Response from server to an 'delete'. */ void Chunk_chooser::delete_response ( unsigned char *data, int datalen ) { unsigned char *ptr = data; int tnum = (short) Read2(ptr); bool okay = *ptr ? true : false; if (!*ptr) EStudio::Alert("Terrain delete failed."); else { // Remove from our list. delete chunklist[tnum]; chunklist.erase(chunklist.begin() + tnum); update_num_chunks(num_chunks - 1); render(); show(); } } /* * Move currently-selected chunk up or down. */ void Chunk_chooser::move ( bool upwards ) { if (selected < 0) return; // Shouldn't happen. unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; int tnum = info[selected].num; if ((tnum == 0 && upwards) || (tnum == num_chunks - 1 && !upwards)) return; if (upwards) // Going to swap tnum & tnum+1. tnum--; Write2(ptr, tnum); ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server( Exult_server::swap_terrain, data, ptr - data); } /* * Response from server to a 'swap'. */ void Chunk_chooser::swap_response ( unsigned char *data, int datalen ) { unsigned char *ptr = data; int tnum = (short) Read2(ptr); bool okay = *ptr ? true : false; if (!*ptr) cout << "Terrain insert failed." << endl; else if (tnum >= 0 && tnum < num_chunks - 1) { unsigned char *tmp = get_chunk(tnum); chunklist[tnum] = get_chunk(tnum + 1); chunklist[tnum + 1] = tmp; if (selected >= 0) // Update selected. { if (info[selected].num == tnum) { // Moving downwards. if (selected >= info_cnt - 1) scroll(false); select(selected + 1); } else if (info[selected].num == tnum + 1) { if (selected <= 0) scroll(true); select(selected - 1); } } render(); show(); } } exult-1.2/mapedit/shapelst.h0000644000175000001440000001543407713365507011635 /** ** A GTK widget showing a list of shapes from an image file. ** ** Written: 7/25/99 - JSF **/ #ifndef INCL_SHAPELST #define INCL_SHAPELST 1 /* Copyright (C) 1999 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "objbrowse.h" #include "shapedraw.h" #include "rect.h" #include #include class Vga_file; class Image_buffer8; class Shapes_vga_file; class Editing_file; /* * Store information about an individual shape shown in the list. */ class Shape_entry { friend class Shape_chooser; int index; // Index in list. Equals shapenum if // not showing a 'group'. int shapenum, framenum; // The given shape/frame. Rectangle box; // Box where drawn. Shape_entry() { } void set(int ind, int shnum, int frnum, int rx, int ry, int rw, int rh) { index = ind; shapenum = shnum; framenum = frnum; box = Rectangle(rx, ry, rw, rh); } }; /* * This class manages a list of shapes from an image file. */ class Shape_chooser: public Object_browser, public Shape_draw { Shapes_vga_file *shapes_file; // Non-null if 'shapes.vga'. GtkWidget *sbar; // Status bar. guint sbar_sel; // Status bar context for selection. GtkWidget *fspin; // Spin button for frame #. GtkAdjustment *frame_adj; // Adjustment for frame spin btn. int framenum0; // Default frame # to display. Shape_entry *info; // An entry for each shape drawn. int info_cnt; // # entries in info. std::vector row_indices; // Index at start of each row. int row0; // Row # at top of window. int nrows; // Last #rows rendered. bool frames_mode; // Show all frames horizontally. int hoffset; // Horizontal offset in pixels (when in // frames_mode). void (*sel_changed)(); // Called when selection changes. // List of files being edited by an // external program (Gimp, etc.) static std::vector editing_files; static int check_editing_timer; // For monitoring files being edited. // Blit onto screen. virtual void show(int x, int y, int w, int h); virtual void show() { Shape_chooser::show(0, 0, draw->allocation.width, draw->allocation.height);} void tell_server_shape(); // Tell Exult what shape is selected. void select(int new_sel); // Show new selection. virtual void render(); // Draw list. virtual void set_background_color(guint32 c) { Shape_draw::set_background_color(c); } void render_frames(); // Show all frames. void scroll_to_frame(); // Scroll so sel. frame is visible. int next_row(int start); // Down/up 1 row. void goto_index(int index); // Get desired index in view. virtual int get_selected_id() { return selected < 0 ? -1 : info[selected].shapenum; } void scroll_vertical(int newindex); // Scroll. void adjust_vscrollbar(); // Set new scroll amounts. void adjust_hscrollbar(int newmax); virtual GtkWidget *create_popup(); // Popup menu. public: Shape_chooser(Vga_file *i, unsigned char *palbuf, int w, int h, Shape_group *g = 0, Shape_file_info *fi = 0); virtual ~Shape_chooser(); void set_shapes_file(Shapes_vga_file *sh) { shapes_file = sh; } void set_framenum0(int f) { framenum0 = f; } void shape_dropped_here(int file, int shapenum, int framenum); int get_count(); // Get # shapes we can display. virtual void search(const char *srch, int dir); virtual void locate(bool upwards); // Locate shape on game map. // Turn off selection. void unselect(bool need_render = true); int is_selected() // Is a shape selected? { return selected >= 0; } void set_selected_callback(void (*fun)()) { sel_changed = fun; } // Get selected shape, or return 0. int get_selected(int& shapenum, int& framenum) { if (selected == -1) return (0); shapenum = info[selected].shapenum; framenum = info[selected].framenum; return (1); } // Configure when created/resized. gint configure(GdkEventConfigure *event); // Blit to screen. static gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); // Handle mouse press. gint mouse_press(GtkWidget *widget, GdkEventButton *event); // Export current frame as a PNG. time_t export_png(const char *fname); // Export given image as a PNG. time_t export_png(const char *fname, Image_buffer8& img, int xoff, int yoff); // Export frames tiled. time_t export_tiled_png(const char *fname, int tiles, bool bycols); void edit_shape_info(); // Edit selected shape's info. // Edit selected shape-frame. void edit_shape(int tiles = 0, bool bycols = false); // Deal with list of files being edited // by an external prog. (Gimp). static gint check_editing_files_cb(gpointer data); static gint check_editing_files(); static void read_back_edited(Editing_file *ed); static void clear_editing_files(); // Import/export from file selector. static void export_frame(char *fname, gpointer user_data); static void import_frame(char *fname, gpointer user_data); void new_frame(); // Add/del. void from_font_toggled(bool on); void new_shape(); void create_new_shape(); void del_frame(); // Give dragged shape. static void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, gpointer data); // Someone else selected. static gint selection_clear(GtkWidget *widget, GdkEventSelection *event, gpointer data); static gint drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); // Handle scrollbar. static void vscrolled(GtkAdjustment *adj, gpointer data); static void hscrolled(GtkAdjustment *adj, gpointer data); // Handle spin-button for frames. static void frame_changed(GtkAdjustment *adj, gpointer data); static void all_frames_toggled(GtkToggleButton *btn, gpointer user_data); #ifdef WIN32 static gint win32_drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #else static gint drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #endif // Menu items: static void on_shapes_popup_info_activate( GtkMenuItem *item, gpointer udata); static void on_shapes_popup_edit_activate( GtkMenuItem *item, gpointer udata); static void on_shapes_popup_edtiles_activate( GtkMenuItem *item, gpointer udata); }; #endif exult-1.2/mapedit/execbox.cc0000644000175000001440000001647307647741317011614 /** ** Execbox.cc - Execute a command-line program and display its output. ** ** Written: 10/02/02 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "execbox.h" #include /* Debugging only */ #include using std::cout; using std::endl; #ifndef WIN32 #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include /* * Create. */ Exec_process::Exec_process ( ) : child_stdin(-1), child_stdout(-1), child_stderr(-1), child_pid(-1), reader(0), stdout_tag(-1), stderr_tag(-1) { } /* * Clean up. */ Exec_process::~Exec_process ( ) { kill_child(); } /* * End process and close pipes. */ void Exec_process::kill_child ( ) { if (child_pid > 0) kill(child_pid, SIGINT); if (child_stdin >= 0) close(child_stdin); if (child_stdout >= 0) close(child_stdout); if (child_stderr >= 0) close(child_stderr); if (stdout_tag >= 0) gdk_input_remove(stdout_tag); if (stderr_tag >= 0) gdk_input_remove(stderr_tag); child_pid = child_stdin = child_stdout = child_stderr = stdout_tag = stderr_tag = -1; } /* * Read from child & call client routine. */ static void Read_from_child ( gpointer data, // ->Exex_process gint id, // Pipe ID. GdkInputCondition condition ) { Exec_process *ex = (Exec_process *) data; ex->read_from_child(id); } void Exec_process::read_from_child ( int id // Pipe to read from. ) { char buf[1024]; int len; while ((len = read(id, buf, sizeof(buf))) > 0) if (reader) (*reader)(buf, len, 0, reader_data); int exit_code; if (!check_child(exit_code)) // Child done? { kill_child(); // Clean up. if (reader) // Tell client. (*reader)(0, 0, exit_code, reader_data); } } /* * Close a pipe. */ inline void Close_pipe ( int p[2] ) { if (p[0] >= 0) close(p[0]); if (p[1] >= 0) close(p[1]); } /* * Close 3 sets of pipes. */ static void Close_pipes ( int p0[2], int p1[2], int p2[2] ) { Close_pipe(p0); Close_pipe(p1); Close_pipe(p2); } /* * Execute a new process. * * Output: False if failed. */ bool Exec_process::exec ( const char *file, // PATH will be searched. char *argv[], // Args. 1st is filename, last is 0. Reader_fun rfun, // Called when child writes, exits. void *udata // User_data for rfun. ) { reader = rfun; // Store callback. reader_data = udata; // Pipes for talking to child: int stdin_pipe[2], stdout_pipe[2], stderr_pipe[2]; stdin_pipe[0] = stdin_pipe[1] = stdout_pipe[0] = stdout_pipe[1] = stderr_pipe[0] = stderr_pipe[1] = -1; kill_child(); // Kill running process. // Create pipes. if (pipe(stdin_pipe) != 0 || pipe(stdout_pipe) != 0 || pipe(stderr_pipe) != 0) { // Error. Close_pipes(stdin_pipe, stdout_pipe, stderr_pipe); return false; } child_pid = fork(); // Split in two. if (child_pid == -1) // Failed? { Close_pipes(stdin_pipe, stdout_pipe, stderr_pipe); return false; } if (child_pid == 0) // Are we the child? { close(0); // Want to read from the pipe. dup(stdin_pipe[0]); Close_pipe(stdin_pipe); // Done with these. close(1); // Write to stdout through pipe. dup(stdout_pipe[1]); Close_pipe(stdout_pipe); close(2); // Write to stderr through pipe. dup(stderr_pipe[1]); Close_pipe(stderr_pipe); execvp(file, argv); // Become the new command. exit(-1); // Gets here if exec failed. } // HERE, we're the parent. child_stdin = stdin_pipe[1]; // Writing here goes to child stdin. close(stdin_pipe[0]); child_stdout = stdout_pipe[0]; // This gets child's stdout. close(stdout_pipe[1]); child_stderr = stderr_pipe[0]; close(stderr_pipe[1]); cout << "Child_stdout is " << child_stdout << ", Child_stderr is " << child_stderr << endl; stdout_tag = gdk_input_add(child_stdout, GDK_INPUT_READ, Read_from_child, this); stderr_tag = gdk_input_add(child_stderr, GDK_INPUT_READ, Read_from_child, this); return true; } /* * See if child is still alive. * * Output: True if child is still running. * If false, exit code is returned in 'exit_code'. */ bool Exec_process::check_child ( int& exit_code // Exit code returned. ) { if (child_pid < 0) return false; // No child. int status; // Don't wait. int ret = waitpid(child_pid, &status, WNOHANG); if (ret != child_pid) return true; // Still running. else { cout << "Exec_box: Child done." << endl; exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1; return false; } } #endif /* * Create. */ Exec_box::Exec_box ( GtkTextView *b, GtkStatusbar *s, Exec_done_fun dfun, // Called when child exits. gpointer udata // Passed to dfun. ) : box(b), status(s), done_fun(dfun), user_data(udata) { executor = new Exec_process; status_ctx = gtk_statusbar_get_context_id(status, "execstatus"); // Keep one msg. always on stack. gtk_statusbar_push(status, status_ctx, ""); } /* * Close. */ Exec_box::~Exec_box ( ) { delete executor; // Kills child. } /* * Show status. */ void Exec_box::show_status ( const char *msg ) { gtk_statusbar_pop(status, status_ctx); gtk_statusbar_push(status, status_ctx, msg); } /* * Read from child & display in the text box. */ static void Exec_callback ( char *data, // Data read, or NULL. int datalen, // Length, or 0 if child exited. int exit_code, // Exit code if datalen = 0. void *user_data // ->Exex_box ) { Exec_box *box = (Exec_box *) user_data; box->read_from_child(data, datalen, exit_code); } void Exec_box::read_from_child ( char *data, // Data read, or NULL. int datalen, // Length, or 0 if child exited. int exit_code // Exit code if datalen = 0. ) { if (datalen > 0) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(box); gtk_text_buffer_insert_at_cursor(buffer,data,datalen); return; } if (exit_code == 0) // Child is done, so check result. show_status("Done: Success"); else show_status("Done: Errors occurred"); if (done_fun) done_fun(exit_code, this, user_data); } /* * Add a message to the box. */ void Exec_box::add_message ( const char *txt ) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(box); gtk_text_buffer_insert_at_cursor(buffer,txt,strlen(txt)); } /* * Execute a new process. * * Output: False if failed. */ bool Exec_box::exec ( const char *file, // PATH will be searched. char *argv[] // Args. 1st is filename, last is 0. ) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(box); gtk_text_buffer_set_text(buffer, "", 0); // Clear out old text if (!executor->exec(file, argv, Exec_callback, this)) return false; return true; } /* * End process. */ void Exec_box::kill_child ( ) { executor->kill_child(); } exult-1.2/mapedit/shapefile.cc0000644000175000001440000003256707717350542012113 /** ** Information about a shapes file. ** ** Written: 1/23/02 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "shapefile.h" #include "u7drag.h" #include "shapegroup.h" #include "shapevga.h" #include "shapelst.h" #include "chunklst.h" #include "paledit.h" #include "utils.h" #include "Flex.h" #include "exceptions.h" #include "combo.h" #include "studio.h" using std::vector; using std::string; using std::cerr; using std::endl; using std::ofstream; /* * Delete file and groups. */ Shape_file_info::~Shape_file_info ( ) { delete groups; delete browser; } /* * Get the main browser for this file, or create it. * * Output: ->browser. */ Object_browser *Shape_file_info::get_browser ( Shape_file_info *vgafile, unsigned char *palbuf ) { if (browser) return browser; // Okay. browser = create_browser(vgafile, palbuf, 0); // Add a reference (us). gtk_widget_ref(browser->get_widget()); return browser; } /* * Cleanup. */ Image_file_info::~Image_file_info ( ) { delete ifile; } /* * Create a browser for our data. */ Object_browser *Image_file_info::create_browser ( Shape_file_info *vgafile, // THE 'shapes.vga' file. unsigned char *palbuf, // Palette for displaying. Shape_group *g // Group, or 0. ) { Shape_chooser *chooser = new Shape_chooser(ifile, palbuf, 400, 64, g, this); // Fonts? Show 'A' as the default. if (strcasecmp(basename.c_str(), "fonts.vga") == 0) chooser->set_framenum0('A'); if (this == vgafile) // Main 'shapes.vga' file? { chooser->set_shapes_file( (Shapes_vga_file *) vgafile->get_ifile()); } return chooser; } /* * Write out if modified. May throw exception. */ void Image_file_info::flush ( ) { if (!modified) return; modified = false; int nshapes = ifile->get_num_shapes(); int shnum; // First read all entries. Shape **shapes = new Shape *[nshapes]; for (shnum = 0; shnum < nshapes; shnum++) shapes[shnum] = ifile->extract_shape(shnum); string filestr("/"); // Always write to 'patch'. filestr += basename; // !flex means single-shape. write_file(filestr.c_str(), shapes, nshapes, !ifile->is_flex()); delete [] shapes; // Tell Exult to reload this file. unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Write2(ptr, ifile->get_u7drag_type()); ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server(Exult_server::reload_shapes, buf, ptr - buf); } /* * Revert to what's on disk. * * Output: True (meaning we support 'revert'). */ bool Image_file_info::revert ( ) { if (modified) { ifile->load(pathname.c_str()); modified = false; } return true; } /* * Write a shape file. (Note: static method.) * May print an error. */ void Image_file_info::write_file ( const char *pathname, // Full path. Shape **shapes, // List of shapes to write. int nshapes, // # shapes. bool single // Don't write a FLEX file. ) { ofstream out; U7open(out, pathname); // May throw exception. if (single) { if (nshapes) shapes[0]->write(out); out.flush(); if (!out.good()) throw file_write_exception(pathname); out.close(); return; } Flex_writer writer(out, "Written by ExultStudio", nshapes); // Write all out. for (int shnum = 0; shnum < nshapes; shnum++) { shapes[shnum]->write(out); writer.mark_section_done(); } if (!writer.close()) throw file_write_exception(pathname); } /* * Cleanup. */ Chunks_file_info::~Chunks_file_info ( ) { delete file; } /* * Create a browser for our data. */ Object_browser *Chunks_file_info::create_browser ( Shape_file_info *vgafile, // THE 'shapes.vga' file. unsigned char *palbuf, // Palette for displaying. Shape_group *g // Group, or 0. ) { // Must be 'u7chunks' (for now). return new Chunk_chooser(vgafile->get_ifile(), *file, palbuf, 400, 64, g); } /* * Write out if modified. May throw exception. */ void Chunks_file_info::flush ( ) { if (!modified) return; modified = false; cerr << "Chunks should be stored by Exult" << endl; } /* * Init. */ Flex_file_info::Flex_file_info ( const char *bnm, // Basename, const char *pnm, // Full pathname, Flex *fl, // Flex file (we'll own it). Shape_group_file *g // Group file (or 0). ) : Shape_file_info(bnm, pnm, g), flex(fl), write_flat(false) { entries.resize(flex->number_of_objects()); lengths.resize(entries.size()); } /* * Init. for single-palette. */ Flex_file_info::Flex_file_info ( const char *bnm, // Basename, const char *pnm, // Full pathname, int size // File size. ) : Shape_file_info(bnm, pnm, 0), flex(0), write_flat(true) { entries.resize(size > 0); lengths.resize(entries.size()); if (size > 0) // Read in whole thing. { std::ifstream in; U7open(in, pnm); // Shouldn't fail. entries[0] = new char[size]; in.read(entries[0], size); lengths[0] = size; } } /* * Cleanup. */ Flex_file_info::~Flex_file_info ( ) { delete flex; int cnt = entries.size(); for (int i = 0; i < cnt; i++) delete entries[i]; } /* * Get i'th entry. */ char *Flex_file_info::get ( int i, size_t& len ) { if (i >= 0 && i < entries.size()) { if (!entries[i]) // Read it if necessary. { entries[i] = flex->retrieve(i, len); lengths[i] = len; } len = lengths[i]; return entries[i]; } else return 0; } /* * Set i'th entry. */ void Flex_file_info::set ( int i, char *newentry, // Allocated data that we'll own. int entlen // Length. ) { if (i < 0 || i > entries.size()) return; if (i == entries.size()) // Appending? { entries.push_back(newentry); lengths.push_back(entlen); } else { delete entries[i]; entries[i] = newentry; lengths[i] = entlen; } } /* * Swap the i'th and i+1'th entries. */ void Flex_file_info::swap ( int i ) { assert (i >= 0 && i < entries.size() - 1); char *tmpent = entries[i]; int tmplen = lengths[i]; entries[i] = entries[i + 1]; lengths[i] = lengths[i + 1]; entries[i + 1] = tmpent; lengths[i + 1] = tmplen; } /* * Remove i'th entry. */ void Flex_file_info::remove ( int i ) { assert (i >= 0 && i < entries.size()); delete entries[i]; // Free memory. entries.erase(entries.begin() + i); lengths.erase(lengths.begin() + i); } /* * Create a browser for our data. */ Object_browser *Flex_file_info::create_browser ( Shape_file_info *vgafile, // THE 'shapes.vga' file. unsigned char *palbuf, // Palette for displaying. Shape_group *g // Group, or 0. ) { const char *bname = basename.c_str(); if (strcasecmp(bname, "palettes.flx") == 0 || strcasecmp(".pal", bname + strlen(bname) - 4) == 0) return new Palette_edit(this); return new Combo_chooser(vgafile->get_ifile(), this, palbuf, 400, 64, g); } /* * Write out if modified. May throw exception. */ void Flex_file_info::flush ( ) { if (!modified) return; modified = false; int cnt = entries.size(); size_t len; int i; for (i = 0; i < cnt; i++) // Make sure all are read. { if (!entries[i]) get(i, len); } ofstream out; string filestr("/"); // Always write to 'patch'. filestr += basename; U7open(out, filestr.c_str()); // May throw exception. if (cnt <= 1 && write_flat) // Write flat file. { if (cnt) out.write(entries[0], lengths[0]); out.close(); if (!out.good()) throw file_write_exception(filestr.c_str()); return; } Flex_writer writer(out, "Written by ExultStudio", cnt); // Write all out. for (int i = 0; i < cnt; i++) { out.write(entries[i], lengths[i]); writer.mark_section_done(); } if (!writer.close()) throw file_write_exception(filestr.c_str()); } /* * Revert to what's on disk. * * Output: True (meaning we support 'revert'). */ bool Flex_file_info::revert ( ) { if (!modified) return true; modified = false; int cnt = entries.size(); for (int i = 0; i < cnt; i++) { delete entries[i]; entries[i] = 0; lengths[i] = 0; } if (flex) { cnt = flex->number_of_objects(); entries.resize(cnt); lengths.resize(entries.size()); } else // Single palette. { std::ifstream in; U7open(in, pathname.c_str()); // Shouldn't fail. in.seekg(0, std::ios::end); // Figure size. int sz = in.tellg(); cnt = sz > 0 ? 1 : 0; entries.resize(cnt); lengths.resize(entries.size()); in.seekg(0); if (cnt) { entries[0] = new char[sz]; in.read(entries[0], sz); lengths[0] = sz; } } return true; } /* * Delete set's entries. */ Shape_file_set::~Shape_file_set ( ) { for (vector::iterator it = files.begin(); it != files.end(); ++it) delete (*it); } /* * This routines tries to create files that don't yet exist. * * Output: true if successful. */ static bool Create_file ( const char *basename, // Base file name. const string& pathname // Full name. ) { int namelen = strlen(basename); if (strcasecmp(".flx", basename + namelen - 4) == 0) { // We can create an empty flx. ofstream out; U7open(out, pathname.c_str()); // May throw exception. Flex_writer writer(out, "Written by ExultStudio", 0); if (!writer.close()) throw file_write_exception(pathname.c_str()); return true; } else if (strcasecmp(".pal", basename + namelen - 4) == 0) { // Empty 1-palette file. ofstream out; U7open(out, pathname.c_str()); // May throw exception. out.close(); // Empty file. return true; } return false; // Might add more later. } /* * Create a new 'Shape_file_info', or return existing one. * * Output: ->file info, or 0 if error. */ Shape_file_info *Shape_file_set::create ( const char *basename // Like 'shapes.vga'. ) { // Already have it open? for (vector::iterator it = files.begin(); it != files.end(); ++it) if (strcasecmp((*it)->basename.c_str(), basename) == 0) return *it; // Found it. // Look in 'static', 'patch'. string sstr = string("/") + basename; string pstr = string("/") + basename; const char *spath = sstr.c_str(), *ppath = pstr.c_str(); bool sexists = U7exists(spath); bool pexists = U7exists(ppath); if (!sexists && !pexists) // Neither place. Try to create. if (!(pexists = Create_file(basename, ppath))) return 0; // Use patch file if it exists. const char *fullname = pexists ? ppath : spath; string group_name(basename); // Create groups file. group_name += ".grp"; Shape_group_file *groups = new Shape_group_file(group_name.c_str()); if (strcasecmp(basename, "shapes.vga") == 0) return append(new Image_file_info(basename, fullname, new Shapes_vga_file(spath, U7_SHAPE_SHAPES, ppath), groups)); else if (strcasecmp(basename, "gumps.vga") == 0) return append(new Image_file_info(basename, fullname, new Vga_file(spath, U7_SHAPE_GUMPS, ppath), groups)); else if (strcasecmp(basename, "faces.vga") == 0) return append(new Image_file_info(basename, fullname, new Vga_file(spath, U7_SHAPE_FACES, ppath), groups)); else if (strcasecmp(basename, "sprites.vga") == 0) return append(new Image_file_info(basename, fullname, new Vga_file(spath, U7_SHAPE_SPRITES, ppath), groups)); else if (strcasecmp(basename, "paperdol.vga") == 0) return append(new Image_file_info(basename, fullname, new Vga_file(spath, U7_SHAPE_PAPERDOL, ppath), groups)); else if (strcasecmp(basename, "fonts.vga") == 0) return append(new Image_file_info(basename, fullname, new Vga_file(spath, U7_SHAPE_FONTS, ppath), groups)); else if (strcasecmp(basename, "u7chunks") == 0) { std::ifstream *file = new std::ifstream; U7open(*file, fullname); return append(new Chunks_file_info(basename, fullname, file, groups)); } else if (strcasecmp(basename, "combos.flx") == 0 || strcasecmp(basename, "palettes.flx") == 0) return append(new Flex_file_info(basename, fullname, new Flex(fullname), groups)); else if (strcasecmp(".pal", basename + strlen(basename) - 4) == 0) { // Single palette? std::ifstream in; U7open(in, fullname); in.seekg(0, std::ios::end); // Figure size. int sz = in.tellg(); return append(new Flex_file_info(basename, fullname, sz)); } else // Not handled above? { // Get image file for this path. Vga_file *ifile = new Vga_file(spath, U7_SHAPE_UNK, ppath); if (ifile->is_good()) return append(new Image_file_info(basename, fullname, ifile, groups)); delete ifile; } cerr << "Error opening image file '" << basename << "'.\n"; return 0; } /* * Write any modified image files. */ void Shape_file_set::flush ( ) { for (vector::iterator it = files.begin(); it != files.end(); ++it) (*it)->flush(); } /* * Any files modified? */ bool Shape_file_set::is_modified ( ) { for (vector::iterator it = files.begin(); it != files.end(); ++it) if ((*it)->modified) return true; return false; } exult-1.2/mapedit/compile.cc0000644000175000001440000000573507647741316011605 /** ** Compile.cc - Run usecode compiler and show results. ** ** Written: 10/08/02 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "studio.h" #include "exult_constants.h" #include "utils.h" #include "execbox.h" using std::cout; using std::endl; using std::string; /* * "Compile" button */ C_EXPORT void on_compile_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->compile(); } /* * "Halt" button. */ C_EXPORT void on_halt_compile_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->halt_compile(); } /* * Called when UCC is done. */ void Ucc_done ( int exit_code, Exec_box *box, // Box that called this. gpointer user_data // Not used. ) { if (exit_code == 0) // Success? { ExultStudio::get_instance()->reload_usecode(); box->add_message("Reloaded usecode\n"); } } /* * Open the compile window. */ void ExultStudio::open_compile_window ( ) { if (!compilewin) // First time? { compilewin = glade_xml_get_widget( app_xml, "compile_win" ); compile_box = new Exec_box( GTK_TEXT_VIEW( glade_xml_get_widget(app_xml, "compile_msgs")), GTK_STATUSBAR( glade_xml_get_widget(app_xml, "compile_status")), Ucc_done, 0); } gtk_widget_show(compilewin); } /* * Compile. */ void ExultStudio::compile ( bool if_needed // Means check timestamps. ) { // Get source (fixed, for now). string source("/usecode.uc"); source = get_system_path(source); string obj("/usecode"); obj = get_system_path(obj); if (!U7exists(source)) { if (!if_needed) EStudio::Alert("Source '%s' doesn't exist", source.c_str()); return; // No source. } // ++++++Check timestamps. open_compile_window(); // Make sure it's open. const char *argv[8]; // Set up args. argv[0] = "ucc"; // Program to run. argv[1] = "-o"; // Specify output. argv[2] = obj.c_str(); argv[3] = source.c_str(); // What to compile. // ++++++Which game type (SI/BG)? argv[4] = 0; // NULL. if (!compile_box->exec("ucc", (char **) argv)) EStudio::Alert("Error executing usecode compiler ('ucc')"); } /* * Halt compilation. */ void ExultStudio::halt_compile ( ) { if (compile_box) compile_box->kill_child(); } exult-1.2/mapedit/paledit.cc0000644000175000001440000006061607657400724011572 /** ** A GTK widget showing a palette's colors. ** ** Written: 12/24/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #ifdef XWIN #include #endif #include #include "paledit.h" #include "u7drag.h" #include "utils.h" #include #include #include #include #include "studio.h" #include "shapefile.h" using std::cout; using std::endl; using std::string; using std::vector; using std::ostream; using std::ofstream; using std::setw; using std::ifstream; using EStudio::Prompt; using EStudio::Alert; /* * Write out a single palette to a buffer. */ static void Write_palette ( unsigned char *buf, // 3*256 bytes. GdkRgbCmap *pal // Palette to write. ) { for (int i = 0; i < 256; i++) { int r = (pal->colors[i]>>16)&255, g = (pal->colors[i]>>8)&255, b = pal->colors[i]&255; buf[3*i] = r/4; // Range 0-63. buf[3*i + 1] = g/4; buf[3*i + 2] = b/4; } } /* * Blit onto screen. */ inline void Palette_edit::show ( int x, int y, int w, int h // Area to blit. ) { int stride = draw->allocation.width; gdk_draw_indexed_image(draw->window, drawgc, x, y, w, h, GDK_RGB_DITHER_NORMAL, image + y*stride + x, stride, palettes[cur_pal]); if (selected >= 0) // Show selected. // Draw yellow box. gdk_draw_rectangle(draw->window, drawgc, FALSE, selected_box.x, selected_box.y, selected_box.w, selected_box.h); } /* * Select an entry. This should be called after rendering * the shape. */ void Palette_edit::select ( int new_sel ) { selected = new_sel; // Remove prev. selection msg. gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); char buf[150]; // Show new selection. g_snprintf(buf, sizeof(buf), "Color %d (0x%02x)", new_sel, new_sel); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } /* * Load/reload from file. */ void Palette_edit::load ( ) { // Free old. for (vector::iterator it = palettes.begin(); it != palettes.end(); ++it) gdk_rgb_cmap_free(*it); int cnt = flex_info->size(); palettes.resize(cnt); // Set size of list. if (!cnt) // No palettes? new_palette(); // Create 1 blank palette. else { for (int pnum = 0; pnum < cnt; pnum++) { size_t len; unsigned char *buf = (unsigned char *) flex_info->get(pnum, len); assert(len = 3*256); guint32 colors[256]; for (int i = 0; i < 256; i++) colors[i] = (buf[3*i]<<16)*4 + (buf[3*i+1]<<8)*4 + buf[3*i+2]*4; palettes[pnum] = gdk_rgb_cmap_new(colors, 256); } } } /* * Draw the palette. This need only be called when it changes. */ void Palette_edit::render ( ) { int neww = draw->allocation.width, newh = draw->allocation.height; // Changed size? if (neww != width || newh != height) { delete image; width = neww; height = newh; image = new guchar[width*height]; } // Figure cell size. int eachw = width/16, eachh = height/16; // Figure extra pixels. int extraw = width%16, extrah = height%16; int color = 0; // Color index. int cury = 0; unsigned char *out = image; for (int y = 0; y < 16; y++, color += 16) { int curx = 0; int stopy = cury + eachh + (y < extrah); for ( ; cury < stopy; cury++) for (int x = 0, c = color; x < 16; x++, c++) { int cntx = eachw + (x < extraw); while (cntx--) *out++ = c; } } if (selected >= 0) // Update selected box. { int selx = selected%16, sely = selected/16; selected_box.x = selx*eachw; selected_box.y = sely*eachh; selected_box.w = eachw; selected_box.h = eachh; if (selx < extraw) // Watch for extra pixels. { selected_box.w++; selected_box.x += selx; } else selected_box.x += extraw; if (sely < extrah) { selected_box.h++; selected_box.y += sely; } else selected_box.y += extrah; select(selected); } } /* * Color box was closed. */ int Palette_edit::color_closed ( GtkWidget *dlg, GdkEvent *event, gpointer data ) { cout << "color_closed" << endl; Palette_edit *paled = (Palette_edit *) data; paled->colorsel = 0; return FALSE; } /* * 'Cancel' was hit in the color selector. */ void Palette_edit::color_cancel ( GtkWidget *dlg, gpointer data ) { Palette_edit *paled = (Palette_edit *) data; if (paled->colorsel) gtk_widget_destroy(GTK_WIDGET(paled->colorsel)); paled->colorsel = 0; } /* * 'Okay' was hit in the color selector. */ void Palette_edit::color_okay ( GtkWidget *dlg, gpointer data ) { Palette_edit *paled = (Palette_edit *) data; if (paled->colorsel) { gdouble rgb[3]; gtk_color_selection_get_color( GTK_COLOR_SELECTION(paled->colorsel->colorsel), rgb); unsigned char r = (unsigned char) (rgb[0]*256), g = (unsigned char) (rgb[1]*256), b = (unsigned char) (rgb[2]*256); if (paled->selected >= 0) paled->palettes[paled->cur_pal]->colors[ paled->selected] = (r<<16) + (g<<8) + b; gtk_widget_destroy(GTK_WIDGET(paled->colorsel)); // Send to flex file. paled->update_flex(paled->cur_pal); paled->render(); paled->show(); } paled->colorsel = 0; } /* * Handle double-click on a color by bringing up a color-selector. */ void Palette_edit::double_clicked ( ) { cout << "Double-clicked" << endl; if (selected < 0 || colorsel) // Only one at a time. return; // Nothing selected. char buf[150]; // Show new selection. g_snprintf(buf, sizeof(buf), "Color %d (0x%02x)", selected, selected); colorsel = GTK_COLOR_SELECTION_DIALOG( gtk_color_selection_dialog_new(buf)); // Set mouse click handler. gtk_signal_connect(GTK_OBJECT(colorsel->ok_button), "clicked", GTK_SIGNAL_FUNC(color_okay), this); gtk_signal_connect(GTK_OBJECT(colorsel->cancel_button), "clicked", GTK_SIGNAL_FUNC(color_cancel), this); // Set delete handler. gtk_signal_connect(GTK_OBJECT(colorsel), "delete_event", GTK_SIGNAL_FUNC(color_closed), this); // Get color. guint32 c = palettes[cur_pal]->colors[selected]; gdouble rgb[3]; rgb[0] = ((double) ((c>>16)&0xff))/256; rgb[1] = ((double) ((c>>8)&0xff))/256; rgb[2] = ((double) ((c>>0)&0xff))/256; gtk_color_selection_set_color(GTK_COLOR_SELECTION(colorsel->colorsel), rgb); gtk_widget_show(GTK_WIDGET(colorsel)); } /* * Configure the viewing window. */ gint Palette_edit::configure ( GtkWidget *widget, // The view window. GdkEventConfigure *event, gpointer data // ->Palette_edit ) { Palette_edit *paled = (Palette_edit *) data; if (!paled->width) // First time? { paled->drawgc = gdk_gc_new(widget->window); // Foreground = yellow. gdk_rgb_gc_set_foreground(paled->drawgc, (255<<16) + (255<<8)); } paled->render(); return (TRUE); } /* * Handle an expose event. */ gint Palette_edit::expose ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Palette_edit. ) { Palette_edit *paled = (Palette_edit *) data; paled->show(event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Handle a mouse button press event. */ gint Palette_edit::mouse_press ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Palette_edit. ) { Palette_edit *paled = (Palette_edit *) data; if (event->button == 4 || event->button == 5) // mouse wheel return (TRUE); if (paled->colorsel) return (TRUE); // Already editing a color. int old_selected = paled->selected; int width = paled->width, height = paled->height; int eventx = (int) event->x, eventy = (int) event->y; // Figure cell size. int eachw = width/16, eachh = height/16; // Figure extra pixels. int extraw = width%16, extrah = height%16; int extrax = extraw*(eachw + 1);// Total length of extra-sized boxes. int extray = extrah*(eachh + 1); int selx, sely; // Gets box indices. if (eventx < extrax) selx = eventx/(eachw + 1); else selx = extraw + (eventx - extrax)/eachw; if (eventy < extray) sely = eventy/(eachh + 1); else sely = extrah + (eventy - extray)/eachh; paled->selected = sely*16 + selx; if (paled->selected == old_selected) { // Same square. Check for dbl-click. if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS) paled->double_clicked(); } else { paled->render(); paled->show(); } if (event->button == 3) gtk_menu_popup(GTK_MENU(paled->create_popup()), 0, 0, 0, 0, event->button, event->time); return (TRUE); } /* * Someone wants the dragged shape. */ void Palette_edit::drag_data_get ( GtkWidget *widget, // The view window. GdkDragContext *context, GtkSelectionData *seldata, // Fill this in. guint info, guint time, gpointer data // ->Palette_edit. ) { cout << "In DRAG_DATA_GET" << endl; Palette_edit *paled = (Palette_edit *) data; #if 0 if (paled->selected < 0 || info != U7_TARGET_SHAPEID) return; // Not sure about this. guchar buf[30]; int file = U7_SHAPE_SHAPES; // +++++For now. Shape_info& shinfo = paled->info[paled->selected]; int len = Store_u7_shapeid(buf, file, shinfo.shapenum, shinfo.framenum); cout << "Setting selection data (" << shinfo.shapenum << '/' << shinfo.framenum << ')' << endl; // Make us owner of xdndselection. gtk_selection_owner_set(widget, gdk_atom_intern("XdndSelection", 0), time); // Set data. gtk_selection_data_set(seldata, gdk_atom_intern(U7_TARGET_SHAPEID_NAME, 0), 8, buf, len); #endif } /* * Another app. has claimed the selection. */ gint Palette_edit::selection_clear ( GtkWidget *widget, // The view window. GdkEventSelection *event, gpointer data // ->Palette_edit. ) { // Palette_edit *paled = (Palette_edit *) data; cout << "SELECTION_CLEAR" << endl; return TRUE; } /* * Beginning of a drag. */ gint Palette_edit::drag_begin ( GtkWidget *widget, // The view window. GdkDragContext *context, gpointer data // ->Palette_edit. ) { cout << "In DRAG_BEGIN" << endl; Palette_edit *paled = (Palette_edit *) data; // Maybe someday. return TRUE; } /* * Handle a change to the 'Palette #' spin button. */ void Palette_edit::palnum_changed ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Shape_chooser. ) { Palette_edit *ed = (Palette_edit *) data; gint newnum = (gint) adj->value; ed->show_palette(newnum); ed->render(); ed->show(); ed->enable_controls(); } /* * Callbacks for buttons: */ void on_exportbtn_clicked (GtkButton *button, gpointer user_data) { GtkFileSelection *fsel = Create_file_selection( "Export palette to text format", (File_sel_okay_fun) Palette_edit::export_palette, user_data); gtk_widget_show(GTK_WIDGET(fsel)); } void on_importbtn_clicked (GtkButton *button, gpointer user_data) { GtkFileSelection *fsel = Create_file_selection( "Import palette from text format", (File_sel_okay_fun) Palette_edit::import_palette, user_data); gtk_widget_show(GTK_WIDGET(fsel)); } void on_insert_btn_clicked (GtkButton *button, gpointer user_data) { Palette_edit *ed = (Palette_edit *) user_data; ed->add_palette(); } void on_remove_btn_clicked (GtkButton *button, gpointer user_data) { Palette_edit *ed = (Palette_edit *) user_data; ed->remove_palette(); } void on_up_btn_clicked (GtkButton *button, gpointer user_data) { Palette_edit *ed = (Palette_edit *) user_data; ed->move_palette(true); } void on_down_btn_clicked (GtkButton *button, gpointer user_data) { Palette_edit *ed = (Palette_edit *) user_data; ed->move_palette(false); } /* * Create box with 'Palette #', 'Import', 'Move' controls. */ GtkWidget *Palette_edit::create_controls ( ) { // Create main box. GtkWidget *topframe = gtk_frame_new (NULL); gtk_widget_show(topframe); GtkWidget *vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_container_add (GTK_CONTAINER (topframe), vbox); GtkWidget *hbox0 = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox0); gtk_box_pack_start(GTK_BOX(vbox), hbox0, TRUE, TRUE, 2); /* * The 'Edit' controls. */ GtkWidget *frame = gtk_frame_new ("Edit"); gtk_widget_show(frame); gtk_box_pack_start (GTK_BOX (hbox0), frame, FALSE, FALSE, 2); GtkWidget *hbuttonbox = gtk_hbutton_box_new (); gtk_widget_show (hbuttonbox); gtk_container_add (GTK_CONTAINER (frame), hbuttonbox); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_START); gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 0); insert_btn = gtk_button_new_with_label ("New"); gtk_widget_show (insert_btn); gtk_container_add (GTK_CONTAINER (hbuttonbox), insert_btn); GTK_WIDGET_SET_FLAGS (insert_btn, GTK_CAN_DEFAULT); remove_btn = gtk_button_new_with_label ("Remove"); gtk_widget_show (remove_btn); gtk_container_add (GTK_CONTAINER (hbuttonbox), remove_btn); GTK_WIDGET_SET_FLAGS (remove_btn, GTK_CAN_DEFAULT); gtk_signal_connect (GTK_OBJECT (insert_btn), "clicked", GTK_SIGNAL_FUNC (on_insert_btn_clicked), this); gtk_signal_connect (GTK_OBJECT (remove_btn), "clicked", GTK_SIGNAL_FUNC (on_remove_btn_clicked), this); /* * The 'Move' controls. */ frame = gtk_frame_new ("Move"); gtk_widget_show(frame); gtk_box_pack_start (GTK_BOX (hbox0), frame, FALSE, FALSE, 2); GtkWidget *bbox = gtk_hbox_new(TRUE, 0); gtk_widget_show(bbox); gtk_container_add(GTK_CONTAINER (frame), bbox); down_btn = gtk_button_new(); gtk_widget_show (down_btn); gtk_box_pack_start (GTK_BOX (bbox), down_btn, FALSE, FALSE, 0); GTK_WIDGET_SET_FLAGS (down_btn, GTK_CAN_DEFAULT); GtkWidget *arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show(arrow); gtk_container_add(GTK_CONTAINER(down_btn), arrow); up_btn = gtk_button_new(); gtk_widget_show (up_btn); gtk_box_pack_start (GTK_BOX (bbox), up_btn, FALSE, FALSE, 0); GTK_WIDGET_SET_FLAGS (up_btn, GTK_CAN_DEFAULT); arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show(arrow); gtk_container_add(GTK_CONTAINER(up_btn), arrow); gtk_signal_connect (GTK_OBJECT (down_btn), "clicked", GTK_SIGNAL_FUNC (on_down_btn_clicked), this); gtk_signal_connect (GTK_OBJECT (up_btn), "clicked", GTK_SIGNAL_FUNC (on_up_btn_clicked), this); /* * The 'File' controls. */ frame = gtk_frame_new ("File"); gtk_widget_show(frame); gtk_box_pack_start (GTK_BOX (hbox0), frame, FALSE, FALSE, 2); hbuttonbox = gtk_hbutton_box_new (); gtk_widget_show (hbuttonbox); gtk_container_add (GTK_CONTAINER (frame), hbuttonbox); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_START); gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 0); GtkWidget *importbtn = gtk_button_new_with_label ("Import"); gtk_widget_show (importbtn); gtk_container_add (GTK_CONTAINER (hbuttonbox), importbtn); GTK_WIDGET_SET_FLAGS (importbtn, GTK_CAN_DEFAULT); GtkWidget *exportbtn = gtk_button_new_with_label ("Export"); gtk_widget_show (exportbtn); gtk_container_add (GTK_CONTAINER (hbuttonbox), exportbtn); GTK_WIDGET_SET_FLAGS (exportbtn, GTK_CAN_DEFAULT); gtk_signal_connect (GTK_OBJECT (importbtn), "clicked", GTK_SIGNAL_FUNC (on_importbtn_clicked), this); gtk_signal_connect (GTK_OBJECT (exportbtn), "clicked", GTK_SIGNAL_FUNC (on_exportbtn_clicked), this); return topframe; } /* * Enable/disable controls after changes. */ void Palette_edit::enable_controls ( ) { // Can't delete last one. gtk_widget_set_sensitive(remove_btn, cur_pal >= 0 && palettes.size() > 1); if (cur_pal == -1) // No palette? { gtk_widget_set_sensitive(down_btn, false); gtk_widget_set_sensitive(up_btn, false); gtk_widget_set_sensitive(remove_btn, false); } else { gtk_widget_set_sensitive(down_btn, cur_pal < palettes.size() - 1); gtk_widget_set_sensitive(up_btn, cur_pal > 0); gtk_widget_set_sensitive(remove_btn, palettes.size() > 1); } } /* * Set up box. */ void Palette_edit::setup ( ) { // Put things in a vert. box. GtkWidget *vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); set_widget(vbox); // A frame looks nice. GtkWidget *frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); draw = gtk_drawing_area_new(); // Create drawing area window. // gtk_drawing_area_size(GTK_DRAWING_AREA(draw), w, h); // Indicate the events we want. gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK); // Set "configure" handler. gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(configure), this); // Set "expose" handler. gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), this); // Set mouse click handler. gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(mouse_press), this); // Mouse motion. gtk_signal_connect(GTK_OBJECT(draw), "drag_begin", GTK_SIGNAL_FUNC(drag_begin), this); gtk_signal_connect (GTK_OBJECT(draw), "drag_data_get", GTK_SIGNAL_FUNC(drag_data_get), this); gtk_signal_connect (GTK_OBJECT(draw), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear), this); gtk_container_add (GTK_CONTAINER (frame), draw); gtk_widget_show(draw); // At bottom, a status bar. sbar = gtk_statusbar_new(); sbar_sel = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "selection"); // At the bottom, status bar & frame: GtkWidget *hbox1 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0); gtk_widget_show(hbox1); gtk_box_pack_start(GTK_BOX(hbox1), sbar, TRUE, TRUE, 0); // Palette # to right of sbar. GtkWidget *label = gtk_label_new("Palette #:"); gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 4); gtk_widget_show(label); // A spin button for palette#. palnum_adj = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, palettes.size() - 1, 1, 2, 2)); pspin = gtk_spin_button_new(palnum_adj, 1, 0); gtk_signal_connect(GTK_OBJECT(palnum_adj), "value_changed", GTK_SIGNAL_FUNC(palnum_changed), this); gtk_box_pack_start(GTK_BOX(hbox1), pspin, FALSE, FALSE, 0); gtk_widget_show(pspin); // Add edit controls to bottom. gtk_box_pack_start(GTK_BOX(vbox), create_controls(), FALSE, FALSE, 0); gtk_widget_show(sbar); enable_controls(); } /* * Create/add a new palette. */ void Palette_edit::new_palette ( ) { guint32 colors[256]; // R, G, B, then all black. memset(&colors[0], 0, sizeof(colors)); colors[0] = 255<<16; colors[1] = 255<<8; colors[2] = 255; GdkRgbCmap *newpal = gdk_rgb_cmap_new(colors, 256); int index = palettes.size(); // Index of new palette. palettes.push_back(newpal); update_flex(index); // Add to file. } /* * Update palette entry in flex file. */ void Palette_edit::update_flex ( int pnum // Palette # to send to file. ) { unsigned char *buf = new unsigned char[3*256]; Write_palette(buf, palettes[pnum]); // Update or append file data. flex_info->set(pnum, (char *) buf, 3*256); flex_info->set_modified(); } /* * Create the list for a single palette. */ Palette_edit::Palette_edit ( Flex_file_info *flinfo // Flex-file info. ) : Object_browser(0, flinfo), flex_info(flinfo), image(0), width(0), height(0), colorsel(0), cur_pal(0) { load(); // Load from file. setup(); } /* * Delete. */ Palette_edit::~Palette_edit ( ) { for (vector::iterator it = palettes.begin(); it != palettes.end(); ++it) gdk_rgb_cmap_free(*it); gtk_widget_destroy(get_widget()); delete image; } /* * Get i'th palette. */ void Palette_edit::show_palette ( int palnum ) { cur_pal = palnum; } /* * Unselect. */ void Palette_edit::unselect ( bool need_render // 1 to render and show. ) { if (selected >= 0) { selected = -1; if (need_render) { render(); show(); } } } /* * Move a palette within the list. */ void Palette_edit::move_palette ( bool up ) { if (cur_pal < 0) return; GdkRgbCmap *tmp; if (up) { if (cur_pal > 0) { tmp = palettes[cur_pal - 1]; palettes[cur_pal - 1] = palettes[cur_pal]; palettes[cur_pal] = tmp; cur_pal--; flex_info->swap(cur_pal);// Update flex-file list. } } else { if (cur_pal < palettes.size() - 1) { tmp = palettes[cur_pal + 1]; palettes[cur_pal + 1] = palettes[cur_pal]; palettes[cur_pal] = tmp; flex_info->swap(cur_pal);// Update flex-file list. cur_pal++; } } flex_info->set_modified(); gtk_spin_button_set_value(GTK_SPIN_BUTTON(pspin), cur_pal); } /* * Update upper bound of a range widget. */ void Update_range_upper ( GtkAdjustment *adj, int new_upper ) { adj->upper = new_upper; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); } /* * Add a new palette at the end of the list. */ void Palette_edit::add_palette ( ) { new_palette(); cur_pal = palettes.size() - 1; // Set to display new palette. Update_range_upper(palnum_adj, palettes.size() - 1); // This will update the display: gtk_spin_button_set_value(GTK_SPIN_BUTTON(pspin), cur_pal); } /* * Remove the current palette. */ void Palette_edit::remove_palette ( ) { // Don't delete the last one. if (cur_pal < 0 || palettes.size() < 2) return; if (Prompt( "Do you really want to delete the palette you're viewing?", "Yes", "No") != 0) return; gdk_rgb_cmap_free(palettes[cur_pal]); palettes.erase(palettes.begin() + cur_pal); flex_info->remove(cur_pal); flex_info->set_modified(); if (cur_pal >= palettes.size()) cur_pal = palettes.size() - 1; Update_range_upper(palnum_adj, palettes.size() - 1); // This will update the display: gtk_spin_button_set_value(GTK_SPIN_BUTTON(pspin), cur_pal); render(); // Cur_pal may not have changed. show(); } /* * Export current palette. */ void Palette_edit::export_palette ( char *fname, gpointer user_data ) { Palette_edit *ed = (Palette_edit *) user_data; if (U7exists(fname)) { char *msg = g_strdup_printf( "'%s' already exists. Overwrite?", fname); int answer = Prompt(msg, "Yes", "No"); g_free(msg); if (answer != 0) return; } // Write out current palette. GdkRgbCmap *pal = ed->palettes[ed->cur_pal]; ofstream out(fname); // OKAY that it's a 'text' file. out << "Palette from ExultStudio" << endl; int i; // Skip 0's at end. for (i = 255; i > 0; i--) if (pal->colors[i] != 0) break; int last_color = i; for (i = 0; i <= last_color; i++) { int r = (pal->colors[i]>>16)&255, g = (pal->colors[i]>>8)&255, b = pal->colors[i]&255; out << setw(3) << r << ' ' << setw(3) << g << ' ' << setw(3) << b << endl; } out.close(); } /* * Import current palette. */ void Palette_edit::import_palette ( char *fname, gpointer user_data ) { Palette_edit *ed = (Palette_edit *) user_data; char *msg = g_strdup_printf( "Overwrite current palette from '%s'?", fname); int answer = Prompt(msg, "Yes", "No"); g_free(msg); if (answer != 0) return; // Read in current palette. GdkRgbCmap *pal = ed->palettes[ed->cur_pal]; ifstream in(fname); // OKAY that it's a 'text' file. char buf[256]; in.getline(buf, sizeof(buf)); // Skip 1st line. if (!in.good()) { Alert("Error reading '%s'", fname); return; } int i = 0; // Color #. while (i < 256 && !in.eof()) { in.getline(buf, sizeof(buf)); char *ptr = &buf[0]; // Skip spaces. while (ptr < buf + sizeof(buf) && *ptr && isspace(*ptr)) ptr++; if (*ptr == '#') continue; // Comment. int r, g, b; if (sscanf(buf, "%d %d %d", &r, &g, &b) == 3) pal->colors[i++] = (r<<16) + (g<<8) + b; } in.close(); // Add to file. ed->update_flex(ed->cur_pal); ed->render(); ed->show(); } exult-1.2/mapedit/objedit.cc0000644000175000001440000001605207652574530011565 /** ** Objedit.cc - object-editing methods. ** ** Written: 7/29/01 - JSF **/ /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "studio.h" #include "u7drag.h" #include "servemsg.h" #include "objserial.h" #include "exult_constants.h" #include "utils.h" #include "shapefile.h" #include "shapedraw.h" using std::cout; using std::endl; /* * Object window's Okay button. */ C_EXPORT void on_obj_okay_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_obj_window(); ExultStudio::get_instance()->close_obj_window(); } /* * Object window's Apply button. */ C_EXPORT void on_obj_apply_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_obj_window(); } /* * Object window's Cancel button. */ C_EXPORT void on_obj_cancel_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->close_obj_window(); } /* * Object window's close button. */ C_EXPORT gboolean on_obj_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_obj_window(); return TRUE; } /* * Draw shape in object shape area. */ C_EXPORT gboolean on_obj_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { ExultStudio::get_instance()->show_obj_shape( event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Object shape/frame # changed, so update shape displayed. */ C_EXPORT gboolean on_obj_shape_changed ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data ) { ExultStudio::get_instance()->show_obj_shape(); return TRUE; } /* * Object shape/frame # changed, so update shape displayed. */ C_EXPORT gboolean on_obj_pos_changed ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data ) { //++++Maybe later, change pos. immediately? return TRUE; } /* * Callback for when a shape is dropped on the draw area. */ static void Obj_shape_dropped ( int file, // U7_SHAPE_SHAPES. int shape, int frame, void *udata ) { if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024) ((ExultStudio *) udata)->set_obj_shape(shape, frame); } #ifdef WIN32 static void Drop_dragged_shape(int shape, int frame, int x, int y, void *data) { cout << "Dropped a shape: " << shape << "," << frame << " " << data << endl; Obj_shape_dropped(U7_SHAPE_SHAPES, shape, frame, data); } #endif /* * Open the object-editing window. */ void ExultStudio::open_obj_window ( unsigned char *data, // Serialized object. int datalen ) { bool first_time = false; if (!objwin) // First time? { first_time = true; objwin = glade_xml_get_widget( app_xml, "obj_window" ); if (vgafile && palbuf) { obj_draw = new Shape_draw(vgafile->get_ifile(), palbuf, glade_xml_get_widget(app_xml, "obj_draw")); obj_draw->enable_drop(Obj_shape_dropped, this); } } // Init. obj address to null. gtk_object_set_user_data(GTK_OBJECT(objwin), 0); if (!init_obj_window(data, datalen)) return; gtk_widget_show(objwin); #ifdef WIN32 if (first_time || !objdnd) Windnd::CreateStudioDropDest(objdnd, objhwnd, Drop_dragged_shape, NULL, NULL, (void*) this); #endif } /* * Close the object-editing window. */ void ExultStudio::close_obj_window ( ) { if (objwin) { gtk_widget_hide(objwin); #ifdef WIN32 Windnd::DestroyStudioDropDest(objdnd, objhwnd); #endif } } /* * Init. the object editor with data from Exult. * * Output: 0 if error (reported). */ int ExultStudio::init_obj_window ( unsigned char *data, int datalen ) { unsigned long addr; int tx, ty, tz; int shape, frame, quality; std::string name; if (!Object_in(data, datalen, addr, tx, ty, tz, shape, frame, quality, name)) { cout << "Error decoding object" << endl; return 0; } // Store address with window. gtk_object_set_user_data(GTK_OBJECT(objwin), (gpointer) addr); // Store name. (Not allowed to change.) set_entry("obj_name", name.c_str(), false); // Shape/frame, quality. // set_entry("obj_shape", shape); // set_entry("obj_frame", frame); // set_entry("obj_quality", quality); set_spin("obj_shape", shape); set_spin("obj_frame", frame); set_spin("obj_quality", quality); set_spin("obj_x", tx); // Position. set_spin("obj_y", ty); set_spin("obj_z", tz); // Set limit on frame #. GtkWidget *btn = glade_xml_get_widget(app_xml, "obj_frame"); if (btn) { GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(btn)); int nframes = vgafile->get_ifile()->get_num_frames(shape); adj->upper = nframes - 1; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); } return 1; } /* * Send updated object info. back to Exult. * * Output: 0 if error (reported). */ int ExultStudio::save_obj_window ( ) { cout << "In save_obj_window()" << endl; unsigned char data[Exult_server::maxlength]; // Get object address. unsigned long addr = (unsigned long) gtk_object_get_user_data( GTK_OBJECT(objwin)); int tx = get_spin("obj_x"), ty = get_spin("obj_y"), tz = get_spin("obj_z"); std::string name(get_text_entry("obj_name")); // int shape = get_num_entry("obj_shape"); // int frame = get_num_entry("obj_frame"); // int quality = get_num_entry("obj_quality"); int shape = get_spin("obj_shape"); int frame = get_spin("obj_frame"); int quality = get_spin("obj_quality"); if (Object_out(server_socket, Exult_server::obj, addr, tx, ty, tz, shape, frame, quality, name) == -1) { cout << "Error sending object data to server" <configure(); // Yes, this is kind of redundant... int shnum = get_num_entry("obj_shape"); int frnum = get_num_entry("obj_frame"); if (!shnum) // Don't draw shape 0. shnum = -1; obj_draw->draw_shape_centered(shnum, frnum); if (w != -1) obj_draw->show(x, y, w, h); else obj_draw->show(); } /* * Set object shape. */ void ExultStudio::set_obj_shape ( int shape, int frame ) { set_spin("obj_shape", shape); set_spin("obj_frame", frame); const char *nm = get_shape_name(shape); set_entry("obj_name", nm ? nm : "", false); show_obj_shape(); } exult-1.2/mapedit/combo.cc0000644000175000001440000011476010040666216011235 /** ** Combo.cc - A combination of multiple objects. ** ** Written: 4/26/02 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "studio.h" #include "combo.h" #include "exult_constants.h" #include "exceptions.h" #include "shapevga.h" #include "shapefile.h" #include "ibuf8.h" #include "objserial.h" #include "shapegroup.h" #include "Flex.h" #include "u7drag.h" using std::cout; using std::cin; using std::endl; const int border = 2; // Border at bottom, sides of each // combo in browser. const int maxtiles = 32; // Max. width/height in tiles. /* * Open combo window (if not already open). */ C_EXPORT void on_new_combo1_activate ( GtkMenuItem *menuitem, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); studio->open_combo_window(); } void ExultStudio::open_combo_window ( ) { if (combowin && combowin->is_visible()) return; // Already open. if (!vgafile) { EStudio::Alert("'shapes.vga' file isn't present"); return; } Shapes_vga_file *svga = (Shapes_vga_file *) vgafile->get_ifile(); delete combowin; // Delete old (svga may have changed). combowin = new Combo_editor(svga, palbuf); combowin->show(true); // Set edit-mode to pick. GtkWidget *mitem = glade_xml_get_widget(app_xml, "pick_for_combo1"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE); } /* * Save combos. */ void ExultStudio::save_combos ( ) { // Get file info. Shape_file_info *combos = files->create("combos.flx"); try { if (combos) combos->flush(); } catch (const exult_exception& e) { EStudio::Alert(e.what()); } } /* * Callbacks for "Combo" editor window. */ C_EXPORT gint on_combo_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); combo->render(&event->area); return TRUE; } C_EXPORT void on_combo_remove_clicked (GtkButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->remove(); } C_EXPORT void on_combo_apply_clicked (GtkButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->save(); } C_EXPORT void on_combo_ok_clicked (GtkButton *button, gpointer user_data) { GtkWidget *win = gtk_widget_get_toplevel(GTK_WIDGET(button)); Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(win)); combo->save(); gtk_widget_hide(win); } C_EXPORT void on_combo_locx_changed (GtkSpinButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->set_position(); } C_EXPORT void on_combo_locy_changed (GtkSpinButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->set_position(); } C_EXPORT void on_combo_locz_changed (GtkSpinButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->set_position(); } C_EXPORT void on_combo_order_changed (GtkSpinButton *button, gpointer user_data) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button)))); combo->set_order(); } /* * Mouse events in draw area. */ C_EXPORT gint on_combo_draw_button_press_event ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Combo_chooser. ) { Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); return combo->mouse_press(event); } /* * Which member makes the better 'hot-spot' in a combo, where 'better' * means lower, then southmost, then eastmost. * * Output: 0 if c0, 1 if c1 */ int hot_spot_compare ( Combo_member& c0, Combo_member& c1 ) { if (c0.tz < c1.tz) return 0; else if (c1.tz < c0.tz) return 1; else if (c0.ty > c1.ty) return 0; else if (c1.ty > c0.ty) return 1; else return c0.tx >= c1.tx ? 0 : 1; } /* * Get footprint of given member. */ Rectangle Combo::get_member_footprint ( int i // i'th member. ) { Combo_member *m = members[i]; // Get tile dims. Shape_info& info = shapes_file->get_info(m->shapenum); int xtiles = info.get_3d_xtiles(m->framenum), ytiles = info.get_3d_ytiles(m->framenum); // Get tile footprint. Rectangle box(m->tx - xtiles + 1, m->ty - ytiles + 1, xtiles, ytiles); return box; } /* * Create empty combo. */ Combo::Combo ( Shapes_vga_file *svga ) : shapes_file(svga), starttx(c_num_tiles), startty(c_num_tiles), hot_index(-1), tilefoot(0, 0, 0, 0) { // Read info. the first time. shapes_file->read_info(false, true);//+++++BG? } /* * Copy another. */ Combo::Combo ( const Combo& c2 ) : shapes_file(c2.shapes_file), starttx(c2.starttx), startty(c2.startty), hot_index(c2.hot_index), name(c2.name), tilefoot(c2.tilefoot) { for (std::vector::const_iterator it = c2.members.begin(); it != c2.members.end(); ++it) { Combo_member *m = *it; members.push_back(new Combo_member(m->tx, m->ty, m->tz, m->shapenum, m->framenum)); } } /* * Clean up. */ Combo::~Combo ( ) { for (std::vector::iterator it = members.begin(); it != members.end(); ++it) delete *it; } /* * Add a new object. */ void Combo::add ( int tx, int ty, int tz, // Location rel. to top-left. int shnum, int frnum // Shape. ) { // Look for identical shape, pos. for (std::vector::iterator it = members.begin(); it != members.end(); ++it) { Combo_member *m = *it; if (tx == m->tx && ty == m->ty && tz == m->tz && shnum == m->shapenum && frnum == m->framenum) return; // Don't add same one twice. } // Get tile dims. Shape_info& info = shapes_file->get_info(shnum); int xtiles = info.get_3d_xtiles(frnum), ytiles = info.get_3d_ytiles(frnum), ztiles = info.get_3d_height(); // Get tile footprint. Rectangle box(tx - xtiles + 1, ty - ytiles + 1, xtiles, ytiles); if (!members.size()) // First one? tilefoot = box; // Init. total footprint. else { // Too far away? if (tilefoot.x + tilefoot.w - box.x > maxtiles || box.x + box.w - tilefoot.x > maxtiles || tilefoot.y + tilefoot.h - box.y > maxtiles || box.y + box.h - tilefoot.y > maxtiles) { EStudio::Alert( "New object is too far (> 32) from others"); return; } // Add to footprint. tilefoot = tilefoot.add(box); } Combo_member *memb = new Combo_member(tx, ty, tz, shnum, frnum); members.push_back(memb); // Figure visible top-left tile, with // 1 to spare. int vtx = tx - xtiles - 2 - (tz + ztiles + 1)/2, vty = ty - ytiles - 2 - (tz + ztiles + 1)/2; if (vtx < starttx) // Adjust our starting point. starttx = vtx; if (vty < startty) startty = vty; if (hot_index == -1 || // First one, or better than prev? hot_spot_compare(*memb, *members[hot_index]) == 0) hot_index = members.size() - 1; } /* * Remove i'th object. */ void Combo::remove ( int i ) { if (i < 0 || i >= members.size()) return; // Get and remove i'th entry. std::vector::iterator it = members.begin() + i; Combo_member *m = *it; members.erase(it); delete m; hot_index = -1; // Figure new hot-spot, footprint. tilefoot = Rectangle(0, 0, 0, 0); for (std::vector::iterator it = members.begin(); it != members.end(); ++it) { Combo_member *m = *it; int index = it - members.begin(); Rectangle box = get_member_footprint(index); if (hot_index == -1) // First? { hot_index = 0; tilefoot = box; } else { if (hot_spot_compare(*m, *members[hot_index]) == 0) hot_index = index; tilefoot = tilefoot.add(box); } } } /* * Paint in a drawing area. */ void Combo::draw ( Shape_draw *draw, int selected, // Index of 'selected' item, or -1. int xoff, int yoff // Offset within draw. ) { int selx = -1000, sely = -1000; bool selfound = false; for (std::vector::iterator it = members.begin(); it != members.end(); ++it) { Combo_member *m = *it; // Figure pixels up-left for lift. int lft = m->tz*(c_tilesize/2); // Figure relative tile. int mtx = m->tx - starttx, mty = m->ty - startty; // Hot spot: int x = mtx*c_tilesize - lft, y = mty*c_tilesize - lft; Shape_frame *shape = shapes_file->get_shape(m->shapenum, m->framenum); if (!shape) continue; // But draw_shape uses top-left. x -= shape->get_xleft(); y -= shape->get_yabove(); x += xoff; y += yoff; // Add offset within area. draw->draw_shape(shape, x, y); if (it - members.begin() == selected) { selx = x; // Save coords for selected. sely = y; selfound = true; } } if (selfound) // Now put border around selected. { Combo_member *m = members[selected]; // FOR NOW, use color #1 ++++++++ draw->draw_shape_outline(m->shapenum, m->framenum, selx, sely, 1); } } /* * Find last member in list that contains a mouse point. * * Output: Index of member found, or -1 if none. */ int Combo::find ( int mx, int my // Mouse position in draw area. ) { int cnt = members.size(); for (int i = cnt - 1; i >= 0; i--) { Combo_member *m = members[i]; // Figure pixels up-left for lift. int lft = m->tz*(c_tilesize/2); // Figure relative tile. int mtx = m->tx - starttx, mty = m->ty - startty; int x = mtx*c_tilesize - lft, y = mty*c_tilesize - lft; Shape_frame *frame = shapes_file->get_shape( m->shapenum, m->framenum); if (frame && frame->has_point(mx - x, my - y)) return i; } return -1; } /* * Write out. * * Output: Allocated buffer containing result. */ unsigned char *Combo::write ( int& datalen // Actual length of data in buf. is // returned here. ) { int namelen = name.length(); // Name length. // Room for our data + members. unsigned char *buf = new unsigned char[namelen + 1 + 7*4 + members.size()*(5*4)]; unsigned char *ptr = buf; Serial_out out(ptr); out << name; out << hot_index << starttx << startty; out << (short) members.size(); // # members to follow. for (std::vector::const_iterator it = members.begin(); it != members.end(); ++it) { Combo_member *m = *it; out << m->tx << m->ty << m->tz << m->shapenum << m->framenum; } datalen = ptr - buf; // Return actual length. return buf; } /* * Read in. * * Output: ->past actual data read. */ unsigned char *Combo::read ( unsigned char *buf, int bufsize ) { unsigned char *ptr = buf; Serial_in in(ptr); in << name; in << hot_index << starttx << startty; short cnt; in << cnt; // # members to follow. for (int i = 0; i < cnt; i++) { short tx, ty, tz, shapenum, framenum; in << tx << ty << tz << shapenum << framenum; Combo_member *memb = new Combo_member(tx, ty, tz, shapenum, framenum); members.push_back(memb); Rectangle box = get_member_footprint(i); if (i == 0) // Figure footprint. tilefoot = box; else tilefoot = tilefoot.add(box); } return ptr; } /* * Set to edit an existing combo. */ void Combo_editor::set_combo ( Combo *newcombo, // We'll own this. int findex // File index. ) { delete combo; combo = newcombo; file_index = findex; selected = -1; ExultStudio::get_instance()->set_entry( "combo_name", combo->name.c_str(), true); set_controls(); // No selection now. render(); } /* * Create combo editor. */ Combo_editor::Combo_editor ( Shapes_vga_file *svga, // File containing shapes. unsigned char *palbuf // Palette for drawing shapes. ) : Shape_draw(svga, palbuf, glade_xml_get_widget( ExultStudio::get_instance()->get_xml(), "combo_draw")), selected(-1), setting_controls(false), file_index(-1) { static bool first = true; combo = new Combo(svga); GladeXML *app_xml = ExultStudio::get_instance()->get_xml(); win = glade_xml_get_widget(app_xml, "combo_win"); gtk_object_set_user_data(GTK_OBJECT(win), this); if (first) // Indicate the events we want. { gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); first = false; } set_controls(); } /* * Clean up. */ Combo_editor::~Combo_editor ( ) { delete combo; } /* * Show/hide. */ void Combo_editor::show ( bool tf ) { if (tf) gtk_widget_show(win); else gtk_widget_hide(win); } /* * Display. */ void Combo_editor::render ( GdkRectangle *area // 0 for whole draw area. ) { Shape_draw::configure(); // Setup the first time. // Get dims. int draww = draw->allocation.width, drawh = draw->allocation.height; GdkRectangle all; if (!area) { all.x = all.y = 0; all.width = draww; all.height = drawh; area = &all; } gdk_gc_set_clip_rectangle(drawgc, area); iwin->fill8(255); // Fill with background color. combo->draw(this, selected); // Draw shapes. Shape_draw::show(area->x, area->y, area->width, area->height); } /* * Set controls according to what's selected. */ void Combo_editor::set_controls ( ) { setting_controls = true; // Avoid updating. ExultStudio *studio = ExultStudio::get_instance(); Combo_member *m = combo->get(selected); if (!m) // None selected? { studio->set_spin("combo_locx", 0, false); studio->set_spin("combo_locy", 0, false); studio->set_spin("combo_locz", 0, false); studio->set_spin("combo_order", 0, false); studio->set_sensitive("combo_remove", false); } else { int draww = draw->allocation.width, drawh = draw->allocation.height; studio->set_sensitive("combo_locx", true); studio->set_spin("combo_locx", m->tx - combo->starttx, 0, draww/c_tilesize); studio->set_sensitive("combo_locy", true); studio->set_spin("combo_locy", m->ty - combo->startty, 0, drawh/c_tilesize); studio->set_sensitive("combo_locz", true); studio->set_spin("combo_locz", m->tz, 0, 15); studio->set_sensitive("combo_order", true); studio->set_spin("combo_order", selected, 0, combo->members.size() - 1); studio->set_sensitive("combo_remove", true); } setting_controls = false; } /* * Handle a mouse-press event. */ gint Combo_editor::mouse_press ( GdkEventButton *event ) { if (event->button != 1) return FALSE; // Handling left-click. // Get mouse position, draw dims. int mx = (int) event->x, my = (int) event->y; selected = combo->find(mx, my); // Find it (or -1 if not found). set_controls(); render(); return TRUE; } /* * Move the selected item within the order. */ void Combo_editor::set_order ( ) { if (setting_controls || selected < 0) return; ExultStudio *studio = ExultStudio::get_instance(); int newi = studio->get_spin("combo_order"); if (selected == newi) return; // Already correct. int dir = newi > selected ? 1 : -1; while (newi != selected) { Combo_member *tmp = combo->members[selected + dir]; combo->members[selected + dir] = combo->members[selected]; combo->members[selected] = tmp; selected += dir; } render(); } /* * Move the selected item to the desired position in the spin buttons. */ void Combo_editor::set_position ( ) { Combo_member *m = combo->get(selected); if (!m || setting_controls) return; ExultStudio *studio = ExultStudio::get_instance(); m->tx = combo->starttx + studio->get_spin("combo_locx"); m->ty = combo->startty + studio->get_spin("combo_locy"); m->tz = studio->get_spin("combo_locz"); render(); } /* * Get # shapes we can display. */ int Combo_chooser::get_count ( ) { return group ? group->size() : combos.size(); } /* * Add an object/shape picked from Exult. */ void Combo_editor::add ( unsigned char *data, // Serialized object. int datalen ) { unsigned long addr; int tx, ty, tz; int shape, frame, quality; std::string name; if (!Object_in(data, datalen, addr, tx, ty, tz, shape, frame, quality, name)) { cout << "Error decoding object" << endl; return; } combo->add(tx, ty, tz, shape, frame); render(); } /* * Remove selected. */ void Combo_editor::remove ( ) { if (selected >= 0) { combo->remove(selected); selected = -1; set_controls(); render(); } } /* * Save combo. */ void Combo_editor::save ( ) { ExultStudio *studio = ExultStudio::get_instance(); // Get name from field. combo->name = studio->get_text_entry("combo_name"); Flex_file_info *flex_info = dynamic_cast (studio->get_files()->create("combos.flx")); if (!flex_info) { EStudio::Alert("Can't open 'combos.flx'"); return; } flex_info->set_modified(); int len; // Serialize. unsigned char *newbuf = combo->write(len); // Update or append file data. flex_info->set(file_index == -1 ? flex_info->size() : file_index, (char *) newbuf, len); Combo_chooser *browser = dynamic_cast( studio->get_browser()); if (browser) // Browser open? file_index = browser->add(new Combo(*combo), file_index); } /* * Blit onto screen. */ void Combo_chooser::show ( int x, int y, int w, int h // Area to blit. ) { Shape_draw::show(draw->window, x, y, w, h); if (selected >= 0) // Show selected. { Rectangle b = info[selected].box; // Draw yellow box. gdk_draw_rectangle(draw->window, drawgc, FALSE, b.x, b.y, b.w, b.h); } } /* * Select an entry. This should be called after rendering * the combo. */ void Combo_chooser::select ( int new_sel ) { if (new_sel < 0 || new_sel >= info_cnt) return; // Bad value. selected = new_sel; enable_controls(); int num = info[selected].num; Combo *combo = combos[num]; // Remove prev. selection msg. // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); char buf[150]; // Show new selection. g_snprintf(buf, sizeof(buf), "Combo %d", num); if (combo && !combo->name.empty()) { int len = strlen(buf); g_snprintf(buf + len, sizeof(buf) - len, ": '%s'", combo->name.c_str()); } gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } /* * Unselect. */ void Combo_chooser::unselect ( bool need_render // 1 to render and show. ) { if (selected >= 0) { selected = -1; if (need_render) { render(); show(); } if (sel_changed) // Tell client. (*sel_changed)(); } enable_controls(); // Enable/disable controls. char buf[150]; // Show new selection. if (info_cnt > 0) { // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); g_snprintf(buf, sizeof(buf), "Combos %d to %d", info[0].num, info[info_cnt - 1].num); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } else { // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, "No combos"); } } /* * Load/reload from file. */ void Combo_chooser::load ( ) { int cnt = combos.size(); for (int i = 0; i < cnt; i++) // Delete all the combos. delete combos[i]; int num_combos = flex_info->size(); // We need 'shapes.vga'. Shape_file_info *svga_info = ExultStudio::get_instance()->get_vgafile(); Shapes_vga_file *svga = svga_info ? (Shapes_vga_file *) svga_info->get_ifile() : 0; combos.resize(num_combos); // Set size of list. if (!svga) num_combos = 0; // Read them all in. for (int i = 0; i < num_combos; i++) { size_t len; unsigned char *buf = (unsigned char *) flex_info->get(i, len); Combo *combo = new Combo(svga); combo->read(buf, len); combos[i] = combo; // Store in list. } } /* * Render as many combos as fit in the combo chooser window. */ void Combo_chooser::render ( ) { // Look for selected frame. int selcombo = -1, new_selected = -1; if (selected >= 0) // Save selection info. selcombo = info[selected].num; // Remove "selected" message. //gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); delete [] info; // Delete old info. list. // Get drawing area dimensions. gint winw = draw->allocation.width, winh = draw->allocation.height; // Provide more than enough room. info = new Combo_info[256]; info_cnt = 0; // Count them. // Clear window first. iwin->fill8(255); // Background color. int index = index0; // We'll always show 128x128. const int combow = 128, comboh = 128; int total_cnt = get_count(); int y = border; // Show bottom if at least 1/2 vis. while (index < total_cnt && y + comboh/2 + border <= winh) { int x = border; int cliph = y + comboh <= winh ? comboh : (winh - y); while (index < total_cnt && x + combow + border <= winw) { iwin->set_clip(x, y, combow, cliph); int combonum = group ? (*group)[index] : index; combos[combonum]->draw(this, -1, x, y); iwin->clear_clip(); // Store info. about where drawn. info[info_cnt].set(combonum, x, y, combow, comboh); if (combonum == selcombo) // Found the selected combo. new_selected = info_cnt; info_cnt++; index++; // Next combo. x += combow + border; } y += comboh + border; } if (new_selected == -1) unselect(false); else select(new_selected); } /* * Scroll to a new combo. */ void Combo_chooser::scroll ( int newindex // Abs. index of leftmost to show. ) { int total = combos.size(); if (index0 < newindex) // Going forwards? index0 = newindex < total ? newindex : total; else if (index0 > newindex) // Backwards? index0 = newindex >= 0 ? newindex : 0; render(); show(); } /* * Scroll up/down by one row. */ void Combo_chooser::scroll ( bool upwards ) { GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(vscroll)); float delta = adj->step_increment; if (upwards) delta = -delta; adj->value += delta; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); scroll((gint) adj->value); } /* * Someone wants the dragged combo. */ void Combo_chooser::drag_data_get ( GtkWidget *widget, // The view window. GdkDragContext *context, GtkSelectionData *seldata, // Fill this in. guint info, guint time, gpointer data // ->Shape_chooser. ) { cout << "In DRAG_DATA_GET" << endl; Combo_chooser *chooser = (Combo_chooser *) data; if (chooser->selected < 0 || info != U7_TARGET_COMBOID) return; // Not sure about this. // Get combo #. int num = chooser->info[chooser->selected].num; Combo *combo = chooser->combos[num]; // Get enough memory. int cnt = combo->members.size(); int buflen = 5*4 + cnt*5*4; cout << "Buflen = " << buflen << endl; guchar *buf = new unsigned char[buflen]; guchar *ptr = buf; U7_combo_data *ents = new U7_combo_data[cnt]; // Get 'hot-spot' member. Combo_member *hot = combo->members[combo->hot_index]; for (int i = 0; i < cnt; i++) { Combo_member *m = combo->members[i]; ents[i].tx = m->tx - hot->tx; ents[i].ty = m->ty - hot->ty; ents[i].tz = m->tz - hot->tz; ents[i].shape = m->shapenum; ents[i].frame = m->framenum; } Rectangle foot = combo->tilefoot; int len = Store_u7_comboid(buf, foot.w, foot.h, foot.x + foot.w - 1 - hot->tx, foot.y + foot.h - 1 - hot->ty, cnt, ents); assert(len <= buflen); #ifdef WIN32 windragdata *wdata = (windragdata *)seldata; wdata->assign(info, len, buf); #else // Make us owner of xdndselection. gtk_selection_owner_set(widget, gdk_atom_intern("XdndSelection", 0), time); // Set data. gtk_selection_data_set(seldata, gdk_atom_intern(U7_TARGET_COMBOID_NAME, 0), 8, buf, len); #endif delete buf; delete [] ents; } /* * Another app. has claimed the selection. */ gint Combo_chooser::selection_clear ( GtkWidget *widget, // The view window. GdkEventSelection *event, gpointer data // ->Combo_chooser. ) { // Combo_chooser *chooser = (Combo_chooser *) data; cout << "SELECTION_CLEAR" << endl; return TRUE; } /* * Beginning of a drag. */ gint Combo_chooser::drag_begin ( GtkWidget *widget, // The view window. GdkDragContext *context, gpointer data // ->Combo_chooser. ) { cout << "In DRAG_BEGIN" << endl; Combo_chooser *chooser = (Combo_chooser *) data; if (chooser->selected < 0) return FALSE; // ++++Display a halt bitmap. // Get ->combo. int num = chooser->info[chooser->selected].num; Combo *combo = chooser->combos[num]; // Show 'hot' member as icon. Combo_member *hot = combo->members[combo->hot_index]; Shape_frame *shape = combo->shapes_file->get_shape(hot->shapenum, hot->framenum); if (shape) chooser->set_drag_icon(context, shape); return TRUE; } /* * Handle a scrollbar event. */ void Combo_chooser::scrolled ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Combo_chooser. ) { Combo_chooser *chooser = (Combo_chooser *) data; gint newindex = (gint) adj->value; chooser->scroll(newindex); } /* * Callbacks for controls: */ /* * Keystroke in draw-area. */ static gboolean on_combo_key_press (GtkEntry *entry, GdkEventKey *event, gpointer user_data) { Combo_chooser *chooser = (Combo_chooser *) user_data; switch (event->keyval) { case GDK_Delete: chooser->remove(); return TRUE; } return FALSE; // Let parent handle it. } /* * Enable/disable controls after selection changed. */ void Combo_chooser::enable_controls ( ) { if (selected == -1) // No selection. { if (!group) { gtk_widget_set_sensitive(move_down, false); gtk_widget_set_sensitive(move_up, false); } return; } if (!group) { gtk_widget_set_sensitive(move_down, info[selected].num < combos.size() - 1); gtk_widget_set_sensitive(move_up, info[selected].num > 0); } } static gint Mouse_release(GtkWidget *, GdkEventButton *, gpointer); /* * Create the list. */ Combo_chooser::Combo_chooser ( Vga_file *i, // Where they're kept. Flex_file_info *flinfo, // Flex-file info. unsigned char *palbuf, // Palette, 3*256 bytes (rgb triples). int w, int h, // Dimensions. Shape_group *g // Filter, or null. ) : Object_browser(g, flinfo), Shape_draw(i, palbuf, gtk_drawing_area_new()), flex_info(flinfo), index0(0), info(0), info_cnt(0), sel_changed(0) { load(); // Init. from file data. // Put things in a vert. box. GtkWidget *vbox = gtk_vbox_new(FALSE, 0); set_widget(vbox); // This is our "widget" gtk_widget_show(vbox); GtkWidget *hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); // A frame looks nice. GtkWidget *frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); // NOTE: draw is in Shape_draw. // Indicate the events we want. gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_KEY_PRESS_MASK); // Set "configure" handler. gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(configure), this); // Set "expose" handler. gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), this); // Keystroke. gtk_signal_connect(GTK_OBJECT(draw), "key-press-event", GTK_SIGNAL_FUNC (on_combo_key_press), this); GTK_WIDGET_SET_FLAGS(draw, GTK_CAN_FOCUS); // Set mouse click handler. gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(mouse_press), this); gtk_signal_connect(GTK_OBJECT(draw), "button_release_event", GTK_SIGNAL_FUNC(Mouse_release), this); // Mouse motion. gtk_signal_connect(GTK_OBJECT(draw), "drag_begin", GTK_SIGNAL_FUNC(drag_begin), this); #ifdef WIN32 // required to override GTK+ Drag and Drop gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(win32_drag_motion), this); #else gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(drag_motion), this); #endif gtk_signal_connect (GTK_OBJECT(draw), "drag_data_get", GTK_SIGNAL_FUNC(drag_data_get), this); gtk_signal_connect (GTK_OBJECT(draw), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear), this); gtk_container_add (GTK_CONTAINER (frame), draw); gtk_drawing_area_size(GTK_DRAWING_AREA(draw), w, h); gtk_widget_show(draw); // Want a scrollbar for the combos. GtkObject *combo_adj = gtk_adjustment_new(0, 0, combos.size(), 1, 4, 1.0); vscroll = gtk_vscrollbar_new(GTK_ADJUSTMENT(combo_adj)); // Update window when it stops. gtk_range_set_update_policy(GTK_RANGE(vscroll), GTK_UPDATE_DELAYED); gtk_box_pack_start(GTK_BOX(hbox), vscroll, FALSE, TRUE, 0); // Set scrollbar handler. gtk_signal_connect(GTK_OBJECT(combo_adj), "value_changed", GTK_SIGNAL_FUNC(scrolled), this); gtk_widget_show(vscroll); // At the bottom, status bar: GtkWidget *hbox1 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0); gtk_widget_show(hbox1); // At left, a status bar. sbar = gtk_statusbar_new(); sbar_sel = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "selection"); gtk_box_pack_start(GTK_BOX(hbox1), sbar, TRUE, TRUE, 0); gtk_widget_show(sbar); // Add controls to bottom. gtk_box_pack_start(GTK_BOX(vbox), create_controls(find_controls|move_controls), FALSE, FALSE, 0); } /* * Delete. */ Combo_chooser::~Combo_chooser ( ) { gtk_widget_destroy(get_widget()); delete [] info; int i; int cnt = combos.size(); for (i = 0; i < cnt; i++) // Delete all the combos. delete combos[i]; } /* * Add a new or updated combo. * * Output: Index of entry. */ int Combo_chooser::add ( Combo *newcombo, // We'll own this. int index // Index to replace, or -1 to add new. ) { if (index == -1) { // New. combos.push_back(newcombo); index = combos.size() - 1; // Index of new entry. } else { assert(index >= 0 && index < combos.size()); delete combos[index]; combos[index] = newcombo; } GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(vscroll)); adj->upper = combos.size(); gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); render(); show(); return index; // Return index. } /* * Remove selected entry. */ void Combo_chooser::remove ( ) { if (selected < 0) return; int tnum = info[selected].num; Combo_editor *combowin = ExultStudio::get_instance()->get_combowin(); if (combowin && combowin->is_visible() && combowin->file_index == tnum) { EStudio::Alert("Can't remove the combo you're editing"); return; } if (EStudio::Prompt("Okay to remove selected combo?", "Yes", "no") != 0) return; selected = -1; Combo *todel = combos[tnum]; delete todel; // Delete from our list. combos.erase(combos.begin() + tnum); flex_info->set_modified(); flex_info->remove(tnum); // Update flex-file list. GtkAdjustment *adj = // Update scrollbar. gtk_range_get_adjustment(GTK_RANGE(vscroll)); adj->upper = combos.size(); gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); render(); show(); } /* * Bring up editor for selected combo. */ void Combo_chooser::edit ( ) { if (selected < 0) return; Combo_editor *combowin = ExultStudio::get_instance()->get_combowin(); if (combowin && combowin->is_visible()) { EStudio::Alert("You're already editing a combo"); return; } int tnum = info[selected].num; ExultStudio *studio = ExultStudio::get_instance(); studio->open_combo_window(); // Open it. Combo_editor *ed = studio->get_combowin(); if (!ed || !ed->is_visible()) return; // Failed. Shouldn't happen. ed->set_combo(new Combo(*(combos[tnum])), tnum); } /* * Configure the viewing window. */ gint Combo_chooser::configure ( GtkWidget *widget, // The draw area. GdkEventConfigure *event, gpointer data // ->Combo_chooser ) { Combo_chooser *chooser = (Combo_chooser *) data; chooser->Shape_draw::configure(); chooser->render(); // Set new scroll amounts. int w = event->width, h = event->height; int per_row = (w - border)/(128 + border); int num_rows = (h - border)/(128 + border); int page_size = per_row*num_rows; GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE( chooser->vscroll)); adj->step_increment = per_row; adj->page_increment = page_size; adj->page_size = page_size; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); #if 0 /* ++++++Later */ if (chooser->group) // Filtering? chooser->enable_drop(); // Can drop combos here. #endif return (TRUE); } /* * Handle an expose event. */ gint Combo_chooser::expose ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Combo_chooser. ) { Combo_chooser *chooser = (Combo_chooser *) data; chooser->show(event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } #ifdef WIN32 /* * Dragging in win32. */ static bool win32_button = false; gint Combo_chooser::win32_drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Combo_chooser. ) { if (win32_button) { win32_button = false; // prepare the dragged data windragdata wdata; // This call allows us to recycle the data transfer initialization code. // It's clumsy, but far easier to maintain. drag_data_get(NULL, NULL, (GtkSelectionData *) &wdata, U7_TARGET_COMBOID, 0, data); POINT pnt; GetCursorPos(&pnt); LPDROPSOURCE idsrc = (LPDROPSOURCE) new Windropsource(0, pnt.x, pnt.y); LPDATAOBJECT idobj = (LPDATAOBJECT) new Winstudioobj(wdata); DWORD dndout; HRESULT res = DoDragDrop(idobj, idsrc, DROPEFFECT_COPY, &dndout); if (FAILED(res)) { g_warning ("Oops! Something is wrong with OLE2 DnD.."); } delete idsrc; idobj->Release(); // Not sure if we really need this. However, it doesn't hurt either. } return true; }; #else gint Combo_chooser::drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Shape_chooser. ) { Combo_chooser *chooser = (Combo_chooser *) data; if (!chooser->dragging && chooser->selected >= 0) chooser->start_drag(U7_TARGET_COMBOID_NAME, U7_TARGET_COMBOID, (GdkEvent *) event); return true; } #endif /* * Handle a mouse button press event. */ gint Combo_chooser::mouse_press ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Combo_chooser. ) { gtk_widget_grab_focus(widget); // Enables keystrokes. Combo_chooser *chooser = (Combo_chooser *) data; if (event->button == 4) { chooser->scroll(true); return(TRUE); } else if (event->button == 5) { chooser->scroll(false); return(TRUE); } int old_selected = chooser->selected; int i; // Search through entries. for (i = 0; i < chooser->info_cnt; i++) if (chooser->info[i].box.has_point( (int) event->x, (int) event->y)) { // Found the box? // Indicate we can drag. #ifdef WIN32 // Here, we have to override GTK+'s Drag and Drop, which is non-OLE and // usually stucks outside the program window. I think it's because // the dragged shape only receives mouse motion events when the new mouse pointer // position is *still* inside the shape. So if you move the mouse too fast, // we are stuck. win32_button = true; #endif chooser->selected = i; chooser->render(); chooser->show(); // Tell client. if (chooser->sel_changed) (*chooser->sel_changed)(); break; } if (i == chooser->info_cnt && event->button == 1) chooser->unselect(true); // Nothing under mouse. else if (chooser->selected == old_selected && old_selected >= 0) { // Same square. Check for dbl-click. if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS) chooser->edit(); } if (event->button == 3) gtk_menu_popup(GTK_MENU(chooser->create_popup()), 0, 0, 0, 0, event->button, event->time); return (TRUE); } /* * Handle a mouse button-release event in the combo chooser. */ static gint Mouse_release ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Shape_chooser. ) { Combo_chooser *chooser = (Combo_chooser *) data; chooser->mouse_up(); } /* * Move currently-selected combo up or down. */ void Combo_chooser::move ( bool upwards ) { if (selected < 0) return; // Shouldn't happen. int tnum = info[selected].num; if ((tnum == 0 && upwards) || (tnum == combos.size() - 1 && !upwards)) return; if (upwards) // Going to swap tnum & tnum+1. tnum--; Combo *tmp = combos[tnum]; combos[tnum] = combos[tnum + 1]; combos[tnum + 1] = tmp; selected += upwards ? -1 : 1; // Update editor if open. Combo_editor *combowin = ExultStudio::get_instance()->get_combowin(); if (combowin && combowin->is_visible()) { if (combowin->file_index == tnum) combowin->file_index = tnum + 1; else if (combowin->file_index == tnum + 1) combowin->file_index = tnum; } flex_info->set_modified(); flex_info->swap(tnum); // Update flex-file list. render(); show(); } /* * Search for an entry. */ void Combo_chooser::search ( const char *srch, // What to search for. int dir // 1 or -1. ) { int total = get_count(); if (!total) return; // Empty. ExultStudio *studio = ExultStudio::get_instance(); // Start with selection, or top. int start = selected >= 0 ? info[selected].num : 0; int i; start += dir; int stop = dir == -1 ? -1 : total; for (i = start; i != stop; i += dir) { int num = group ? (*group)[i] : i; const char *nm = combos[i]->name.c_str(); if (nm && search_name(nm, srch)) break; // Found it. } if (i == stop) return; // Not found. while (i < index0) // Above current view? scroll(true); while (i >= index0 + info_cnt) // Below? scroll(false); int newsel = i - index0; // New selection. if (newsel >= 0 && newsel < info_cnt) select(newsel); show(); } exult-1.2/mapedit/execbox.h0000644000175000001440000000627007647741317011450 /** ** Execbox.h - Execute a command-line program and display its output. ** ** Written: 10/02/02 - JSF **/ #ifndef INCL_EXECBOX_H #define INCL_EXECBOX_H 1 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include class Exec_box; class Exec_process; // Called when child is done: typedef void (*Exec_done_fun)(int exit_code, Exec_box *box, gpointer user_data); #ifndef WIN32 /* * A class for executing a child process and capturing its output in a * GTK program. */ class Exec_process { public: // Function called when data is read // from child. If datalen == 0, // child is done & exit_code is set. typedef void (*Reader_fun)(char *data, int datalen, int exit_code, gpointer user_data); private: // Pipes for talking to child: int child_stdin, child_stdout, child_stderr; int child_pid; // Child's process ID. gint stdout_tag, stderr_tag; // GDK tags for getting child's output. Reader_fun reader; // Called when data read from child. void *reader_data; // User data passed back. public: Exec_process(); ~Exec_process(); void kill_child(); // Kill process. void read_from_child(int id); // Read and call 'reader'. // Execute. bool exec(const char *file, char *argv[], Reader_fun rfun, void *udata); bool check_child(int& exit_code); // Is child still running? }; #else class Exec_process { public: typedef void (*Reader_fun)(char *data, int datalen, int exit_code, gpointer user_data); Exec_process() {} ~Exec_process() {} void kill_child() {} void read_from_child(int id) {} bool exec(const char *file, char *argv[], Reader_fun rfun, void *udata) { return false; } bool check_child(int& exit_code) { return false; } }; #endif /* * This class can execute a command-line program and display its output. */ class Exec_box { Exec_process *executor; // Handles child process. GtkTextView *box; // Where we show responses. GtkStatusbar *status; // For showing status. guint status_ctx; // Context for status. Exec_done_fun done_fun; // Called when child has exited. gpointer user_data; // Passed to done_fun. public: Exec_box(GtkTextView *b, GtkStatusbar *s, Exec_done_fun dfun = 0, gpointer udata = 0); ~Exec_box(); void show_status(const char *msg); // Set status bar. // Handle data from child. void read_from_child(char *data, int datalen, int exit_code); void add_message(const char *txt); // Add text to box. // Execute. bool exec(const char *file, char *argv[]); void kill_child(); // End. }; #endif exult-1.2/mapedit/objbrowse.cc0000644000175000001440000002366207713365507012146 #ifdef HAVE_CONFIG_H # include #endif #include #include #include "objbrowse.h" #include "shapegroup.h" #include "shapefile.h" #include "studio.h" #include "exceptions.h" using EStudio::Add_menu_item; using EStudio::Create_arrow_button; Object_browser::Object_browser(Shape_group *grp, Shape_file_info *fi) : group(grp), file_info(fi), popup(0), selected(-1), vscroll(0), hscroll(0), find_text(0), index0(0), loc_down(0), loc_up(0), move_down(0), move_up(0), config_width(0), config_height(0) { widget = 0; } Object_browser::~Object_browser() { if (popup) gtk_widget_destroy(popup); } void Object_browser::set_widget(GtkWidget *w) { widget = w; } /* * Search a name for a string, ignoring case. */ bool Object_browser::search_name ( const char *nm, const char *srch ) { char first = tolower(*srch); while (*nm) { if (tolower(*nm) == first) { const char *np = nm + 1, *sp = srch + 1; while (*sp && tolower(*np) == tolower(*sp)) { sp++; np++; } if (!*sp) // Matched to end of search string. return true; } nm++; } return false; } bool Object_browser::server_response(int , unsigned char *, int ) { return false; // Not handled here. } void Object_browser::end_terrain_editing() { } void Object_browser::set_background_color(guint32) { } GtkWidget *Object_browser::get_widget() { return widget; } void Object_browser::on_browser_group_add ( GtkMenuItem *item, gpointer udata ) { Object_browser *chooser = (Object_browser *) udata; Shape_group *grp = (Shape_group *) gtk_object_get_user_data( GTK_OBJECT(item)); int id = chooser->get_selected_id(); if (id >= 0) // Selected shape? { grp->add(id); // Add & redisplay open windows. ExultStudio::get_instance()->update_group_windows(grp); } } /* * Add an "Add to group..." submenu to a popup for our group. */ void Object_browser::add_group_submenu ( GtkWidget *popup ) { // Use our group, or assume we're in // the main window. Shape_group_file *groups = group ? group->get_file() : ExultStudio::get_instance()->get_cur_groups(); int gcnt = groups ? groups->size() : 0; if (gcnt > 1 || // Groups besides ours? (gcnt == 1 && !group)) { GtkWidget *mitem = Add_menu_item(popup, "Add to group..."); GtkWidget *group_menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), group_menu); for (int i = 0; i < gcnt; i++) { Shape_group *grp = groups->get(i); if (grp == group) continue;// Skip ourself. GtkWidget *gitem = Add_menu_item( group_menu, grp->get_name(), GTK_SIGNAL_FUNC ( Object_browser::on_browser_group_add), this); // Store group on menu item. gtk_object_set_user_data(GTK_OBJECT(gitem), grp); } } } /* * Okay clicked in file-selector. */ void File_selector_ok ( GtkButton *btn, gpointer user_data ) { GtkFileSelection *fsel = GTK_FILE_SELECTION(gtk_widget_get_toplevel( GTK_WIDGET(btn))); const char *fname = gtk_file_selection_get_filename(fsel); File_sel_okay_fun fun = (File_sel_okay_fun) gtk_object_get_user_data(GTK_OBJECT(fsel)); if (fname && *fname && fun) (*fun)(fname, user_data); } /* * Create a modal file selector. */ GtkFileSelection *Create_file_selection ( const char *title, File_sel_okay_fun ok_handler, gpointer user_data ) { GtkFileSelection *fsel = GTK_FILE_SELECTION(gtk_file_selection_new( title)); gtk_window_set_modal(GTK_WINDOW(fsel), true); gtk_object_set_user_data(GTK_OBJECT(fsel), (void *)ok_handler); gtk_signal_connect(GTK_OBJECT(fsel->ok_button), "clicked", GTK_SIGNAL_FUNC(File_selector_ok), user_data); // Destroy when done. gtk_signal_connect_object(GTK_OBJECT(fsel->ok_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fsel)); gtk_signal_connect_object(GTK_OBJECT(fsel->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fsel)); return fsel; } /* * Save file in browser. */ void Object_browser::on_browser_file_save ( GtkMenuItem *item, gpointer udata ) { Object_browser *chooser = (Object_browser *) udata; if (!chooser->file_info) return; // Nothing to write to. try { chooser->file_info->flush(); } catch (const exult_exception& e) { EStudio::Alert(e.what()); } } /* * Revert file in browser to what's on disk. */ void Object_browser::on_browser_file_revert ( GtkMenuItem *item, gpointer udata ) { Object_browser *chooser = (Object_browser *) udata; if (!chooser->file_info) return; // No file? char *msg = g_strdup_printf("Okay to throw away any changes to '%s'?", chooser->file_info->get_basename()); if (EStudio::Prompt(msg, "Yes", "No") != 0) return; if (!chooser->file_info->revert()) EStudio::Alert("Revert not yet implemented for this file"); else { chooser->load(); // Reload from file. chooser->render(); // Repaint. chooser->show(); } } /* * Set up popup menu for shape browser. */ GtkWidget *Object_browser::create_popup ( ) { if (popup) // Clean out old. gtk_widget_destroy(popup); popup = gtk_menu_new(); // Create popup menu. // Add "File" submenu. GtkWidget *mitem = Add_menu_item(popup, "File..."); GtkWidget *file_menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), file_menu); Add_menu_item(file_menu, "Save", GTK_SIGNAL_FUNC(on_browser_file_save), this); Add_menu_item(file_menu, "Revert", GTK_SIGNAL_FUNC(on_browser_file_revert), this); if (selected >= 0) // Item selected? Add groups. add_group_submenu(popup); return popup; } /* * Callbacks for controls: */ static void on_find_down (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->search(gtk_entry_get_text( GTK_ENTRY(chooser->get_find_text())), 1); } static void on_find_up (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->search(gtk_entry_get_text( GTK_ENTRY(chooser->get_find_text())), -1); } static gboolean on_find_key (GtkEntry *entry, GdkEventKey *event, gpointer user_data) { if (event->keyval == GDK_Return) { Object_browser *chooser = (Object_browser *) user_data; chooser->search(gtk_entry_get_text( GTK_ENTRY(chooser->get_find_text())), 1); return TRUE; } return FALSE; // Let parent handle it. } static void on_loc_down (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->locate(false); } static void on_loc_up (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->locate(true); } static void on_move_down (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->move(false); } static void on_move_up (GtkButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *) user_data; chooser->move(true); } /* * Create box with various controls. * * Note: 'this' is passed as user-data to all the signal handlers, * which call various virtual methods. */ GtkWidget *Object_browser::create_controls ( int controls // Browser_control flags. ) { GtkWidget *topframe = gtk_frame_new (NULL); gtk_widget_show(topframe); // Everything goes in here. GtkWidget *tophbox = gtk_hbox_new (FALSE, 0); gtk_widget_show (tophbox); gtk_container_add (GTK_CONTAINER (topframe), tophbox); /* * The 'Find' controls. */ if (controls & (int) find_controls) { GtkWidget *frame = gtk_frame_new("Find"); gtk_widget_show(frame); gtk_box_pack_start (GTK_BOX (tophbox), frame, FALSE, FALSE, 2); GtkWidget *hbox2 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox2); gtk_container_add (GTK_CONTAINER(frame), hbox2); find_text = gtk_entry_new (); gtk_widget_show (find_text); gtk_box_pack_start(GTK_BOX(hbox2), find_text, FALSE, FALSE, 0); gtk_widget_set_usize (find_text, 110, -2); GtkWidget *find_down = Create_arrow_button( GTK_ARROW_DOWN, GTK_SIGNAL_FUNC(on_find_down), this); gtk_box_pack_start(GTK_BOX(hbox2), find_down, FALSE, FALSE, 0); GtkWidget *find_up = Create_arrow_button(GTK_ARROW_UP, GTK_SIGNAL_FUNC(on_find_up), this); gtk_box_pack_start(GTK_BOX(hbox2), find_up, FALSE, FALSE, 0); gtk_signal_connect (GTK_OBJECT(find_text), "key-press-event", GTK_SIGNAL_FUNC(on_find_key), this); } /* * The 'Locate' controls. */ if (controls & (int) locate_controls) { GtkWidget *frame = gtk_frame_new ("Locate"); gtk_widget_show(frame); gtk_box_pack_start (GTK_BOX (tophbox), frame, FALSE, FALSE, 2); GtkWidget *bbox = gtk_hbox_new(TRUE, 0); gtk_widget_show (bbox); gtk_container_add (GTK_CONTAINER (frame), bbox); loc_down = Create_arrow_button(GTK_ARROW_DOWN, GTK_SIGNAL_FUNC(on_loc_down), this); gtk_box_pack_start(GTK_BOX (bbox), loc_down, FALSE, FALSE, 0); loc_up = Create_arrow_button(GTK_ARROW_UP, GTK_SIGNAL_FUNC(on_loc_up), this); gtk_box_pack_start(GTK_BOX (bbox), loc_up, FALSE, FALSE, 0); } /* * The 'Move' controls. */ if (controls & (int) move_controls) { GtkWidget *frame = gtk_frame_new ("Move"); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX (tophbox), frame, FALSE, FALSE, 2); GtkWidget *bbox = gtk_hbox_new(TRUE, 0); gtk_widget_show (bbox); gtk_container_add (GTK_CONTAINER (frame), bbox); move_down = Create_arrow_button(GTK_ARROW_DOWN, GTK_SIGNAL_FUNC(on_move_down), this); gtk_box_pack_start(GTK_BOX (bbox), move_down, FALSE, FALSE, 0); move_up = Create_arrow_button(GTK_ARROW_UP, GTK_SIGNAL_FUNC(on_move_up), this); gtk_box_pack_start (GTK_BOX (bbox), move_up, FALSE, FALSE, 0); } return topframe; } exult-1.2/mapedit/exult_studio.glade0000644000175000001440000202365210043107403013345 10 Select File GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True True True True GTK_RELIEF_NORMAL True True True GTK_RELIEF_NORMAL True ExultStudio GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True True _File True True True New game... True True _Open game... True True Save all True True True _New... True True True Shapes file... True True Single shape file... True True Save... True True True _Map True True _Shape info True True _Groups True True _Combos True True _Reload... True True True _Map True True _Usecode True True True _Connect True True _Preferences... True True E_xit True True _Edit True True True _Cut True True C_opy True True _Paste True True True Properties... True True Basic properties... True True True Create _egg... True True Create _NPC... True True _Mode True True True Move True True True Paint True False move1 True Paint with chunks True False move1 True Pick for combo True False move1 True _Tools True True True Locator... True True New combo... True True Unused shapes... True True Compile usecode... True 0 False False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 4 True Play True GTK_RELIEF_NORMAL False False 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True True Grid True GTK_RELIEF_NORMAL False False True 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True False 0 True Edit lift: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 13 1 4 4 2 True True 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True False 0 True Hide lift: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True 1 0 False GTK_UPDATE_ALWAYS False False 12 0 13 1 4 4 2 True True 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True True Edit terrain True GTK_RELIEF_NORMAL False False True 0 False True 0 False False True 1 200 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True GTK_POS_TOP False False True GTK_POLICY_ALWAYS GTK_POLICY_ALWAYS GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True True False False True False True True Files False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True GTK_POLICY_ALWAYS GTK_POLICY_ALWAYS GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True True False False True 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True True True 0 True * False 0 True True True True 0 True True Add True GTK_RELIEF_NORMAL 0 False False True True Del True GTK_RELIEF_NORMAL 0 False False 0 False False 2 False True False True True Groups False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab False False True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 0 True True 0 True True True True 0 False False Exult Egg GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 2 True True 0 True True 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Cached in True True Party near True True Avatar near True True Avatar far True True Avatar footpad True True Party footpad True True Something on True True External True True Criteria False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 True GTK_UPDATE_ALWAYS False True 0 0 100 1 10 10 True Probability False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 2 2 False 0 0 True True Nocturnal True GTK_RELIEF_NORMAL False False True 0 1 0 1 True True Once-only True GTK_RELIEF_NORMAL False False True 1 2 0 1 True True Hatched True GTK_RELIEF_NORMAL False False True 0 1 1 2 True True Auto-reset True GTK_RELIEF_NORMAL False False True 1 2 1 2 True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 1 0 31 1 5 5 True Distance False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True 0 False False True 0 True True 4 True True True True GTK_POS_TOP True False 6 True False 12 True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Shape Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 False False 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Frame Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 False False 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 0 True True 0 True True True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Combat True True Horiz. pace True True Vert. pace True True Talk True True Dance True True Eat True True Farm True True Tend shop True True Miner True True Hound True True Stand True True Loiter True True Wander True True Blacksmith True True Sleep True True Wait True True Sit True True Graze True True Bake True True Sew True True Shy True True Lab True True Thief True True Waiter True True Special True True Kid games True True Eat at inn True True Duel True True Preach True True Patrol True True Desk work True True Schedule False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 False False True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Friendly True True Neutral True True Hostile True True Random True True Alignment False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 False False True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 True GTK_UPDATE_ALWAYS False True 1 1 31 1 5 10 True Count False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 False False 0 True True False True True Monster False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Score Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True True Continuous True GTK_RELIEF_NORMAL False False True True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Jukebox False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Sfx Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True True Continuous True GTK_RELIEF_NORMAL False False True True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Sound Effect False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Speech Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item False True True Voice False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Function Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Quality False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Usecode False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Shape Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True North True True Northeast True True East True True Southeast True True South True True Southwest True True West True True Northwest True True Party member True True Direction False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 255 1 10 10 True Delay (seconds) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Missile False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 2 True False 2 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True False 0 4 True False 4 True X: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True True True 0 True * False 0 True True 0 True True 4 True False 4 True Y: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True True True 0 True * False 0 True True 0 False False 0 True True 8 True True Use Coordinates True GTK_RELIEF_NORMAL False False True 0 False False True Coordinates False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Egg Path Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Teleport False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Halt True True Storm True True Magic storm True True Clouds True True Weather False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True False True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 1 0 255 1 10 10 True Duration (game mins.) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Weather False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 255 1 10 10 True Number False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item False True True Path False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 255 1 10 10 True Distance False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item False True True Button False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 4 True True True 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 True True True True 0 False False Exult NPC GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True Face #000 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True False 0 True 2 2 False 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Name False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Usecode False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Ident False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False True True True 0 True * False True NPC # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill fill 0 True True 0 True True True 2 2 False 0 0 64 True 0 0.5 GTK_SHADOW_ETCHED_IN True 1 2 0 2 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Shape # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Frame # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill fill 0 True True 0 True True True True 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Neutral True True Friendly True True Hostile True True Random True True Alignment False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Nearest True True Weakest True True Strongest True True Beserk True True Protect True True Defend True True Flank True True Flee True True Random True True Manual True True Attack mode False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True 8 True True True True GTK_POS_TOP False False 4 True 5 2 True 4 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Strength False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Dexterity False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Intelligence False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 2 3 fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Health False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 3 4 fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Combat False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 4 5 fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Mana False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Max. Mana False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 fill fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Training False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 2 3 fill fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100000 1 100 10000 True Experience False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 3 4 fill fill True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 60 1 10 10 True Food Level False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 4 5 fill fill False True True Properties False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True 11 3 True 0 0 True True Bleeding True GTK_RELIEF_NORMAL False False True 1 2 0 1 fill True True Asleep True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Charmed True GTK_RELIEF_NORMAL False False True 2 3 0 1 fill True True Confused True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Conjured True GTK_RELIEF_NORMAL False False True 1 2 1 2 fill True True Cursed True GTK_RELIEF_NORMAL False False True 2 3 1 2 fill True True Dancing True GTK_RELIEF_NORMAL False False True 0 1 2 3 fill True True Don't move True GTK_RELIEF_NORMAL False False True 1 2 2 3 fill True True Ethereal True GTK_RELIEF_NORMAL False False True 2 3 2 3 fill True True Fly True GTK_RELIEF_NORMAL False False True 0 1 3 4 fill True True Freeze True GTK_RELIEF_NORMAL False False True 1 2 3 4 fill True True In action True GTK_RELIEF_NORMAL False False True 2 3 3 4 fill True True In motion True GTK_RELIEF_NORMAL False False True 0 1 4 5 fill True True In party True GTK_RELIEF_NORMAL False False True 1 2 4 5 fill True True Invisible True GTK_RELIEF_NORMAL False False True 0 1 5 6 fill True True Met True GTK_RELIEF_NORMAL False False True 1 2 5 6 fill True True Naked True GTK_RELIEF_NORMAL False False True 2 3 5 6 fill True True No magic True GTK_RELIEF_NORMAL False False True 0 1 6 7 fill True True Okay to land True GTK_RELIEF_NORMAL False False True 1 2 6 7 fill True True Paralyzed True GTK_RELIEF_NORMAL False False True 2 3 6 7 fill True True Petra True GTK_RELIEF_NORMAL False False True 0 1 7 8 fill True True Poisoned True GTK_RELIEF_NORMAL False False True 1 2 7 8 fill True True Polymorph True GTK_RELIEF_NORMAL False False True 2 3 7 8 fill True True Protection True GTK_RELIEF_NORMAL False False True 0 1 8 9 fill True True Female True GTK_RELIEF_NORMAL False False True 1 2 8 9 fill True True Summoned True GTK_RELIEF_NORMAL False False True 2 3 8 9 fill True True Swim True GTK_RELIEF_NORMAL False False True 0 1 9 10 fill True True Tattooed True GTK_RELIEF_NORMAL False False True 1 2 9 10 fill True True Tournament True GTK_RELIEF_NORMAL False False True 2 3 9 10 fill True True Tremor True GTK_RELIEF_NORMAL False False True 0 1 10 11 fill True True Walk True GTK_RELIEF_NORMAL False False True 1 2 10 11 fill True True Zombie True GTK_RELIEF_NORMAL False False True 2 3 10 11 fill False True checkbutton101 True GTK_RELIEF_NORMAL False False True 2 3 4 5 fill False True True Flags False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 6 True 10 4 False 4 2 True True Set True GTK_RELIEF_NORMAL 2 3 2 3 True True Set True GTK_RELIEF_NORMAL 2 3 3 4 True True Set True GTK_RELIEF_NORMAL 2 3 4 5 True True Set True GTK_RELIEF_NORMAL 2 3 5 6 True True Set True GTK_RELIEF_NORMAL 2 3 6 7 True True Set True GTK_RELIEF_NORMAL 2 3 7 8 True True Set True GTK_RELIEF_NORMAL 2 3 8 9 True True Set True GTK_RELIEF_NORMAL 2 3 9 10 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 9 10 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 8 9 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 7 8 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 6 7 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 5 6 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 4 5 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 3 4 True --- False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 2 3 True Midnight: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 2 3 True 3:00 AM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 3 4 True 6:00 AM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 4 5 True 9:00 AM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 5 6 True 12:00 Noon: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 6 7 True 3:00 PM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 7 8 True 6:00 PM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 8 9 True 9:00 PM: False False GTK_JUSTIFY_LEFT False False 0.2 0.5 0 0 0 1 9 10 True Time False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 1 0 1 True Activity False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 1 2 0 1 True Location (x,y,z) False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 3 4 0 1 fill True False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 2 3 0 1 True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 2 3 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 3 4 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 4 5 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 5 6 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 6 7 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 7 8 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 8 9 fill fill True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 3072 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 15 1 10 10 0 True True True True Game True GTK_RELIEF_NORMAL 0 False False 3 4 9 10 fill fill True 0 4 1 2 3 False True True Schedules False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 0 True True True 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 True True True True 0 False False Exult Schedule GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE True True False True True False 0 True GTK_BUTTONBOX_SPREAD True True True Cancel True GTK_RELIEF_NORMAL 0 0 False True GTK_PACK_END True 11 3 True 0 0 True True Combat True GTK_RELIEF_NORMAL 0 1 0 1 True True Horiz. Pace True GTK_RELIEF_NORMAL 1 2 0 1 True True Vert. Pace True GTK_RELIEF_NORMAL 2 3 0 1 True True --None-- True GTK_RELIEF_NORMAL 2 3 10 11 True True Talk True GTK_RELIEF_NORMAL 0 1 1 2 True True Desk Work True GTK_RELIEF_NORMAL 0 1 10 11 True True Duel True GTK_RELIEF_NORMAL 0 1 9 10 True True Special True GTK_RELIEF_NORMAL 0 1 8 9 True True Lab Work True GTK_RELIEF_NORMAL 0 1 7 8 True True Bake True GTK_RELIEF_NORMAL 0 1 6 7 True True Wait True GTK_RELIEF_NORMAL 0 1 5 6 True True Wander True GTK_RELIEF_NORMAL 0 1 4 5 True True Hound True GTK_RELIEF_NORMAL 0 1 3 4 True True Farm True GTK_RELIEF_NORMAL 0 1 2 3 True True Follow True GTK_RELIEF_NORMAL 1 2 10 11 True True Preach True GTK_RELIEF_NORMAL 1 2 9 10 True True Kid Games True GTK_RELIEF_NORMAL 1 2 8 9 True True Thief True GTK_RELIEF_NORMAL 1 2 7 8 True True Sew True GTK_RELIEF_NORMAL 1 2 6 7 True True Sit True GTK_RELIEF_NORMAL 1 2 5 6 True True Blacksmith True GTK_RELIEF_NORMAL 1 2 4 5 True True Stand True GTK_RELIEF_NORMAL 1 2 3 4 True True Tend Shop True GTK_RELIEF_NORMAL 1 2 2 3 True True Dance True GTK_RELIEF_NORMAL 1 2 1 2 True True Eat True GTK_RELIEF_NORMAL 2 3 1 2 True True Miner True GTK_RELIEF_NORMAL 2 3 2 3 True True Loiter True GTK_RELIEF_NORMAL 2 3 3 4 True True Sleep True GTK_RELIEF_NORMAL 2 3 4 5 True True Graze True GTK_RELIEF_NORMAL 2 3 5 6 True True Shy True GTK_RELIEF_NORMAL 2 3 6 7 True True Waiter True GTK_RELIEF_NORMAL 2 3 7 8 True True Eat at Inn True GTK_RELIEF_NORMAL 2 3 8 9 True True Patrol True GTK_RELIEF_NORMAL 2 3 9 10 0 True True Exult Object GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True True 0 True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True False True 0 True * False True Name False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 255 1 10 10 True Quality False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 1023 1 10 10 True Shape # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False True 0 0 100 1 10 10 True Frame # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True 0 True True 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 3071 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 3071 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 15 1 3 3 0 True True True Position (x, y, z) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 True True Exult Shape Info GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 64 True 0 0.5 GTK_SHADOW_ETCHED_IN True 0 False True True 2 2 True 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True False True 0 True * False True Shape False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Name False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Frame False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True Origin (x,y) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 fill fill 0 True True 0 True True 8 True True True True GTK_POS_TOP False False True False 0 True 2 3 True 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True Tiles (x,y,z) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Unusable True True Quality True True Quantity True True Breakable True True Quality Flags True True Container True True Hatchable True True Spellbook True True Barge True True Virtue Stone True True Monster True True Human True True Building True True Class False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Head True True Back True True Belt True True Left Hand True True Left Finger True True Legs True True Feet True True Right Finger True True Right Hand True True Torso True True Neck True True Ammo True True Back 2H True True Shield True True Ears True True Clock True True Hands 2 True True Usecode True True LR Hand True True Ready spot False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Weight False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Volume False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True True In-hand offset (x,y) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 4 4 True 0 0 True True Sound effect True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Strange True GTK_RELIEF_NORMAL False False True 1 2 0 1 fill True True Animated True GTK_RELIEF_NORMAL False False True 2 3 0 1 fill True True Solid True GTK_RELIEF_NORMAL False False True 3 4 0 1 fill True True Water True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Poisonous True GTK_RELIEF_NORMAL False False True 1 2 1 2 fill True True Field True GTK_RELIEF_NORMAL False False True 2 3 1 2 fill True True Door True GTK_RELIEF_NORMAL False False True 3 4 1 2 fill True True Barge part True GTK_RELIEF_NORMAL False False True 0 1 2 3 fill True True Transparent True GTK_RELIEF_NORMAL False False True 1 2 2 3 fill True True Light source True GTK_RELIEF_NORMAL False False True 2 3 2 3 fill True True X-obstacle True GTK_RELIEF_NORMAL False False True 0 1 3 4 fill True True Y-obstacle True GTK_RELIEF_NORMAL False False True 1 2 3 4 fill True True Occludes True GTK_RELIEF_NORMAL False False True 2 3 3 4 fill True True Translucent True GTK_RELIEF_NORMAL False False True 3 4 2 3 fill True False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 3 4 3 4 True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Weapon True GTK_RELIEF_NORMAL False False True 0 True True True True Ammo True GTK_RELIEF_NORMAL False False True 0 True True True True Armor True GTK_RELIEF_NORMAL False False True 0 True True True True Monster True GTK_RELIEF_NORMAL False False True 0 True True True Extra False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Object False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 3 3 True 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Damage False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Range False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 4 True True 0 True True Use True True None True True Charges True True Thrown True 0 False False True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 1024 1 20 20 0 True True True Ammo False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Projectile False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 True * False True Usecode False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 2 3 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Hand True True Thrown (poor) True True Thrown True True Fires True True Use False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 1 2 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Sound Effect False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 2 3 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Hit sound effect False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 2 3 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Normal True True Fire True True Magic True True Poison True True Damage Type False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 0 1 fill 0 False False 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 4 4 True 0 0 True True Sleep True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Charm True GTK_RELIEF_NORMAL False False True 1 2 0 1 fill True True Curse True GTK_RELIEF_NORMAL False False True 2 3 0 1 fill True True Poison True GTK_RELIEF_NORMAL False False True 3 4 0 1 fill True True Paralyze True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Magebane True GTK_RELIEF_NORMAL False False True 1 2 1 2 fill True True Explodes True GTK_RELIEF_NORMAL False False True 2 3 1 2 fill True True Returns True GTK_RELIEF_NORMAL False False True 3 4 1 2 fill 6 True 0 0.5 GTK_SHADOW_ETCHED_IN 2 True False 0 True True Raise True GTK_RELIEF_NORMAL False False True 0 False False True True Reach True GTK_RELIEF_NORMAL False False True 0 False False True Strike Frames False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 2 2 4 fill fill 6 True 0 0.5 GTK_SHADOW_ETCHED_IN 2 True False 0 True True Raise True GTK_RELIEF_NORMAL False False True 0 False False True True Reach True GTK_RELIEF_NORMAL False False True 0 False False True Projectile Frames False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 4 2 4 fill fill True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Weapon False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 1 3 True 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Damage False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 1024 1 4 4 True Family False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True Normal True True Fire True True Magic True True Poison True True Damage Type False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 0 1 fill 0 False True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 2 4 True 0 0 True True Sleep True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Charm True GTK_RELIEF_NORMAL False False True 1 2 0 1 fill True True Curse True GTK_RELIEF_NORMAL False False True 2 3 0 1 fill True True Poison True GTK_RELIEF_NORMAL False False True 3 4 0 1 fill True True Paralyze True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Magebane True GTK_RELIEF_NORMAL False False True 1 2 1 2 fill True True Explodes True GTK_RELIEF_NORMAL False False True 2 3 1 2 fill True False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 3 4 1 2 True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Ammo False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Points False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 False False 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 4 1 False 0 0 True True Normal True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Fire True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Magic True GTK_RELIEF_NORMAL False False True 0 1 2 3 fill True True Poison True GTK_RELIEF_NORMAL False False True 0 1 3 4 fill True Immunity False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Armor False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab True False 0 True 3 3 True 0 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Dexterity False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Intelligence False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Combat False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 1 2 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Armor False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 1 2 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Reach False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 1 2 2 3 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 0 True True 4 True True Edit True GTK_RELIEF_NORMAL 0 False False True Equip. Rec. # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 2 3 2 3 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Strength False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 0 1 fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN 1 True True 0 True True Friendly True True Neutral True True Hostile True True Random True True Alignment False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 1 2 fill fill 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 4 4 True Weapon Damage False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 1 2 3 fill fill 0 False True True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 2 2 True 0 0 True True Normal True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Fire True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Magic True GTK_RELIEF_NORMAL False False True 1 2 0 1 True True Poison True GTK_RELIEF_NORMAL False False True 1 2 1 2 True Vulnerable False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 2 2 True 0 0 True True Normal True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Fire True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Magic True GTK_RELIEF_NORMAL False False True 1 2 0 1 True True Poison True GTK_RELIEF_NORMAL False False True 1 2 1 2 True Immune False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 3 4 True 0 0 False True True GTK_RELIEF_NORMAL False False True 3 4 2 3 fill True True Splits True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True Poison-safe True GTK_RELIEF_NORMAL False False True 0 1 1 2 fill True True Ethereal True GTK_RELIEF_NORMAL False False True 0 1 2 3 fill True True Can't die True GTK_RELIEF_NORMAL False False True 1 2 0 1 fill True True Flies True GTK_RELIEF_NORMAL False False True 1 2 1 2 fill True True No body True GTK_RELIEF_NORMAL False False True 1 2 2 3 fill True True Can't yell True GTK_RELIEF_NORMAL False False True 2 3 0 1 fill True True Swims True GTK_RELIEF_NORMAL False False True 2 3 1 2 fill False True True GTK_RELIEF_NORMAL False False True 2 3 2 3 fill True True Can't bleed True GTK_RELIEF_NORMAL False False True 3 4 0 1 fill True True Walks True GTK_RELIEF_NORMAL False False True 3 4 1 2 fill True Flags False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True False True True Monster False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 tab 0 False True True GTK_BUTTONBOX_SPREAD 30 True True True True Okay True GTK_RELIEF_NORMAL True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 True True Monster Equipment GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 1 0 False GTK_UPDATE_ALWAYS False False 0 0 100 1 10 10 True Record # False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 False False True GTK_POLICY_NEVER GTK_POLICY_ALWAYS GTK_SHADOW_NONE GTK_CORNER_TOP_LEFT True GTK_SHADOW_IN True 1 1 False 0 0 True False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 1 0 1 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 False True Exult Shape Group GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True False 0 True Move: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True GTK_RELIEF_NORMAL True GTK_ARROW_UP GTK_SHADOW_OUT 0.5 0.5 0 0 2 False False True True GTK_RELIEF_NORMAL True GTK_ARROW_DOWN GTK_SHADOW_OUT 0.5 0.5 0 0 0 False False 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True True Remove True GTK_RELIEF_NORMAL 0 False False 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True Name: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True True True 0 True * False 0 True True 0 True True 0 False False True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 0 True True ExultStudio Prompt GTK_WINDOW_TOPLEVEL GTK_WIN_POS_MOUSE True True False True True False 0 True GTK_BUTTONBOX_SPREAD True True True Yes True GTK_RELIEF_NORMAL 0 True True True No True GTK_RELIEF_NORMAL 0 True True True Cancel True GTK_RELIEF_NORMAL 0 0 False True GTK_PACK_END True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True False 0 True A question to ask False False GTK_JUSTIFY_LEFT False False 0.05 0.5 2 12 0 True True 0 True True Exult Locator GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 2 True 0 0.5 GTK_SHADOW_ETCHED_OUT 0.5 0.5 1 False 2 True 2 2 False 0 0 True 1 2 1 2 fill fill True True True GTK_POS_TOP 0 GTK_UPDATE_CONTINUOUS False 0 0 0 0 0 0 1 2 0 1 fill fill True True True GTK_POS_TOP 0 GTK_UPDATE_CONTINUOUS False 0 0 0 0 0 0 0 1 1 2 fill fill True 0 0.5 GTK_SHADOW_IN 0.5 0.5 1 True True 0 1 0 1 0 True True True GTK_BUTTONBOX_DEFAULT_STYLE 30 True True True Close True GTK_RELIEF_NORMAL 0 False False ExultStudio Preferences GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 6 True 4 2 False 0 0 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True Image Editor Command: False False GTK_JUSTIFY_LEFT False False 0.1 0.5 0 0 0 1 0 1 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True Default Game Name: False False GTK_JUSTIFY_LEFT False False 0.1 0.5 0 0 0 1 2 3 fill 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 blackgate True * False 1 2 2 3 fill fill True 0.5 0.5 1 1 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True True True True 0 gimp-remote -n True * False 1 2 0 1 fill 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True Shape List Background: False False GTK_JUSTIFY_LEFT False False 0.1 0.5 0 0 0 1 3 4 fill 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 4 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 16 True 2 True True True True ... True GTK_RELIEF_NORMAL 0 True True 1 2 3 4 fill fill 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True Image-Edit Filetype: False False GTK_JUSTIFY_LEFT False False 0.1 0.5 0 0 0 1 1 2 fill 2 True 0 0.5 GTK_SHADOW_ETCHED_IN True True 0 True True .PNG True True .SHP True 1 2 1 2 fill fill 0 False True True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True Apply True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 False True Exult New Shape GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE True True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN 8 True 2 2 False 2 2 True True 1 0 True GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 1 2 0 1 True True 1 0 True GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 1 2 1 2 True Create new shape #: False False GTK_JUSTIFY_CENTER False False 0 0.5 0 0 0 1 0 1 4 4 True Initial number of frames: False False GTK_JUSTIFY_CENTER False False 0 0.5 0 0 0 1 1 2 4 4 0 False True True 0 0.5 GTK_SHADOW_ETCHED_IN True 3 2 False 0 0 4 True True From font: True GTK_RELIEF_NORMAL False False True 0 1 0 1 fill True True True True 0 True * False 1 2 0 1 True True 1 0 False GTK_UPDATE_ALWAYS False False 16 0 100 1 10 10 1 2 1 2 True False 4 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 0 True True 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True 0 True True 1 2 2 3 fill fill True Height (pixels): False False GTK_JUSTIFY_CENTER False False 0 0.5 0 0 0 1 1 2 6 True Color (from palette): False False GTK_JUSTIFY_CENTER False False 0 0.5 0 0 0 1 2 3 6 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True Cancel True GTK_RELIEF_NORMAL 0 False False Exult Tiles GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE True True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True 3 2 False 0 0 True False 0 True True by rows True GTK_RELIEF_NORMAL True False True 0 False False True True by columns True GTK_RELIEF_NORMAL False False True tiled_by_rows 0 False False 1 2 0 1 fill True Export tiled..... False False GTK_JUSTIFY_LEFT False False 0 0.5 21 0 0 1 0 1 fill True True 1 0 False GTK_UPDATE_ALWAYS False False 4 0 100 1 10 10 0 1 2 3 4 True 0 2 1 2 fill True ...tiles at a time. False False GTK_JUSTIFY_CENTER False False 0.16 0.5 2 0 1 2 2 3 4 16 fill 0 True True True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True cancel True GTK_RELIEF_NORMAL 0 False True Exult Combo-Builder GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True False 0 True Name: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 8 0 0 False True True True True True 0 True * False 4 True True 0 False True True False 0 True GTK_POLICY_ALWAYS GTK_POLICY_ALWAYS GTK_SHADOW_NONE GTK_CORNER_TOP_LEFT True GTK_SHADOW_IN True 0 True True 2 True True 0 False False 2 True False 4 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 0 True True True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 0 True True True Location (x,y,z) False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 True True 1 0 False GTK_UPDATE_ALWAYS False False 1 0 100 1 10 10 0 True True True Order False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 label_item 0 True True 8 True True Remove True GTK_RELIEF_NORMAL 0 False True 2 False True 0 True True True 0 0.5 GTK_SHADOW_ETCHED_IN True GTK_BUTTONBOX_SPREAD 30 True True True Okay True GTK_RELIEF_NORMAL True True True Apply True GTK_RELIEF_NORMAL True True True cancel True GTK_RELIEF_NORMAL 0 False True Exult Messages GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True GTK_POLICY_AUTOMATIC GTK_POLICY_ALWAYS GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True False GTK_JUSTIFY_LEFT GTK_WRAP_WORD True 0 0 0 0 0 0 0 True True True GTK_BUTTONBOX_DEFAULT_STYLE 30 True True True Done True GTK_RELIEF_NORMAL 0 False True Exult: Compiling GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False 0 True 0 0.5 GTK_SHADOW_ETCHED_IN True False 0 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True True 0 2 True True Compile True GTK_RELIEF_NORMAL 0 True True 2 True True Halt True GTK_RELIEF_NORMAL 0 True True 0 True True 2 True 0 0.5 GTK_SHADOW_ETCHED_IN 4 True False 0 True Source: False False GTK_JUSTIFY_CENTER False False 0.5 0.5 0 0 0 False False True True True True 0 usecode.uc True * False 0 True True 0 True True 0 False True True 0 0.5 GTK_SHADOW_ETCHED_IN True GTK_POLICY_NEVER GTK_POLICY_ALWAYS GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True False GTK_JUSTIFY_LEFT GTK_WRAP_WORD True 0 0 0 0 0 0 0 True True True True 0 False False exult-1.2/mapedit/studio.cc0000644000175000001440000016176510043110315011437 /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #ifdef XWIN #include #endif #include #include #include #include /* These are for sockets. */ #ifdef WIN32 #include #include #include "servewin32.h" #else #include #include #endif #include #include #include "shapelst.h" #include "shapevga.h" #include "Flex.h" #include "studio.h" #include "utils.h" #include "u7drag.h" #include "shapegroup.h" #include "shapefile.h" #include "locator.h" #include "combo.h" #include "Configuration.h" #include "objserial.h" #include "exceptions.h" #include "logo.xpm" #include "fnames.h" #include "execbox.h" using std::cerr; using std::cout; using std::endl; using std::string; using std::vector; using std::ofstream; ExultStudio *ExultStudio::self = 0; Configuration *config = 0; const std::string c_empty_string; // Used by config. library. // Mode menu items: static char *mode_names[4] = {"move1", "paint1", "paint_with_chunks1", "pick_for_combo1"}; enum ExultFileTypes { ShapeArchive =1, ChunkArchive, PaletteFile, FlexArchive, ComboArchive }; typedef struct _FileTreeItem FileTreeItem; struct _FileTreeItem { const gchar *label; ExultFileTypes datatype; FileTreeItem *children; }; /* columns */ enum { FOLDER_COLUMN = 0, FILE_COLUMN, DATA_COLUMN, NUM_COLUMNS }; static void Filelist_selection(GtkTreeView *treeview, GtkTreePath *path) { int type = -1; char *text; GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, FILE_COLUMN, &text, DATA_COLUMN, &type,-1); printf("%s %d\n",text,type); ExultStudio *studio = ExultStudio::get_instance(); switch(type) { case ShapeArchive: studio->set_browser("Shape Browser", studio->create_browser(text)); break; case ComboArchive: studio->set_browser("Combo Browser", studio->create_browser(text)); break; case ChunkArchive: studio->set_browser("Chunk Browser", studio->create_browser(text)); break; case PaletteFile: studio->set_browser("Palette Browser", studio->create_browser(text)); break; default: break; } g_free(text); } C_EXPORT void on_filelist_tree_cursor_changed(GtkTreeView *treeview) { GtkTreePath *path; GtkTreeViewColumn *col; gtk_tree_view_get_cursor(treeview, &path, &col); Filelist_selection(treeview, path); } C_EXPORT void on_open_game_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->choose_game_path(); } C_EXPORT void on_new_game_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->new_game(); } C_EXPORT void on_connect_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->connect_to_server(); } C_EXPORT void on_save_all1_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->save_all(); } C_EXPORT void on_new_shapes_file_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->new_shape_file(false); } C_EXPORT void on_new_shape_file_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->new_shape_file(true); } C_EXPORT void on_save_map_menu_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->write_map(); } C_EXPORT void on_read_map_menu_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->read_map(); } C_EXPORT void on_save_shape_info1_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->write_shape_info(); } C_EXPORT void on_reload_usecode_menu_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->reload_usecode(); } C_EXPORT void on_compile_usecode_menu_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->compile(); } C_EXPORT void on_save_groups1_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->save_groups(); } C_EXPORT void on_save_combos1_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->save_combos(); } C_EXPORT void on_preferences_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->open_preferences(); } C_EXPORT void on_cut1_activate (GtkMenuItem *menuitem, gpointer user_data) { unsigned char z = 0; ExultStudio::get_instance()->send_to_server(Exult_server::cut, &z, 1); } C_EXPORT void on_copy1_activate (GtkMenuItem *menuitem, gpointer user_data) { unsigned char o = 1; ExultStudio::get_instance()->send_to_server(Exult_server::cut, &o, 1); } C_EXPORT void on_paste1_activate (GtkMenuItem *menuitem, gpointer user_data) { ExultStudio::get_instance()->send_to_server(Exult_server::paste); } C_EXPORT void on_properties1_activate (GtkMenuItem *menuitem, gpointer user_data) { unsigned char o = 0; // 0=npc/egg properties. ExultStudio::get_instance()->send_to_server( Exult_server::edit_selected, &o, 1); } C_EXPORT void on_basic_properties1_activate (GtkMenuItem *menuitem, gpointer user_data) { unsigned char o = 1; // 1=basic object properties. ExultStudio::get_instance()->send_to_server( Exult_server::edit_selected, &o, 1); } C_EXPORT void on_move1_activate (GtkMenuItem *menuitem, gpointer user_data) { // NOTE: modes are defined in cheat.h. if (GTK_CHECK_MENU_ITEM(menuitem)->active) ExultStudio::get_instance()->set_edit_mode(0); } C_EXPORT void on_paint1_activate (GtkMenuItem *menuitem, gpointer user_data) { if (GTK_CHECK_MENU_ITEM(menuitem)->active) ExultStudio::get_instance()->set_edit_mode(1); } C_EXPORT void on_paint_with_chunks1_activate (GtkMenuItem *menuitem, gpointer user_data) { if (GTK_CHECK_MENU_ITEM(menuitem)->active) ExultStudio::get_instance()->set_edit_mode(2); } C_EXPORT void on_pick_for_combo1_activate (GtkMenuItem *menuitem, gpointer user_data) { if (GTK_CHECK_MENU_ITEM(menuitem)->active) ExultStudio::get_instance()->set_edit_mode(3); } C_EXPORT void on_unused_shapes1_activate (GtkMenuItem *menuitem, gpointer user_data) { if (EStudio::Prompt( "Finding unused shapes may take several minutes\nProceed?", "Yes", "No") != 0) return; ExultStudio::get_instance()->send_to_server( Exult_server::unused_shapes); } C_EXPORT void on_play_button_clicked (GtkToggleButton *button, gpointer user_data) { ExultStudio::get_instance()->set_play( gtk_toggle_button_get_active(button)); } C_EXPORT void on_tile_grid_button_toggled (GtkToggleButton *button, gpointer user_data) { ExultStudio::get_instance()->set_tile_grid( gtk_toggle_button_get_active(button)); } C_EXPORT void on_edit_lift_spin_changed (GtkSpinButton *button, gpointer user_data) { ExultStudio::get_instance()->set_edit_lift( gtk_spin_button_get_value_as_int(button)); } C_EXPORT void on_hide_lift_spin_changed (GtkSpinButton *button, gpointer user_data) { ExultStudio::get_instance()->set_hide_lift( gtk_spin_button_get_value_as_int(button)); } C_EXPORT void on_edit_terrain_button_toggled (GtkToggleButton *button, gpointer user_data) { ExultStudio::get_instance()->set_edit_terrain( gtk_toggle_button_get_active(button)); } void on_choose_directory (gchar *dir, gpointer user_data) { ExultStudio::get_instance()->set_game_path(dir); } /* * Configure main window. */ C_EXPORT gint on_main_window_configure_event ( GtkWidget *widget, // The view window. GdkEventConfigure *event, gpointer data ) { ExultStudio *studio = ExultStudio::get_instance(); // Configure "Hide lift" spin range. studio->set_spin("hide_lift_spin", studio->get_spin("hide_lift_spin"), 1, 16); return FALSE; } /* * Main window's close button. */ C_EXPORT gboolean on_main_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { if (!ExultStudio::get_instance()->okay_to_close()) return TRUE; // Can't quit. return FALSE; } C_EXPORT void on_main_window_destroy_event ( GtkWidget *widget, gpointer data ) { gtk_main_quit(); } /* * "Exit" in main window. */ C_EXPORT void on_main_window_quit (GtkMenuItem *menuitem, gpointer user_data) { if (ExultStudio::get_instance()->okay_to_close()) gtk_main_quit(); } /* * Main window got focus. */ C_EXPORT gboolean on_main_window_focus_in_event ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data ) { Shape_chooser::check_editing_files(); return FALSE; } /* * Set up everything. */ ExultStudio::ExultStudio(int argc, char **argv): files(0), curfile(0), names(0), glade_path(0), shape_info_modified(false), shape_names_modified(false), vgafile(0), facefile(0), eggwin(0), server_socket(-1), server_input_tag(-1), static_path(0), image_editor(0), default_game(0), background_color(0), browser(0), palbuf(0), egg_monster_draw(0), egg_ctx(0), waiting_for_server(0), npcwin(0), npc_draw(0), npc_face_draw(0), npc_ctx(0), npc_status_id(0), objwin(0), obj_draw(0), shapewin(0), shape_draw(0), equipwin(0), locwin(0), combowin(0), compilewin(0), compile_box(0) { // Initialize the various subsystems self = this; gtk_init( &argc, &argv ); gdk_rgb_init(); glade_init(); config = new Configuration; config->read_config_file(USER_CONFIGURATION_FILE); // Get options. const char *xmldir = 0; // Default: Look here for .glade. const char *game = 0; // Game to look up in .exult.cfg. static char *optstring = "g:x:d:"; extern int optind, opterr, optopt; extern char *optarg; opterr = 0; // Don't let getopt() print errs. int optchr; while ((optchr = getopt(argc, argv, optstring)) != -1) switch (optchr) { case 'g': // Game. Replaces use of -d, -x. game = optarg; break; case 'x': // XML (.glade) directory. xmldir = optarg; break; } string dirstr, datastr; if (!xmldir) { config->value("config/disk/data_path", datastr, EXULT_DATADIR); xmldir = datastr.c_str(); } string defgame; // Default game name. config->value("config/estudio/default_game", defgame, "blackgate"); default_game = g_strdup(defgame.c_str()); if (!game) game = default_game; config->set("config/estudio/default_game", defgame, true); char path[256]; // Set up paths. if(xmldir) strcpy(path, xmldir); else if(U7exists(EXULT_DATADIR"/exult_studio.glade")) strcpy(path,EXULT_DATADIR); else strcpy(path,"."); strcat(path, "/exult_studio.glade"); // Load the Glade interface app_xml = glade_xml_new(path, NULL, NULL); app = glade_xml_get_widget( app_xml, "main_window" ); glade_path = g_strdup(path); // More setting up... // Connect signals automagically. glade_xml_signal_autoconnect(app_xml); int w, h; // Get main window dims. config->value("config/estudio/main/width", w, 0); config->value("config/estudio/main/height", h, 0); if (w > 0 && h > 0) //++++Used to work gtk_window_set_default_size(GTK_WINDOW(app), w, h); gtk_window_resize(GTK_WINDOW(app), w, h); gtk_widget_show( app ); // Background color for shape browser. int bcolor; config->value("config/estudio/background_color", bcolor, 0); background_color = bcolor; if (game) // Game given? { string d("config/disk/game/"); d += game; string gd = d + "/path"; config->value(gd.c_str(), dirstr, ""); if (dirstr == "") { cerr << "Game '" << game << "' path not found in config. file" << endl; exit(1); } string pd = d + "/patch"; // Look up patch dir. too. string ptchstr; config->value(pd.c_str(), ptchstr, ""); set_game_path(dirstr.c_str(), ptchstr == "" ? 0 : ptchstr.c_str()); } string iedit; // Get image-editor command. config->value("config/estudio/image_editor", iedit, "gimp-remote -n"); image_editor = g_strdup(iedit.c_str()); config->set("config/estudio/image_editor", iedit, true); #ifdef WIN32 OleInitialize(NULL); #endif // Init. 'Mode' menu, since Glade // doesn't seem to do it right. GSList *group = NULL; for (int i = 0; i < sizeof(mode_names)/sizeof(mode_names[0]); i++) { GtkWidget *item = glade_xml_get_widget(app_xml, mode_names[i]); gtk_radio_menu_item_set_group(GTK_RADIO_MENU_ITEM(item), group); group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item)); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), i == 0); } } ExultStudio::~ExultStudio() { #ifdef WIN32 OleUninitialize(); #endif // Store main window size. int w = app->allocation.width, h = app->allocation.height; // Finish up external edits. Shape_chooser::clear_editing_files(); config->set("config/estudio/main/width", w, true); config->set("config/estudio/main/height", h, true); int num_names = names.size(); for (int i = 0; i < num_names; i++) delete names[i]; names.resize(0); g_free(glade_path); delete files; files = 0; delete [] palbuf; palbuf = 0; if (objwin) gtk_widget_destroy(objwin); delete obj_draw; if (eggwin) gtk_widget_destroy(eggwin); delete egg_monster_draw; eggwin = 0; if (npcwin) gtk_widget_destroy(npcwin); delete npc_draw; npcwin = 0; if (shapewin) gtk_widget_destroy(shapewin); delete shape_draw; shapewin = 0; if (equipwin) gtk_widget_destroy(equipwin); equipwin = 0; if (compilewin) gtk_widget_destroy(compilewin); compilewin = 0; delete compile_box; compile_box = 0; if (locwin) delete locwin; if (combowin) delete combowin; locwin = 0; g_object_unref( G_OBJECT( app_xml ) ); #ifndef WIN32 if (server_input_tag >= 0) gdk_input_remove(server_input_tag); if (server_socket >= 0) close(server_socket); #else if (server_input_tag >= 0) gtk_timeout_remove(server_input_tag); if (server_socket >= 0) Exult_server::disconnect_from_server(); #endif g_free(static_path); g_free(image_editor); g_free(default_game); self = 0; delete config; config = 0; } /* * Okay to close game? */ bool ExultStudio::okay_to_close ( ) { if (need_to_save()) { int choice = prompt("File(s) modified. Save?", "Yes", "No", "Cancel"); if (choice == 2) // Cancel? return false; if (choice == 0) save_all(); // Write out changes. } return true; } /* * See if given window has focus (experimental). */ inline bool Window_has_focus(GtkWindow *win) { return (win->focus_widget != 0 && GTK_WIDGET_HAS_FOCUS(win->focus_widget)); } /* * Do we have focus? Currently only checks main window and group * windows. */ bool ExultStudio::has_focus ( ) { if (Window_has_focus(GTK_WINDOW(app))) return true; // Main window. // Group windows: vector::const_iterator it; for (it = group_windows.begin(); it != group_windows.end(); ++it) if (Window_has_focus(*it)) return true; return false; } /* * Set browser area. NOTE: obj may be null. */ void ExultStudio::set_browser(const char *name, Object_browser *obj) { GtkWidget *browser_frame = glade_xml_get_widget(app_xml, "browser_frame" ); GtkWidget *browser_box = glade_xml_get_widget(app_xml, "browser_box" ); //+++Now owned by Shape_file_info. delete browser; if (browser) gtk_container_remove(GTK_CONTAINER(browser_box), browser->get_widget()); browser = obj; gtk_frame_set_label( GTK_FRAME( browser_frame ), name ); gtk_widget_show( browser_box ); if (browser) gtk_box_pack_start(GTK_BOX(browser_box), browser->get_widget(), TRUE, TRUE, 0); } Object_browser *ExultStudio::create_browser(const char *fname) { curfile = open_shape_file(fname); if (!curfile) return 0; Object_browser *chooser = curfile->get_browser(vgafile, palbuf); setup_groups(); // Set up 'groups' page. return chooser; } /* * Get current groups. */ Shape_group_file *ExultStudio::get_cur_groups ( ) { return curfile ? curfile->get_groups() : 0; } /* * Test for a directory 'slash' or colon. */ inline bool Is_dir_marker ( char c ) { return (c == '/' || c == '\\' || c == ':'); } /* * New game directory was chosen. */ void on_choose_new_game_dir ( const char *dir, gpointer udata // ->studio. ) { ((ExultStudio *) udata)->create_new_game(dir); } void ExultStudio::create_new_game ( const char *dir // Directory for new game. ) { // Take basename as game name. const char *eptr = dir + strlen(dir) - 1; while (eptr >= dir && Is_dir_marker(*eptr)) eptr--; eptr++; const char *ptr = eptr - 1; for ( ; ptr >= dir; ptr--) if (Is_dir_marker(*ptr)) { ptr++; break; } if (ptr < dir || eptr - ptr <= 0) { EStudio::Alert("Can't find base game name in '%s'", dir); return; } string gamestr(ptr, eptr - ptr); string dirstr(dir); string static_path = dirstr + "/static"; if (U7exists(static_path)) { string msg("Directory '"); msg += static_path; msg += "' already exists.\n"; msg += "Files within may be overwritten.\n"; msg += "Proceed?"; if (prompt(msg.c_str(), "Yes", "No") != 0) return; } U7mkdir(dir, 0755); // Create "game", "game/static", // "game/patch". U7mkdir(static_path.c_str(), 0755); string patch_path = dirstr + "/patch"; U7mkdir(patch_path.c_str(), 0755); // Set .exult.cfg. string d("config/disk/game/"); string gameconfig = d + gamestr; d = gameconfig + "/path"; config->set(d.c_str(), dirstr, false); d = gameconfig + "/patch"; config->set(d.c_str(), patch_path, false); d = gameconfig + "/editing"; // We are editing. config->set(d.c_str(), "yes", true); string esdir; // Get dir. for new files. config->value("config/disk/data_path", esdir, EXULT_DATADIR); esdir += "/estudio/new"; DIR *dirrd = opendir(esdir.c_str()); if (!dirrd) EStudio::Alert("'%s' for initial data files not found", esdir.c_str()); else { struct dirent *entry; while(entry=readdir(dirrd)) { char *fname = entry->d_name; int flen = strlen(fname); // Ignore case of extension. if(!strcmp(fname, ".") || !strcmp(fname,"..")) continue; string src = esdir + '/' + fname; string dest = static_path + '/' + fname; try { U7copy(src.c_str(), dest.c_str()); } catch (exult_exception& e) { EStudio::Alert(e.what()); } } closedir(dirrd); } set_game_path(dir); // Open as current game. write_shape_info(true); // Create initial .dat files. } /* * Prompt for a 'new game' directory. */ void ExultStudio::new_game() { if (!okay_to_close()) // Okay to close prev. game? return; GtkFileSelection *fsel = Create_file_selection( "Choose new game directory", on_choose_new_game_dir, this); gtk_widget_show(GTK_WIDGET(fsel)); } /* * Choose game directory. */ void ExultStudio::choose_game_path() { if (!okay_to_close()) // Okay to close prev. game? return; size_t bufsize=128; char * cwd(new char[bufsize]); while(!getcwd(cwd,bufsize)) { if(errno==ERANGE) { bufsize+=128; delete [] cwd; cwd=new char[bufsize]; } else { // Ooops. getcwd() has failed delete [] cwd; // Prevent leakage return; } } GtkFileSelection *fsel = Create_file_selection( "Select game directory", (File_sel_okay_fun) on_choose_directory, 0L); gtk_file_selection_set_filename(fsel, cwd); gtk_widget_show(GTK_WIDGET(fsel)); delete [] cwd; // Prevent leakage } /* * Note: Patchpath may be NULL,in which case gamepath/patch is used. */ void ExultStudio::set_game_path(const char *gamepath, const char *patchpath) { // Finish up external edits. Shape_chooser::clear_editing_files(); // Set top-level path. add_system_path("", gamepath); if (static_path) g_free(static_path); // Set up path to static. static_path = g_strdup_printf("%s/static", gamepath); add_system_path("", static_path); char *patch_path = patchpath ? g_strdup(patchpath) : g_strdup_printf("%s/patch", gamepath); add_system_path("", patch_path); if (!U7exists(patch_path)) // Create patch if not there. U7mkdir(patch_path, 0755); g_free(patch_path); // Clear file cache! U7FileManager::get_ptr()->reset(); delete palbuf; // Delete old. string palname("/"); // 1st look in patch for palettes. palname += "palettes.flx"; size_t len; if (!U7exists(palname.c_str())) (palname = "/") += "palettes.flx"; if (!U7exists(palname.c_str())) { // No palette file, so create fake. palbuf = new unsigned char[3*256]; // How about all white? memset(palbuf, (63<<16)|(63<<8)|63, 3*256); } else { U7object pal(palname.c_str(), 0); // this may throw an exception palbuf = (unsigned char *) pal.retrieve(len); } // Set background color. palbuf[3*255] = (background_color>>18)&0x3f; palbuf[3*255 + 1] = (background_color>>10)&0x3f; palbuf[3*255 + 2] = (background_color>>2)&0x3f; // Delete old names. int num_names = names.size(); for (int i = 0; i < num_names; i++) delete names[i]; names.resize(0); delete files; // Close old shape files. browser = 0; // This was owned by 'files'. files = new Shape_file_set(); vgafile = open_shape_file("shapes.vga"); facefile = open_shape_file("faces.vga"); // Read in shape names. string txtname("/text.flx"); if (!U7exists(txtname.c_str())) txtname = "/text.flx"; if (U7exists(txtname.c_str())) { Flex *items = new Flex(txtname.c_str()); int num_names = items->number_of_objects(); names.resize(num_names); int i; for (i = 0; i < num_names; i++) names[i] = items->retrieve(i, len); delete items; } setup_file_list(); // Set up file-list window. set_browser("", 0); // No browser. connect_to_server(); // Connect to server with 'gamedat'. } void add_to_tree(GtkTreeStore *model, const char *folderName, const char *files, ExultFileTypes file_type) { struct dirent *entry; GtkTreeIter iter; // First, we add the folder gtk_tree_store_append(model, &iter, NULL); gtk_tree_store_set(model, &iter, FOLDER_COLUMN, folderName, FILE_COLUMN, NULL, DATA_COLUMN, -1, -1); // Scan the files which are separated by commas GtkTreeIter child_iter; char *startpos = (char *)files; int adding_children = 1; do { char *pattern; char *commapos = strstr(startpos, ","); if(commapos==0) { pattern = strdup(startpos); adding_children = 0; } else { pattern = g_strndup(startpos, commapos-startpos); startpos = commapos+1; } string spath(""), ppath(""); spath = get_system_path(spath); ppath = get_system_path(ppath); char *ext = strstr(pattern,"*"); if(!ext) ext = pattern; else ext++; DIR *dir = opendir(ppath.c_str());// Get names from 'patch' first. if (dir) { while(entry=readdir(dir)) { char *fname = entry->d_name; int flen = strlen(fname); // Ignore case of extension. if(!strcmp(fname,".")||!strcmp(fname,"..") ||strcasecmp(fname + flen - strlen(ext), ext) != 0) continue; gtk_tree_store_append (model, &child_iter, &iter); gtk_tree_store_set (model, &child_iter, FOLDER_COLUMN, NULL, FILE_COLUMN, fname, DATA_COLUMN, file_type, -1); } closedir(dir); } dir = opendir(spath.c_str()); // Now go through 'static'. if (dir) { while(entry=readdir(dir)) { char *fname = entry->d_name; int flen = strlen(fname); // Ignore case of extension. if(!strcmp(fname,".")||!strcmp(fname,"..")||strcasecmp(fname + flen - strlen(ext), ext) != 0) continue; // See if also in 'patch'. string fullpath(ppath); fullpath += "/"; fullpath += fname; if (U7exists(fullpath)) continue; gtk_tree_store_append (model, &child_iter, &iter); gtk_tree_store_set (model, &child_iter, FOLDER_COLUMN, NULL, FILE_COLUMN, fname, DATA_COLUMN, file_type, -1); } closedir(dir); } free(pattern); } while (adding_children); } /* * Set up the file list to the left of the main window. */ void ExultStudio::setup_file_list() { GtkWidget *file_list = glade_xml_get_widget( app_xml, "file_list" ); /* create tree store */ GtkTreeModel *oldmod = gtk_tree_view_get_model( GTK_TREE_VIEW(file_list)); GtkTreeStore *model; if (oldmod) model = GTK_TREE_STORE(oldmod); else // Create the first time. { model = gtk_tree_store_new( NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); gtk_tree_view_set_model(GTK_TREE_VIEW(file_list), GTK_TREE_MODEL(model)); g_object_unref(model); gint col_offset; GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); GtkTreeViewColumn *column; /* column for folder names */ g_object_set (renderer, "xalign", 0.0, NULL); col_offset = gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(file_list), -1, "Folders", renderer, "text", FOLDER_COLUMN, NULL); column = gtk_tree_view_get_column(GTK_TREE_VIEW(file_list), col_offset - 1); gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(column), TRUE); /* column for file names */ col_offset = gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(file_list), -1, "Files", renderer, "text", FILE_COLUMN, NULL); column = gtk_tree_view_get_column(GTK_TREE_VIEW(file_list), col_offset - 1); gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(column), TRUE); } gtk_tree_store_clear(model); add_to_tree(model, "Shape Files", "*.vga,*.shp,combos.flx", ShapeArchive); add_to_tree(model, "Map Files", "u7chunks", ChunkArchive); add_to_tree(model, "Palette Files", "*.pal,palettes.flx", PaletteFile); #if 0 /* Skip this until we can do something with these files. */ add_to_tree(model, "FLEX Files", "*.flx", FlexArchive); #endif // Expand all entries. gtk_tree_view_expand_all(GTK_TREE_VIEW(file_list)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(file_list), TRUE); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(file_list)), GTK_SELECTION_SINGLE); } /* * Save all the files we've changed: * Object browser. * Group files. * Shape files. * Shape info (tfa.dat, weapons.dat, etc.) * Game map. */ void ExultStudio::save_all ( ) { save_groups(); // Group files. if (files) { // Get back any changed images. Shape_chooser::check_editing_files(); files->flush(); // Write out the .vga files. } write_shape_info(); write_map(); } /* * Any files need saving? */ bool ExultStudio::need_to_save ( ) { if (groups_modified()) return true; if (files && files->is_modified()) return true; if (shape_info_modified || shape_names_modified) return true; // Ask Exult about the map. if (Send_data(server_socket, Exult_server::info) != -1) { // Should get immediate answer. unsigned char data[Exult_server::maxlength]; Exult_server::Msg_type id; Exult_server::wait_for_response(server_socket, 100); int len = Exult_server::Receive_data(server_socket, id, data, sizeof(data)); unsigned char *ptr = &data[0]; int vers, edlift, hdlift, edmode; bool editing, grid, mod; if (id == Exult_server::info && Game_info_in(data, len, vers, edlift, hdlift, editing, grid, mod, edmode) && mod == true) return true; } return false; } /* * Write out map. */ void ExultStudio::write_map ( ) { send_to_server(Exult_server::write_map); } /* * Read in map. */ void ExultStudio::read_map ( ) { send_to_server(Exult_server::read_map); } /* * Write out shape info. and text. */ void ExultStudio::write_shape_info ( bool force // If set, always write. ) { if ((force || shape_info_modified) && vgafile) { Shapes_vga_file *svga = (Shapes_vga_file *) vgafile->get_ifile(); // Make sure data's been read in. svga->read_info(false, true);//+++++BG? svga->write_info(false);//++++BG? } shape_info_modified = false; if (force || shape_names_modified) { shape_names_modified = false; int cnt = names.size(); std::ofstream out; U7open(out, "/text.flx"); Flex_writer writer(out, "Text created by ExultStudio", cnt); for (int i = 0; i < cnt; i++) { char *str = names[i]; if (str) out << str; out.put((char) 0); // 0-delimit. writer.mark_section_done(); } if (!writer.close()) EStudio::Alert("Error writing 'text.flx'"); } } /* * Reload usecode. */ void ExultStudio::reload_usecode ( ) { send_to_server(Exult_server::reload_usecode); } /* * Tell Exult to start/stop playing. */ void ExultStudio::set_play ( gboolean play // True to play, false to edit. ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, play ? 0 : 1); // Map_edit = !play. send_to_server(Exult_server::map_editing_mode, data, ptr - data); } /* * Tell Exult to show or not show the tile grid. */ void ExultStudio::set_tile_grid ( gboolean grid // True to show. ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, grid ? 1 : 0); // Map_edit = !play. send_to_server(Exult_server::tile_grid, data, ptr - data); } /* * Tell Exult to edit at a given lift. */ void ExultStudio::set_edit_lift ( int lift ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, lift); send_to_server(Exult_server::edit_lift, data, ptr - data); } /* * Tell Exult to hide objects at or above a given lift. */ void ExultStudio::set_hide_lift ( int lift ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, lift); send_to_server(Exult_server::hide_lift, data, ptr - data); } /* * Tell Exult to enter/leave 'terrain-edit' mode. */ void ExultStudio::set_edit_terrain ( gboolean terrain // True/false ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, terrain ? 1 : 0); // NOTE: Pass -1 to abort. But I // haven't got an interface yet. send_to_server(Exult_server::terrain_editing_mode, data, ptr - data); if (!terrain) { // Turning it off. if (browser) browser->end_terrain_editing(); // FOR NOW, skip_lift is reset. set_spin("hide_lift_spin", 16, true); } else // Disable "Hide lift". set_sensitive("hide_lift_spin", false); // Set edit-mode to paint. GtkWidget *mitem = glade_xml_get_widget(app_xml, terrain ? "paint1" : "move1"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE); } void ExultStudio::set_edit_mode ( int md // 0-2 (drag, paint, pick. ) { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, md); // haven't got an interface yet. send_to_server(Exult_server::set_edit_mode, data, ptr - data); } /* * Insert 0-delimited text into an edit box. */ static void Insert_text ( GtkEditable *ed, const char *text, int& pos // Where to insert. Updated. ) { gtk_editable_insert_text(ed, text, strlen(text), &pos); } /* * Show unused shape list received from exult. */ void ExultStudio::show_unused_shapes ( unsigned char *data, // Bits set for unused shapes. int datalen // #bytes. ) { int nshapes = datalen*8; GtkTextView *text = GTK_TEXT_VIEW(glade_xml_get_widget(app_xml, "msg_text")); GtkTextBuffer *buffer = gtk_text_view_get_buffer(text); gtk_text_buffer_set_text(buffer, "", 0); // Clear out old text set_visible("msg_win", TRUE); // Show message window. int pos = 0; GtkEditable *ed = GTK_EDITABLE(text); Insert_text(ed, "The following shapes were not found.\n", pos); Insert_text(ed, "Note that some may be created by usecode (script)\n\n", pos); for (int i = 0x96; i < nshapes; i++) // Ignore flats (<0x96). if (!(data[i/8]&(1<<(i%8)))) { const char *nm = get_shape_name(i); char *msg = g_strdup_printf(" Shape %4d: %s\n", i, nm ? nm : ""); Insert_text(ed, msg, pos); g_free(msg); } // FIXME: gtk_text_set_point(text, 0); // Scroll back to top. } /* * Open a shape (or chunks) file in 'patch' or 'static' directory. * * Output: ->file info (may already have existed), or 0 if error. */ Shape_file_info *ExultStudio::open_shape_file ( const char *basename // Base name of file to open. ) { Shape_file_info *info = files->create(basename); if (!info) EStudio::Alert("'%s' not found in static or patch directories", basename); return info; } /* * Prompt for a new shape file name. */ void ExultStudio::new_shape_file ( bool single // Not a FLEX file. ) { GtkFileSelection *fsel = Create_file_selection( single ? "Write new .shp file" : "Write new .vga file", (File_sel_okay_fun) create_shape_file, (gpointer) single); // This doesn't work very well in GTK 1.2. Try again later. // gtk_file_selection_complete(fsel, single ? "*.shp" : "*.vga"); if (is_system_path_defined("")) { // Default to 'patch'. string patch = get_system_path("/"); gtk_file_selection_set_filename(fsel, patch.c_str()); } gtk_widget_show(GTK_WIDGET(fsel)); } /* * Create a new shape/shapes file. */ void ExultStudio::create_shape_file ( char *pathname, // Full path. gpointer udata // 1 if NOT a FLEX file. ) { bool oneshape = (bool) udata; Shape *shape = 0; if (oneshape) // Single-shape? { // Create one here. const int w = 8, h = 8; unsigned char pixels[w*h]; // Create an 8x8 shape. memset(&pixels[0], 1, w*h); // Just use color #1. shape = new Shape(new Shape_frame(&pixels[0], w, h, w - 1, h - 1, true)); } try { // Write file. if (oneshape) Image_file_info::write_file(pathname, &shape, 1, true); else Image_file_info::write_file(pathname, 0, 0, false); } catch (const exult_exception& e) { EStudio::Alert(e.what()); } ExultStudio *studio = ExultStudio::get_instance(); studio->setup_file_list(); // Rescan list of shape files. } /* * Get value of a toggle button (false if not found). */ bool ExultStudio::get_toggle ( char *name ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); return btn ? gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)) : -1; } /* * Find and set a toggle/checkbox button. */ void ExultStudio::set_toggle ( char *name, bool val ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); if (btn) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(btn), val); } /* * Get an 8-bit set of flags from a group of toggles. */ unsigned char ExultStudio::get_bit_toggles ( char **names, // Names for bit 0, 1, 2,... int num // # of names/bits. ) { unsigned char bits = 0; for (int i = 0; i < num; i++) bits |= (get_toggle(names[i]) ? 1 : 0) << i; return bits; } /* * Set a group of toggles based on a sequential (0, 1, 2...) set of bit * flags. */ void ExultStudio::set_bit_toggles ( char **names, // Names for bit 0, 1, 2,... int num, // # of names/bits. unsigned char bits ) { for (int i = 0; i < num; i++) set_toggle(names[i], (bits&(1<children, active); } /* * Find and set an option-menu button. */ void ExultStudio::set_optmenu ( char *name, int val ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); if (btn) gtk_option_menu_set_history(GTK_OPTION_MENU(btn), val); } /* * Get value of spin button (-1 if unsuccessful). */ int ExultStudio::get_spin ( char *name ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); return btn ? gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(btn)) : -1; } /* * Find and set a spin button. */ void ExultStudio::set_spin ( char *name, int val, bool sensitive ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); if (btn) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(btn), val); gtk_widget_set_sensitive(btn, sensitive); } } /* * Find and set a spin button, along with its range. */ void ExultStudio::set_spin ( char *name, int val, int low, int high // Range. ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); if (btn) { gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(btn), GTK_ADJUSTMENT( gtk_adjustment_new (0, low, high, 1, 10, 10))); gtk_spin_button_set_value(GTK_SPIN_BUTTON(btn), val); } } /* * Get number from a text field. * * Output: Number, or -1 if not found. */ int ExultStudio::get_num_entry ( char *name ) { GtkWidget *field = glade_xml_get_widget(app_xml, name); if (!field) return -1; const gchar *txt = gtk_entry_get_text(GTK_ENTRY(field)); if (!txt) return -1; while (*txt == ' ') txt++; // Skip space. if (txt[0] == '0' && txt[1] == 'x') return (int) strtoul(txt + 2, 0, 16); // Hex. else return atoi(txt); } /* * Get text from a text field. * * Output: ->text, or null if not found. */ const gchar *ExultStudio::get_text_entry ( char *name ) { GtkWidget *field = glade_xml_get_widget(app_xml, name); if (!field) return 0; return gtk_entry_get_text(GTK_ENTRY(field)); } /* * Find and set a text field to a number. */ void ExultStudio::set_entry ( char *name, int val, bool hex, bool sensitive ) { GtkWidget *field = glade_xml_get_widget(app_xml, name); if (field) { char *txt = hex ? g_strdup_printf("0x%x", val) : g_strdup_printf("%d", val); gtk_entry_set_text(GTK_ENTRY(field), txt); g_free(txt); gtk_widget_set_sensitive(field, sensitive); } } /* * Set text field. */ void ExultStudio::set_entry ( char *name, const char *val, bool sensitive ) { GtkWidget *field = glade_xml_get_widget(app_xml, name); if (field) { gtk_entry_set_text(GTK_ENTRY(field), val); gtk_widget_set_sensitive(field, sensitive); } } /* * Set statusbar. * Output: Msg. ID, or 0. */ guint ExultStudio::set_statusbar ( char *name, int context, char *msg ) { GtkWidget *sbar = glade_xml_get_widget(app_xml, name); if (sbar) return gtk_statusbar_push(GTK_STATUSBAR(sbar), context, msg); else return 0; } /* * Pop last message that was set. */ void ExultStudio::remove_statusbar ( char *name, int context, guint msgid ) { if (msgid == 0) return; GtkWidget *sbar = glade_xml_get_widget(app_xml, name); if (sbar) return gtk_statusbar_remove(GTK_STATUSBAR(sbar),context,msgid); } /* * Set a button's text. */ void ExultStudio::set_button ( char *name, const char *text ) { GtkWidget *btn = glade_xml_get_widget(app_xml, name); GtkLabel *label = GTK_LABEL(GTK_BIN(btn)->child); gtk_label_set_text(label, text); } /* * Show/hide a widget. */ void ExultStudio::set_visible ( char *name, bool vis ) { GtkWidget *widg = glade_xml_get_widget(app_xml, name); if (widg) { if (vis) gtk_widget_show(widg); else gtk_widget_hide(widg); } } /* * Enable/disable a widget. */ void ExultStudio::set_sensitive ( char *name, bool tf ) { GtkWidget *widg = glade_xml_get_widget(app_xml, name); if (widg) gtk_widget_set_sensitive(widg, tf); } /* * Handle 'prompt' dialogs: */ static int prompt_choice = 0; // Gets prompt choice. C_EXPORT void on_prompt3_yes_clicked (GtkToggleButton *button, gpointer user_data) { prompt_choice = 0; } C_EXPORT void on_prompt3_no_clicked (GtkToggleButton *button, gpointer user_data) { prompt_choice = 1; } C_EXPORT void on_prompt3_cancel_clicked (GtkToggleButton *button, gpointer user_data) { prompt_choice = 2; } /* * Prompt for one of two/three answers. * * Output: 0 for 1st choice, 1 for 2nd, 2 for 3rd. */ int ExultStudio::prompt ( const char *msg, // Question to ask. const char *choice0, // 1st choice. const char *choice1, // 2nd choice, or NULL. const char *choice2 // 3rd choice, or NULL. ) { static GdkPixmap *logo_pixmap = NULL; static GdkBitmap *logo_mask = NULL; if (!logo_pixmap) // First time? { logo_pixmap = gdk_pixmap_create_from_xpm_d(app->window, &logo_mask, NULL, logo_xpm); GtkWidget *pix = gtk_pixmap_new(logo_pixmap, logo_mask); gtk_widget_show(pix); GtkWidget *hbox = glade_xml_get_widget(app_xml, "prompt3_hbox"); gtk_box_pack_start(GTK_BOX(hbox), pix, FALSE, FALSE, 12); // Make logo show to left. gtk_box_reorder_child(GTK_BOX(hbox), pix, 0); } GtkWidget *dlg = glade_xml_get_widget(app_xml, "prompt3_dialog"); gtk_label_set_text( GTK_LABEL(glade_xml_get_widget(app_xml, "prompt3_label")), msg); set_button("prompt3_yes", choice0); if (choice1) { set_button("prompt3_no", choice1); set_visible("prompt3_no", true); } else set_visible("prompt3_no", false); if (choice2) // 3rd choice? Show btn if so. { set_button("prompt3_cancel", choice2); set_visible("prompt3_cancel", true); } else set_visible("prompt3_cancel", false); prompt_choice = -1; gtk_window_set_modal(GTK_WINDOW(dlg), true); gtk_widget_show(dlg); // Should be modal. while (prompt_choice == -1) // Spin. gtk_main_iteration(); // (Blocks). gtk_widget_hide(dlg); assert(prompt_choice >= 0 && prompt_choice <= 2); return prompt_choice; } namespace EStudio { /* * Same as ExultStudio::prompt, but as a routine. */ int Prompt ( const char *msg, // Question to ask. const char *choice0, // 1st choice. const char *choice1, // 2nd choice, or NULL. const char *choice2 // 3rd choice, or NULL. ) { return ExultStudio::get_instance()->prompt(msg, choice0, choice1, choice2); } /* * Just print a message (usually an error). */ void Alert ( const char *msg, // May be in printf format. ... ) { std::va_list args; va_start(args, msg); char *fullmsg = g_strdup_vprintf(msg, args); Prompt(fullmsg, "Okay"); g_free(fullmsg); } /* * Add a menu item to a menu. * * Output: Menu item. */ GtkWidget *Add_menu_item ( GtkWidget *menu, // Menu to add to. const char *label, // What to put. NULL for separator. GtkSignalFunc func, // Handle menu choice. gpointer func_data // Data passed to func(). ) { GtkWidget *mitem = label ? gtk_menu_item_new_with_label(label) : gtk_menu_item_new(); gtk_widget_show(mitem); gtk_menu_append(GTK_MENU(menu), mitem); if (!label) // Want separator? gtk_widget_set_sensitive(mitem, FALSE); if (func) // Function? gtk_signal_connect(GTK_OBJECT(mitem), "activate", GTK_SIGNAL_FUNC(func), func_data); return mitem; } /* * Create an arrow button. */ GtkWidget *Create_arrow_button ( GtkArrowType dir, // Direction. GtkSignalFunc clicked, // Call this when clicked. gpointer func_data // Passed to 'clicked'. ) { GtkWidget *btn = gtk_button_new(); gtk_widget_show(btn); GTK_WIDGET_SET_FLAGS(btn, GTK_CAN_DEFAULT); GtkWidget *arrow = gtk_arrow_new(dir, GTK_SHADOW_OUT); gtk_widget_show(arrow); gtk_container_add(GTK_CONTAINER(btn), arrow); gtk_signal_connect(GTK_OBJECT(btn), "clicked", clicked, func_data); return btn; } } // namespace EStudio /* * 'Preferences' window events. */ C_EXPORT void on_prefs_cancel_clicked (GtkButton *button, gpointer user_data) { gtk_widget_hide(gtk_widget_get_toplevel(GTK_WIDGET(button))); } C_EXPORT void on_prefs_apply_clicked (GtkButton *button, gpointer user_data) { ExultStudio::get_instance()->save_preferences(); } C_EXPORT void on_prefs_okay_clicked (GtkButton *button, gpointer user_data) { ExultStudio::get_instance()->save_preferences(); gtk_widget_hide(gtk_widget_get_toplevel(GTK_WIDGET(button))); } /* * 'Okay' was hit in the color selector. */ void ExultStudio::background_color_okay ( GtkWidget *dlg, gpointer data ) { GtkColorSelectionDialog *colorsel = GTK_COLOR_SELECTION_DIALOG(dlg); gdouble rgb[3]; gtk_color_selection_get_color( GTK_COLOR_SELECTION(colorsel->colorsel), rgb); unsigned char r = (unsigned char) (rgb[0]*256), g = (unsigned char) (rgb[1]*256), b = (unsigned char) (rgb[2]*256); ExultStudio *studio = ExultStudio::get_instance(); studio->background_color = (r<<16) + (g<<8) + b; // Show new color. GtkWidget *backgrnd = glade_xml_get_widget(studio->app_xml, "prefs_background"); gtk_object_set_user_data(GTK_OBJECT(backgrnd), (gpointer) studio->background_color); GdkRectangle area = {0, 0, backgrnd->allocation.width, backgrnd->allocation.height}; gtk_widget_draw(backgrnd, &area); gtk_widget_destroy(dlg); } C_EXPORT void on_prefs_background_choose_clicked (GtkButton *button, gpointer user_data) { GtkColorSelectionDialog *colorsel = GTK_COLOR_SELECTION_DIALOG( gtk_color_selection_dialog_new("Background color")); gtk_window_set_modal(GTK_WINDOW(colorsel), true); // Set mouse click handler. gtk_signal_connect_object(GTK_OBJECT(colorsel->ok_button), "clicked", GTK_SIGNAL_FUNC(ExultStudio::background_color_okay), GTK_OBJECT(colorsel)); gtk_signal_connect_object(GTK_OBJECT(colorsel->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(colorsel)); // Set delete handler. gtk_signal_connect(GTK_OBJECT(colorsel), "delete_event", GTK_SIGNAL_FUNC(gtk_false), 0L); // Get color. guint32 c = ExultStudio::get_instance()->get_background_color(); gdouble rgb[3]; rgb[0] = ((double) ((c>>16)&0xff))/256; rgb[1] = ((double) ((c>>8)&0xff))/256; rgb[2] = ((double) ((c>>0)&0xff))/256; gtk_color_selection_set_color(GTK_COLOR_SELECTION(colorsel->colorsel), rgb); gtk_widget_show(GTK_WIDGET(colorsel)); } // Background color area exposed. C_EXPORT gboolean on_prefs_background_expose_event ( GtkWidget *widget, // The draw area. GdkEventExpose *event, gpointer data ) { guint32 color = (guint32) gtk_object_get_user_data(GTK_OBJECT(widget)); GdkGC *gc = (GdkGC *) gtk_object_get_data(GTK_OBJECT(widget), "color_gc"); if (!gc) { gc = gdk_gc_new(widget->window); gtk_object_set_data(GTK_OBJECT(widget), "color_gc", gc); } gdk_rgb_gc_set_foreground(gc, color); gdk_draw_rectangle(widget->window, gc, TRUE, event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } // X at top of window. C_EXPORT gboolean on_prefs_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { gtk_widget_hide(widget); return TRUE; } /* * Open preferences window. */ void ExultStudio::open_preferences ( ) { set_entry("prefs_image_editor", image_editor ? image_editor : ""); set_entry("prefs_default_game", default_game ? default_game : ""); GtkWidget *backgrnd = glade_xml_get_widget(app_xml, "prefs_background"); gtk_object_set_user_data(GTK_OBJECT(backgrnd), (gpointer) background_color); GtkWidget *win = glade_xml_get_widget(app_xml, "prefs_window"); gtk_widget_show(win); } /* * Save preferences. */ void ExultStudio::save_preferences ( ) { const char *text = get_text_entry("prefs_image_editor"); g_free(image_editor); image_editor = g_strdup(text); config->set("config/estudio/image_editor", image_editor, true); text = get_text_entry("prefs_default_game"); g_free(default_game); default_game = g_strdup(text); config->set("config/estudio/default_game", default_game, true); GtkWidget *backgrnd = glade_xml_get_widget(app_xml, "prefs_background"); background_color = (guint32) gtk_object_get_user_data( GTK_OBJECT(backgrnd)); config->set("config/estudio/background_color", background_color, true); // Set background color. palbuf[3*255] = (background_color>>18)&0x3f; palbuf[3*255 + 1] = (background_color>>10)&0x3f; palbuf[3*255 + 2] = (background_color>>2)&0x3f; if (browser) // Repaint browser. browser->set_background_color(background_color); } /* * Main routine. */ void ExultStudio::run() { gtk_main(); } /* * This is called every few seconds to try to reconnect to Exult. */ static gint Reconnect ( gpointer data // ->ExultStudio. ) { ExultStudio *studio = (ExultStudio *) data; if (studio->connect_to_server()) return 0; // Cancel timer. We succeeded. else return 1; } /* * Send message to server. * * Output: false if error sending (reported). */ bool ExultStudio::send_to_server ( Exult_server::Msg_type id, unsigned char *data, int datalen ) { if (Send_data(server_socket, id, data, datalen) == -1) { cerr << "Error sending to server" << endl; return false; } return true; } /* * Input from server is available. */ #ifndef WIN32 static void Read_from_server ( gpointer data, // ->ExultStudio. gint socket, GdkInputCondition condition ) { ExultStudio *studio = (ExultStudio *) data; studio->read_from_server(); } #else static gint Read_from_server ( gpointer data // ->ExultStudio. ) { ExultStudio *studio = (ExultStudio *) data; studio->read_from_server(); return TRUE; } #endif gint Do_Drop_Callback(gpointer data); void ExultStudio::read_from_server ( ) { #ifdef WIN32 // Nothing int len = Exult_server::peek_pipe(); //Do_Drop_Callback(&len); if (len == -1) { cout << "Disconnected from server" << endl; gtk_timeout_remove(server_input_tag); Exult_server::disconnect_from_server(); server_input_tag = -1; server_socket = -1; // Try again every 4 secs. gtk_timeout_add(4000, Reconnect, this); return; } if (len < 1) return; #endif unsigned char data[Exult_server::maxlength]; Exult_server::Msg_type id; int datalen = Exult_server::Receive_data(server_socket, id, data, sizeof(data)); if (datalen < 0) { cout << "Error reading from server" << endl; if (server_socket == -1)// Socket closed? { #ifndef WIN32 gdk_input_remove(server_input_tag); #else gtk_timeout_remove(server_input_tag); Exult_server::disconnect_from_server(); #endif server_input_tag = -1; // Try again every 4 secs. gtk_timeout_add(4000, Reconnect, this); } return; } cout << "Read " << datalen << " bytes from server" << endl; cout << "ID = " << (int) id << endl; switch (id) { case Exult_server::obj: open_obj_window(data, datalen); break; case Exult_server::egg: open_egg_window(data, datalen); break; case Exult_server::npc: open_npc_window(data, datalen); break; case Exult_server::user_responded: case Exult_server::cancel: case Exult_server::locate_terrain: case Exult_server::swap_terrain: case Exult_server::insert_terrain: case Exult_server::delete_terrain: case Exult_server::locate_shape: case Exult_server::game_pos: if (waiting_for_server) // Send msg. to callback. { waiting_for_server(id, data, datalen, waiting_client); waiting_for_server = 0; waiting_client = 0; } else if (browser) browser->server_response((int) id, data, datalen); break; case Exult_server::info: info_received(data, datalen); break; case Exult_server::view_pos: if (locwin) locwin->view_changed(data, datalen); break; case Exult_server::combo_pick: open_combo_window(); // Open if necessary. if (combowin) combowin->add(data, datalen); break; case Exult_server::unused_shapes: show_unused_shapes(data, datalen); break; case Exult_server::select_status: set_edit_menu(data[0] != 0, data[1] != 0); break; case Exult_server::usecode_debugging: std::cerr << "Warning: got a usecode debugging message! (ignored)" << std::endl; break; } } /* * Try to connect to the Exult game. * * Output: True if succeeded. */ bool ExultStudio::connect_to_server ( ) { if (!static_path) return false; // No place to go. #ifndef WIN32 if (server_socket >= 0) // Close existing socket. { close(server_socket); gdk_input_remove(server_input_tag); } server_socket = server_input_tag = -1; struct sockaddr_un addr; addr.sun_family = AF_UNIX; char *home = getenv("HOME"); addr.sun_path[0] = 0; if (home) // Use $HOME/.exult/exultserver { // if possible. strcpy(addr.sun_path, home); strcat(addr.sun_path, "/.exult/exultserver"); if (!U7exists(addr.sun_path)) addr.sun_path[0] = 0; } if (!addr.sun_path[0]) // Default to game/gamedat. { strcpy(addr.sun_path, static_path); char *pstatic = strrchr(addr.sun_path, '/'); if (pstatic && !pstatic[1]) // End of path? { pstatic[0] = 0; pstatic = strrchr(addr.sun_path, '/'); } if (!pstatic) { cout << "Can't find gamedat for socket" << endl; return false; } strcpy(pstatic + 1, "gamedat/exultserver"); } server_socket = socket(PF_LOCAL, SOCK_STREAM, 0); if (server_socket < 0) { perror("Failed to open map-editor socket"); return false; } // Set to be non-blocking. // fcntl(server_socket, F_SETFL, // fcntl(server_socket, F_GETFL) | O_NONBLOCK); cout << "Trying to connect to server at '" << addr.sun_path << "'" << endl; if (connect(server_socket, (struct sockaddr *) &addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) == -1) { perror("Socket connect"); close(server_socket); server_socket = -1; return false; } server_input_tag = gdk_input_add(server_socket, GDK_INPUT_READ, Read_from_server, this); #else // Close existing socket. if (server_socket != -1) Exult_server::disconnect_from_server(); if (server_input_tag != -1) gtk_timeout_remove(server_input_tag); server_socket = server_input_tag = -1; if (Exult_server::try_connect_to_server(static_path) > 0) server_input_tag = gtk_timeout_add(50, Read_from_server, this); else return false; #endif cout << "Connected to server" << endl; send_to_server(Exult_server::info); // Request version, etc. set_edit_menu(false, false); // For now, init. edit menu. return true; } /* * 'Info' message received. */ void ExultStudio::info_received ( unsigned char *data, // Message from Exult. int len ) { int vers, edlift, hdlift, edmode; bool editing, grid, mod; Game_info_in(data, len, vers, edlift, hdlift, editing, grid, mod, edmode); if (vers != Exult_server::version) { // Wrong version of Exult. EStudio::Alert("Expected ExultServer version %d, but got %d", Exult_server::version, vers); #ifndef WIN32 close(server_socket); gdk_input_remove(server_input_tag); #else Exult_server::disconnect_from_server(); gtk_timeout_remove(server_input_tag); #endif server_socket = server_input_tag = -1; return; } // Set controls to what Exult thinks. set_spin("edit_lift_spin", edlift); set_spin("hide_lift_spin", hdlift); set_toggle("play_button", !editing); set_toggle("tile_grid_button", grid); if (edmode >= 0 && edmode < sizeof(mode_names)/sizeof(mode_names[0])) { GtkWidget *mitem = glade_xml_get_widget(app_xml, mode_names[edmode]); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE); } } /* * Set edit menu entries depending on whether there's a selection or * clipboard available. */ void ExultStudio::set_edit_menu ( bool sel, // Selection available. bool clip // Clipboard isn't empty. ) { set_sensitive("cut1", sel); set_sensitive("copy1", sel); set_sensitive("paste1", clip); set_sensitive("properties1", sel); set_sensitive("basic_properties1", sel); } exult-1.2/mapedit/Makefile.am0000644000175000001440000000323310054030562011645 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../shapes \ -I$(srcdir)/../imagewin -I$(srcdir)/../conf \ -I$(srcdir)/../files -I$(srcdir)/../server \ $(GLADE_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" if GIMP_PLUGIN GIMP_PLUGINS=u7shp else GIMP_PLUGINS= endif if BUILD_STUDIO bin_PROGRAMS = exult_studio else bin_PROGRAMS = endif u7shp_SOURCES = u7shp.c exult_studio_SOURCES = \ chunklst.cc \ chunklst.h \ combo.cc \ combo.h \ compile.cc \ eggedit.cc \ execbox.h \ execbox.cc \ locator.cc \ locator.h \ npcedit.cc \ objedit.cc \ shapeedit.cc \ studio.cc \ studio.h \ exult_studio.cc \ objbrowse.h \ objbrowse.cc \ paledit.cc \ paledit.h \ shapedraw.cc \ shapedraw.h \ shapefile.cc \ shapefile.h \ shapegroup.cc \ shapegroup.h \ shapelst.cc \ shapelst.h noinst_PROGRAMS = $(GIMP_PLUGINS) exult_studio_LDADD = \ ../conf/libconf.la \ ../files/libu7file.la \ ../imagewin/libimagewin.la \ ../shapes/libshapes.la \ ../server/libserver.la \ -lpng $(FREETYPE2_LIBS) $(SYSLIBS) $(x_libraries) $(GLADE_LIBS) exult_studio_CFLAGS = $(LIBGLADE_INCLUDES) exult_studio_LDFLAGS = -export-dynamic # For libglade 2.x mapeditdir = $(datadir)/exult if BUILD_STUDIO mapedit_DATA = exult_studio.glade else mapedit_DATA = endif u7shp$(EXEEXT): u7shp.c $(top_builddir)/config.h CFLAGS="-I$(top_srcdir) -DHAVE_CONFIG_H" $(GIMPTOOL) --build $< EXTRA_DIST= \ exult_studio.glade \ logo.xpm if GIMP_PLUGIN install-exec-local: install -d $(DESTDIR)$(GIMP_PLUGIN_PREFIX) install -c $(DESTDIR)$(GIMP_PLUGINS) $(GIMP_PLUGIN_PREFIX) else install-exec-local: endif CLEANFILES = *~ u7shp exult-1.2/mapedit/Makefile.in0000644000175000001440000004023110061527067011666 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../shapes \ -I$(srcdir)/../imagewin -I$(srcdir)/../conf \ -I$(srcdir)/../files -I$(srcdir)/../server \ $(GLADE_INCLUDES) $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" @GIMP_PLUGIN_TRUE@GIMP_PLUGINS = u7shp @GIMP_PLUGIN_FALSE@GIMP_PLUGINS = @BUILD_STUDIO_TRUE@bin_PROGRAMS = exult_studio @BUILD_STUDIO_FALSE@bin_PROGRAMS = u7shp_SOURCES = u7shp.c exult_studio_SOURCES = \ chunklst.cc \ chunklst.h \ combo.cc \ combo.h \ compile.cc \ eggedit.cc \ execbox.h \ execbox.cc \ locator.cc \ locator.h \ npcedit.cc \ objedit.cc \ shapeedit.cc \ studio.cc \ studio.h \ exult_studio.cc \ objbrowse.h \ objbrowse.cc \ paledit.cc \ paledit.h \ shapedraw.cc \ shapedraw.h \ shapefile.cc \ shapefile.h \ shapegroup.cc \ shapegroup.h \ shapelst.cc \ shapelst.h noinst_PROGRAMS = $(GIMP_PLUGINS) exult_studio_LDADD = \ ../conf/libconf.la \ ../files/libu7file.la \ ../imagewin/libimagewin.la \ ../shapes/libshapes.la \ ../server/libserver.la \ -lpng $(FREETYPE2_LIBS) $(SYSLIBS) $(x_libraries) $(GLADE_LIBS) exult_studio_CFLAGS = $(LIBGLADE_INCLUDES) exult_studio_LDFLAGS = -export-dynamic # For libglade 2.x mapeditdir = $(datadir)/exult @BUILD_STUDIO_TRUE@mapedit_DATA = exult_studio.glade @BUILD_STUDIO_FALSE@mapedit_DATA = EXTRA_DIST = \ exult_studio.glade \ logo.xpm CLEANFILES = *~ u7shp subdir = mapedit mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @BUILD_STUDIO_TRUE@bin_PROGRAMS = exult_studio$(EXEEXT) @BUILD_STUDIO_FALSE@bin_PROGRAMS = @GIMP_PLUGIN_TRUE@noinst_PROGRAMS = u7shp$(EXEEXT) @GIMP_PLUGIN_FALSE@noinst_PROGRAMS = PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_exult_studio_OBJECTS = chunklst.$(OBJEXT) combo.$(OBJEXT) \ compile.$(OBJEXT) eggedit.$(OBJEXT) execbox.$(OBJEXT) \ locator.$(OBJEXT) npcedit.$(OBJEXT) objedit.$(OBJEXT) \ shapeedit.$(OBJEXT) studio.$(OBJEXT) exult_studio.$(OBJEXT) \ objbrowse.$(OBJEXT) paledit.$(OBJEXT) shapedraw.$(OBJEXT) \ shapefile.$(OBJEXT) shapegroup.$(OBJEXT) shapelst.$(OBJEXT) exult_studio_OBJECTS = $(am_exult_studio_OBJECTS) exult_studio_DEPENDENCIES = ../conf/libconf.la ../files/libu7file.la \ ../imagewin/libimagewin.la ../shapes/libshapes.la \ ../server/libserver.la am_u7shp_OBJECTS = u7shp.$(OBJEXT) u7shp_OBJECTS = $(am_u7shp_OBJECTS) u7shp_LDADD = $(LDADD) u7shp_DEPENDENCIES = u7shp_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/chunklst.Po $(DEPDIR)/combo.Po \ @AMDEP_TRUE@ $(DEPDIR)/compile.Po $(DEPDIR)/eggedit.Po \ @AMDEP_TRUE@ $(DEPDIR)/execbox.Po $(DEPDIR)/exult_studio.Po \ @AMDEP_TRUE@ $(DEPDIR)/locator.Po $(DEPDIR)/npcedit.Po \ @AMDEP_TRUE@ $(DEPDIR)/objbrowse.Po $(DEPDIR)/objedit.Po \ @AMDEP_TRUE@ $(DEPDIR)/paledit.Po $(DEPDIR)/shapedraw.Po \ @AMDEP_TRUE@ $(DEPDIR)/shapeedit.Po $(DEPDIR)/shapefile.Po \ @AMDEP_TRUE@ $(DEPDIR)/shapegroup.Po $(DEPDIR)/shapelst.Po \ @AMDEP_TRUE@ $(DEPDIR)/studio.Po $(DEPDIR)/u7shp.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ DIST_SOURCES = $(exult_studio_SOURCES) $(u7shp_SOURCES) DATA = $(mapedit_DATA) DIST_COMMON = Makefile.am Makefile.in TODO SOURCES = $(exult_studio_SOURCES) $(u7shp_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu mapedit/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) exult_studio$(EXEEXT): $(exult_studio_OBJECTS) $(exult_studio_DEPENDENCIES) @rm -f exult_studio$(EXEEXT) $(CXXLINK) $(exult_studio_LDFLAGS) $(exult_studio_OBJECTS) $(exult_studio_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/chunklst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/combo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/compile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/eggedit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/execbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/exult_studio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/locator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/npcedit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objbrowse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objedit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/paledit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapedraw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapeedit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapefile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapegroup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapelst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/studio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/u7shp.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .c.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$< .c.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(COMPILE) -c `cygpath -w $<` .c.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CCDEPMODE = @CCDEPMODE@ .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: install-mapeditDATA: $(mapedit_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(mapeditdir) @list='$(mapedit_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(mapeditdir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(mapeditdir)/$$f; \ done uninstall-mapeditDATA: @$(NORMAL_UNINSTALL) @list='$(mapedit_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(mapeditdir)/$$f"; \ rm -f $(DESTDIR)$(mapeditdir)/$$f; \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mapeditdir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-mapeditDATA install-exec-am: install-binPROGRAMS install-exec-local install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ uninstall-mapeditDATA .PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-noinstPROGRAMS distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-binPROGRAMS install-data \ install-data-am install-exec install-exec-am install-exec-local \ install-info install-info-am install-man install-mapeditDATA \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-info-am uninstall-mapeditDATA u7shp$(EXEEXT): u7shp.c $(top_builddir)/config.h CFLAGS="-I$(top_srcdir) -DHAVE_CONFIG_H" $(GIMPTOOL) --build $< @GIMP_PLUGIN_TRUE@install-exec-local: @GIMP_PLUGIN_TRUE@ install -d $(DESTDIR)$(GIMP_PLUGIN_PREFIX) @GIMP_PLUGIN_TRUE@ install -c $(DESTDIR)$(GIMP_PLUGINS) $(GIMP_PLUGIN_PREFIX) @GIMP_PLUGIN_FALSE@install-exec-local: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/mapedit/locator.cc0000644000175000001440000003232407712727750011611 /** ** Locator.cc - Locate game positions. ** ** Written: March 2, 2002 - JSF **/ /* Copyright (C) 2001-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "studio.h" #include "servemsg.h" #include "exult_constants.h" #include "locator.h" #include "utils.h" using std::cout; using std::endl; /* * Open locator window. */ C_EXPORT void on_locator1_activate ( GtkMenuItem *menuitem, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); studio->open_locator_window(); } void ExultStudio::open_locator_window ( ) { if (!locwin) // First time? { locwin = new Locator(); } locwin->show(true); } /* * Locator window's close button. */ C_EXPORT void on_loc_close_clicked ( GtkButton *btn, gpointer user_data ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(btn)))); loc->show(false); } /* * Locator window's X button. */ C_EXPORT gboolean on_loc_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { Locator *loc = (Locator *) gtk_object_get_user_data(GTK_OBJECT(widget)); loc->show(false); return TRUE; } /* * Draw area created, or size changed. */ C_EXPORT gint on_loc_draw_configure_event ( GtkWidget *widget, // The view window. GdkEventConfigure *event, gpointer data // ->Shape_chooser ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); loc->configure(widget); return TRUE; } /* * Draw area needs a repain. */ C_EXPORT gint on_loc_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); loc->render(&event->area); return TRUE; } /* * Mouse events in draw area. */ C_EXPORT gint on_loc_draw_button_press_event ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Chunk_chooser. ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); return loc->mouse_press(event); } C_EXPORT gint on_loc_draw_button_release_event ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Chunk_chooser. ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); return loc->mouse_release(event); } C_EXPORT gint on_loc_draw_motion_notify_event ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Chunk_chooser. ) { Locator *loc = (Locator *) gtk_object_get_user_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget)))); return loc->mouse_motion(event); } /* * Create locator window. */ Locator::Locator ( ) : drawgc(0), tx(0), ty(0), txs(40), tys(25), scale(1), dragging(false), send_location_timer(-1) { GladeXML *app_xml = ExultStudio::get_instance()->get_xml(); win = glade_xml_get_widget(app_xml, "loc_window"); gtk_object_set_user_data(GTK_OBJECT(win), this); draw = glade_xml_get_widget(app_xml, "loc_draw"); // Indicate the events we want. gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); // Set up scales. GtkWidget *scale = glade_xml_get_widget(app_xml, "loc_hscale"); hadj = gtk_range_get_adjustment(GTK_RANGE(scale)); scale = glade_xml_get_widget(app_xml, "loc_vscale"); vadj = gtk_range_get_adjustment(GTK_RANGE(scale)); hadj->upper = vadj->upper = c_num_chunks; hadj->page_increment = vadj->page_increment = c_chunks_per_schunk; hadj->page_size = vadj->page_size = 2; gtk_signal_emit_by_name(GTK_OBJECT(hadj), "changed"); gtk_signal_emit_by_name(GTK_OBJECT(vadj), "changed"); // Set scrollbar handlers. gtk_signal_connect(GTK_OBJECT(hadj), "value_changed", GTK_SIGNAL_FUNC(hscrolled), this); gtk_signal_connect(GTK_OBJECT(vadj), "value_changed", GTK_SIGNAL_FUNC(vscrolled), this); } /* * Delete. */ Locator::~Locator ( ) { if (send_location_timer != -1) gtk_timeout_remove(send_location_timer); gtk_widget_destroy(win); } /* * Show/hide. */ void Locator::show ( bool tf ) { if (tf) { gtk_widget_show(win); query_location(); // Get Exult's loc. } else gtk_widget_hide(win); } /* * Configure the draw window. */ void Locator::configure ( GtkWidget *widget // The draw window. ) { if (!widget->window) return; // Not ready yet. if (!drawgc) // First time? { drawgc = gdk_gc_new(widget->window); } } /* * Display. */ void Locator::render ( GdkRectangle *area // 0 for whole draw area. ) { // Get dims. int draww = draw->allocation.width, drawh = draw->allocation.height; GdkRectangle all; if (!area) { all.x = all.y = 0; all.width = draww; all.height = drawh; area = &all; } gdk_gc_set_clip_rectangle(drawgc, area); // Background is dark blue. gdk_rgb_gc_set_foreground(drawgc, 64); gdk_draw_rectangle(draw->window, drawgc, TRUE, area->x, area->y, area->width, area->height); // Show superchunks with dotted lines. #if 0 gdk_gc_set_line_attributes(drawgc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL); #endif // Paint in light grey. gdk_rgb_gc_set_foreground(drawgc, 0xc0c0c0); int i; int cur = 0; // Cur. pixel. // First the rows. for (i = 0; i < c_num_schunks - 1; i++) { int rowht = (drawh - cur)/(c_num_schunks - i); cur += rowht; gdk_draw_line(draw->window, drawgc, 0, cur, draww, cur); if (i == c_num_schunks/2 - 1) { // Make middle one 3 pixels. gdk_draw_line(draw->window, drawgc, 0, cur - 1, draww, cur - 1); gdk_draw_line(draw->window, drawgc, 0, cur + 1, draww, cur + 1); } } cur = 0; // Now the columns. for (i = 0; i < c_num_schunks - 1; i++) { int colwd = (draww - cur)/(c_num_schunks - i); cur += colwd; gdk_draw_line(draw->window, drawgc, cur, 0, cur, drawh); if (i == c_num_schunks/2 - 1) { // Make middle one 3 pixels. gdk_draw_line(draw->window, drawgc, cur - 1, 0, cur - 1, drawh); gdk_draw_line(draw->window, drawgc, cur + 1, 0, cur + 1, drawh); } } #if 0 // Back to solid lines for loc. box. gdk_gc_set_line_attributes(drawgc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL); #endif // Figure where to draw box. int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; int x = (cx*draww)/c_num_chunks, y = (cy*drawh)/c_num_chunks; int w = (txs*draww)/c_num_tiles, h = (tys*drawh)/c_num_tiles; if (w == 0) w = 1; if (h == 0) h = 1; // Draw location in yellow. gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (255<<8)); gdk_draw_rectangle(draw->window, drawgc, FALSE, x, y, w, h); viewbox.x = x; viewbox.y = y; // Save location. viewbox.width = w; viewbox.height = h; // Put a light-red box around it. gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (128<<8) + 128); gdk_draw_rectangle(draw->window, drawgc, FALSE, x - 3, y - 3, w + 6, h + 6); } /* * Message was received from Exult that the view has changed. */ void Locator::view_changed ( unsigned char *data, // Tx, Ty, xtiles, ytiles, scale. int datalen ) { if (datalen < 4*4) return; // Bad length. if (dragging) return; //+++++++Not sure about this. tx = Read4(data); ty = Read4(data); txs = Read4(data); tys = Read4(data); // ++++Scale? Later. // Do things by chunk. int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; tx = cx*c_tiles_per_chunk; ty = cy*c_tiles_per_chunk; // Update scrolls. gtk_adjustment_set_value(hadj, cx); gtk_adjustment_set_value(vadj, cy); render(); } /* * Handle a scrollbar event. */ void Locator::vscrolled // For vertical scrollbar. ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Shape_chooser. ) { Locator *loc = (Locator *) data; int oldty = loc->ty; loc->ty = ((gint) adj->value)*c_tiles_per_chunk; if (loc->ty != oldty) // (Already equal if this event came // from Exult msg.). { loc->render(); loc->send_location(); } } void Locator::hscrolled // For horizontal scrollbar. ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Locator. ) { Locator *loc = (Locator *) data; int oldtx = loc->tx; loc->tx = ((gint) adj->value)*c_tiles_per_chunk; if (loc->tx != oldtx) // (Already equal if this event came // from Exult msg.). { loc->render(); loc->send_location(); } } /* * Send location to Exult. */ void Locator::send_location ( ) { unsigned char data[50]; unsigned char *ptr = &data[0]; Write4(ptr, tx); Write4(ptr, ty); Write4(ptr, txs); Write4(ptr, tys); Write4(ptr, static_cast(-1)); // Don't change. cout << "Locator::send_location" << endl; ExultStudio::get_instance()->send_to_server(Exult_server::view_pos, &data[0], ptr - data); } /* * Query Exult for its location. */ void Locator::query_location ( ) { unsigned char data[50]; unsigned char *ptr = &data[0]; Write4(ptr, static_cast(-1)); Write4(ptr, static_cast(-1)); Write4(ptr, static_cast(-1)); Write4(ptr, static_cast(-1)); Write4(ptr, static_cast(-1)); ExultStudio::get_instance()->send_to_server(Exult_server::view_pos, &data[0], ptr - data); } /* * This is called a fraction of a second after mouse motion to send * the new location to Exult if the mouse hasn't moved further. */ gint Locator::delayed_send_location ( gpointer data // ->locator. ) { Locator *loc = (Locator *) data; loc->send_location(); loc->send_location_timer = -1; return 0; // Cancels timer. } /* * Go to a mouse location in the draw area. */ void Locator::goto_mouse ( int mx, int my, // Pixel coords. in draw area. bool delay_send // Delay send_location for a bit. ) { GdkRectangle oldbox = viewbox; // Old location of box. int oldtx = tx, oldty = ty; // Set tx,ty here so hscrolled() & // vscrolled() don't send to Exult. tx = (mx*c_num_tiles)/draw->allocation.width; ty = (my*c_num_tiles)/draw->allocation.height; int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk; if (cx > c_num_chunks - 2) cx = c_num_chunks - 2; if (cy > c_num_chunks - 2) cy = c_num_chunks - 2; tx = cx*c_tiles_per_chunk; ty = cy*c_tiles_per_chunk; // Update scrolls. gtk_adjustment_set_value(hadj, cx); gtk_adjustment_set_value(vadj, cy); // Now we just send it once. if (tx != oldtx || ty != oldty) { if (send_location_timer != -1) gtk_timeout_remove(send_location_timer); if (delay_send) // Send in 1/3 sec. if no more motion. send_location_timer = gtk_timeout_add(333, delayed_send_location, this); else { send_location(); send_location_timer = -1; } GdkRectangle newbox; // Figure dirty rectangle; GdkRectangle dirty; newbox.x = (cx*draw->allocation.width)/c_num_chunks, newbox.y = (cy*draw->allocation.height)/c_num_chunks; newbox.width = oldbox.width; newbox.height = oldbox.height; gdk_rectangle_union(&oldbox, &newbox, &dirty); // Expand a bit. dirty.x -= 4; dirty.y -= 4; dirty.width += 8; dirty.height += 8; render(&dirty); } } /* * Handle a mouse-press event. */ gint Locator::mouse_press ( GdkEventButton *event ) { dragging = false; if (event->button != 1) return FALSE; // Handling left-click. // Get mouse position, draw dims. int mx = (int) event->x, my = (int) event->y; int draww = draw->allocation.width, drawh = draw->allocation.height; // Double-click? if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS) { goto_mouse(mx, my); return TRUE; } // On (or close to) view box? if (mx < viewbox.x - 3 || my < viewbox.y - 3 || mx > viewbox.x + viewbox.width + 6 || my > viewbox.y + viewbox.height + 6) return FALSE; dragging = true; drag_relx = mx - viewbox.x; // Save rel. pos. drag_rely = my - viewbox.y; return (TRUE); } /* * Handle a mouse-release event. */ gint Locator::mouse_release ( GdkEventButton *event ) { dragging = false; return TRUE; } /* * Handle a mouse-motion event. */ gint Locator::mouse_motion ( GdkEventMotion *event ) { int mx, my; GdkModifierType state; if (event->is_hint) gdk_window_get_pointer(event->window, &mx, &my, &state); else { mx = (int) event->x; my = (int) event->y; state = (GdkModifierType) event->state; } if (!dragging || !(state & GDK_BUTTON1_MASK)) return FALSE; // Not dragging with left button. // Delay sending location to Exult. goto_mouse(mx + drag_relx, my + drag_rely, true); return TRUE; } exult-1.2/mapedit/shapegroup.h0000644000175000001440000000534407664343445012170 /** ** A group of shapes/chunks that can be used as a 'palette'. ** ** Written: 1/22/02 - JSF **/ #ifndef INCL_SHAPEGROUP #define INCL_SHAPEGROUP 1 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include class Shape_group_file; /* * A group of shape/chunk #'s: */ class Shape_group : std::vector // Not public on purpose. { std::string name; // What this group is called. Shape_group_file *file; // Where this comes from. public: friend class Shape_group_file; Shape_group(const char *nm, Shape_group_file *f); ~Shape_group() { } Shape_group_file *get_file() { return file; } const char *get_name() const { return name.c_str(); } void set_name(char *nm) { name = nm; } int size() { return std::vector::size(); } int& operator[](int i) { return std::vector::operator[](i); } void del(int i); void swap(int i); // Swap entries i and i+1. void add(int id); // Add ID, checking for duplicate 1st. }; /* * This class represents the file containing groups for a given shape * or chunks file. It is read from the 'patch' or 'static' directory, * and saved to the 'patch' directory. */ class Shape_group_file { std::string name; // Base filename. std::vector groups;// List of groups from the file. bool modified; // Changed since last save. public: friend class Shape_group; Shape_group_file(const char *nm); ~Shape_group_file(); int size() { return groups.size(); } Shape_group *get(int i) { return groups[i]; } void clear() // Clears list (but doesn't delete). { groups.resize(0); } void add(Shape_group *grp) // Add a new group. { groups.push_back(grp); modified = true; } void set(Shape_group *grp, int i) { groups[i] = grp; modified = true; } void insert(Shape_group *grp, int i) { groups.insert(groups.begin() + i, grp); modified = true; } bool is_modified() { return modified; } int find(const char *nm); // Find group with given name. // Remove and delete group. void remove(int index, bool del = true); void write(); // Write out (to 'patch' directory). }; #endif exult-1.2/mapedit/shapedraw.h0000644000175000001440000000542307657400521011756 /** ** Shapedraw.h - Manage a drawing area that shows one or more shapes. ** ** Written: 6/2/2001 - JSF **/ #ifndef INCL_SHAPEDRAW #define INCL_SHAPEDRAW 1 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include class Vga_file; class Shape_frame; class Image_buffer8; typedef void (*Drop_callback)(int filenum, int shapenum, int framenum, void *udata); /* * This class can draw shapes from a .vga file. */ class Shape_draw { protected: Vga_file *ifile; // Where the shapes come from. GtkWidget *draw; // GTK draw area to display them in. GdkGC *drawgc; // For drawing in 'draw'. Image_buffer8 *iwin; // What we render into. GdkRgbCmap *palette; // For gdk_draw_indexed_image(). Drop_callback drop_callback; // Called when a shape is dropped here. void *drop_user_data; bool dragging; // Dragging from here. public: Shape_draw(Vga_file *i, unsigned char *palbuf, GtkWidget *drw); virtual ~Shape_draw(); // Blit onto screen. void show(GdkDrawable *drawable, int x, int y, int w, int h); void show(int x, int y, int w, int h) { show(draw->window, x, y, w, h); } void show() { show(0, 0, draw->allocation.width, draw->allocation.height);} guint32 get_color(int i) { return palette->colors[i]; } void draw_shape(Shape_frame *shape, int x, int y); void draw_shape(int shapenum, int framenum, int x, int y); void draw_shape_outline(int shapenum, int framenum, int x, int y, unsigned char color); void draw_shape_centered(int shapenum, int framenum); virtual void render(); // Update what gets shown. void set_background_color(guint32 c); void configure(); // Configure when created/resized. // Handler for drop. static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer udata); void enable_drop(Drop_callback callback, void *udata); void set_drag_icon(GdkDragContext *context, Shape_frame *shape); // Start/end dragging from here. void start_drag(char *target, int id, GdkEvent *event); void mouse_up() { dragging = false; } }; #endif exult-1.2/mapedit/shapefile.h0000644000175000001440000001200107554107500011723 /** ** Information about a shapes file. ** ** Written: 1/23/02 - JSF **/ #ifndef INCL_SHAPEFILE #define INCL_SHAPEFILE 1 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include class Vga_file; class Shape_group_file; class Object_browser; class Shape_group; class Shape; class Flex; /* * A shape file: */ class Shape_file_info { protected: std::string basename; // Base filename. std::string pathname; // Full pathname. Shape_group_file *groups; // Groups within ifile. bool modified; // Ifile was modified. Object_browser *browser; // Widget for seeing this file. public: friend class Shape_file_set; // We will own files and groups. Shape_file_info(const char *bnm, const char *pnm, Shape_group_file *g) : basename(bnm), pathname(pnm), groups(g), modified(false), browser(0) { } virtual ~Shape_file_info(); const char *get_basename() { return basename.c_str(); } const char *get_pathname() { return pathname.c_str(); } Shape_group_file *get_groups() { return groups; } void set_modified() { modified = true; } virtual Vga_file *get_ifile() { return 0; } // Call this to create group browser. virtual Object_browser *create_browser(Shape_file_info *vgafile, unsigned char *palbuf, Shape_group *g) { return 0; } // Call for main browser. virtual Object_browser *get_browser(Shape_file_info *vgafile, unsigned char *palbuf); virtual std::ifstream *get_file() { return 0; } virtual Flex *get_flex() { return 0; } virtual void flush() // Write if modified. { modified = false; } virtual bool revert() { return false; } // Means 'not supported'. }; /* * Image file: */ class Image_file_info : public Shape_file_info { Vga_file *ifile; // Contains the images. public: // We will own ifile. Image_file_info(const char *bnm, const char *pnm, Vga_file *i, Shape_group_file *g) : Shape_file_info(bnm, pnm, g), ifile(i) { } virtual ~Image_file_info(); virtual Vga_file *get_ifile() { return ifile; } virtual Object_browser *create_browser(Shape_file_info *vgafile, unsigned char *palbuf, Shape_group *g = 0); virtual void flush(); // Write if modified. virtual bool revert(); static void write_file(const char *pathname, Shape **shapes, int nshapes, bool single); }; /* * Chunks file: */ class Chunks_file_info : public Shape_file_info { std::ifstream *file; // For 'chunks'; ifile is NULL. public: // We will own file. Chunks_file_info(const char *bnm, const char *pnm, std::ifstream *f, Shape_group_file *g) : Shape_file_info(bnm, pnm, g), file(f) { } virtual ~Chunks_file_info(); virtual std::ifstream *get_file() { return file; } virtual Object_browser *create_browser(Shape_file_info *vgafile, unsigned char *palbuf, Shape_group *g = 0); virtual void flush(); // Write if modified. }; /* * Flex file (used for combos, palettes): */ class Flex_file_info : public Shape_file_info { Flex *flex; // NULL if just 1 entry. std::vector entries; // Entries are stored here. std::vector lengths; // Lengths here. bool write_flat; // Write flat file if just 1 entry. public: // We will own flex. Flex_file_info(const char *bnm, const char *pnm, Flex *fl, Shape_group_file *g); // Create for single-palette. Flex_file_info(const char *bnm, const char *pnm, int size); int size() // Get # flex entries. { return entries.size(); } char *get(int i, size_t& len); // Get i'th entry. // Set i'th entry. void set(int i, char *newentry, int entlen); void swap(int i); // Swap entries i, i+1. void remove(int i); // Remove i'th entry. virtual ~Flex_file_info(); virtual Object_browser *create_browser(Shape_file_info *vgafile, unsigned char *palbuf, Shape_group *g = 0); virtual Flex *get_flex() { return flex; } virtual void flush(); // Write if modified. virtual bool revert(); }; /* * A set of Shape_file's. */ class Shape_file_set { std::vector files; Shape_file_info *append(Shape_file_info *fi) { files.push_back(fi); return fi; } public: Shape_file_set() { } ~Shape_file_set(); // Create, or return existing one. Shape_file_info *create(const char *basename); int size() { return files.size(); } Shape_file_info *operator[](int i) { return files[i]; } void flush(); // Write if modified. bool is_modified(); // Any modified? }; #endif exult-1.2/mapedit/locator.h0000644000175000001440000000420207442606001011426 /** ** Locator.h - Locate game positions. ** ** Written: March 2, 2002 - JSF **/ /* Copyright (C) 2001-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_LOCATOR #define INCL_LOCATOR /* * The 'locator' window: */ class Locator { GtkWidget *win; // Main window. GtkWidget *draw; // GTK draw area to display. GdkGC *drawgc; // For drawing in 'draw'. GtkAdjustment *hadj, *vadj; // For horiz., vert. scales. int tx, ty, txs, tys, scale; // Current Exult win. info. in tiles. GdkRectangle viewbox; // Where view box was last drawn. bool dragging; // True if dragging view box. int drag_relx, drag_rely; // Mouse pos. rel to view box. int send_location_timer; // For sending new loc. to Exult. void send_location(); // Send location/size to Exult. void query_location(); static gint delayed_send_location(gpointer data); // Set view to mouse location. void goto_mouse(int mx, int my, bool delay_send = false); public: Locator(); ~Locator(); void show(bool tf); // Show/hide. // Configure when created/resized. void configure(GtkWidget *widget); void render(GdkRectangle *area = 0); // Message from exult. void view_changed(unsigned char *data, int datalen); // Handle scrollbar. static void vscrolled(GtkAdjustment *adj, gpointer data); static void hscrolled(GtkAdjustment *adj, gpointer data); // Handle mouse. gint mouse_press(GdkEventButton *event); gint mouse_release(GdkEventButton *event); gint mouse_motion(GdkEventMotion *event); }; #endif exult-1.2/mapedit/exult_studio.cc0000644000175000001440000000222307424024620012653 #ifdef HAVE_CONFIG_H # include #endif #if defined(WIN32) && !defined(USE_CONSOLE) #include #define STDOUT_FILE TEXT("studio_out.txt") #define STDERR_FILE TEXT("studio_err.txt") #endif #include "studio.h" int main(int argc, char **argv) { // Code copied from SDL_main #if defined(WIN32) && !defined(USE_CONSOLE) /* Flush the output in case anything is queued */ fclose(stdout); fclose(stderr); /* Redirect standard input and standard output */ FILE *newfp = freopen(STDOUT_FILE, "w", stdout); if ( newfp == NULL ) { /* This happens on NT */ #if !defined(stdout) stdout = fopen(STDOUT_FILE, "w"); #else newfp = fopen(STDOUT_FILE, "w"); if ( newfp ) { *stdout = *newfp; } #endif } newfp = freopen(STDERR_FILE, "w", stderr); if ( newfp == NULL ) { /* This happens on NT */ #if !defined(stderr) stderr = fopen(STDERR_FILE, "w"); #else newfp = fopen(STDERR_FILE, "w"); if ( newfp ) { *stderr = *newfp; } #endif } setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ setbuf(stderr, NULL); /* No buffering */ #endif //defined(WIN32) && !defined(USE_CONSOLE) ExultStudio studio(argc, argv); studio.run(); } exult-1.2/mapedit/shapelst.cc0000644000175000001440000016407310040666324011763 /** ** A GTK widget showing a list of shapes from an image file. ** ** Written: 7/25/99 - JSF **/ /* Copyright (C) 1999 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef WIN32 #include "Windrag.h" #include #endif #include #include #ifdef XWIN #include #endif #include #include #include #include #include "shapelst.h" #include "shapevga.h" #include "ibuf8.h" #include "Flex.h" #include "u7drag.h" #include "studio.h" #include "utils.h" #include "shapegroup.h" #include "shapefile.h" #include "pngio.h" #include "fontgen.h" using std::cout; using std::endl; using std::strlen; using std::string; using EStudio::Prompt; using EStudio::Alert; using EStudio::Add_menu_item; std::vector Shape_chooser::editing_files; int Shape_chooser::check_editing_timer = -1; /* * Here's a description of a file being edited by an external program * like Gimp or Photoshop. */ class Editing_file { string vga_basename; // Name of image file this comes from. string pathname; // Full path to file. time_t mtime; // Last modification time. int shapenum, framenum; // Shape/frame. int tiles; // If > 0, #8x8 tiles per row or col. bool bycolumns; // If true tile by column first. public: friend class Shape_chooser; // Create for single frame: Editing_file(const char *vganm, const char *pnm, time_t m, int sh, int fr) : vga_basename(vganm), pathname(pnm), mtime(m), shapenum(sh), framenum(fr), tiles(0) { } // Create tiled: Editing_file(const char *vganm, const char *pnm, time_t m, int sh, int ts, bool bycol) : vga_basename(vganm), pathname(pnm), mtime(m), shapenum(sh), framenum(0), tiles(ts), bycolumns(bycol) { } }; /* * Callback for when a shape is dropped on our draw area. */ static void Shape_dropped_here ( int file, // U7_SHAPE_SHAPES. int shape, int frame, void *udata ) { ((Shape_chooser *) udata)->shape_dropped_here(file, shape, frame); } /* * Blit onto screen. */ void Shape_chooser::show ( int x, int y, int w, int h // Area to blit. ) { Shape_draw::show(draw->window, x, y, w, h); if (selected >= 0) // Show selected. { Rectangle b = info[selected].box; // Draw yellow box. gdk_draw_rectangle(draw->window, drawgc, FALSE, b.x, b.y, b.w, b.h); } } /* * Send selected shape/frame to Exult. */ void Shape_chooser::tell_server_shape ( ) { int shnum = -1, frnum = 0; if (selected >= 0) { shnum = info[selected].shapenum; frnum = info[selected].framenum; } unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Write2(ptr, shnum); Write2(ptr, frnum); ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server(Exult_server::set_edit_shape, buf, ptr - buf); } /* * Select an entry. This should be called after rendering * the shape. */ void Shape_chooser::select ( int new_sel ) { selected = new_sel; tell_server_shape(); // Tell Exult. int shapenum = info[selected].shapenum; // Update spin-button value, range. gtk_widget_set_sensitive(fspin, true); gtk_adjustment_set_value(frame_adj, info[selected].framenum); int nframes = ifile->get_num_frames(shapenum); frame_adj->upper = nframes - 1; gtk_adjustment_changed(frame_adj); gtk_widget_set_sensitive(fspin, true); // Remove prev. selection msg. // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); char buf[150]; // Show new selection. g_snprintf(buf, sizeof(buf), "Shape %d (%d frames)", shapenum, nframes); ExultStudio *studio = ExultStudio::get_instance(); if (shapes_file && studio->get_shape_name(shapenum)) { int len = strlen(buf); g_snprintf(buf + len, sizeof(buf) - len, ": '%s'", studio->get_shape_name(shapenum)); } gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } const int border = 4; // Border at bottom, sides. /* * Render as many shapes as fit in the shape chooser window. */ void Shape_chooser::render ( ) { if (frames_mode) { render_frames(); return; } // Look for selected frame. int selshape = -1, selframe = -1, new_selected = -1; if (selected >= 0) // Save selection info. { selshape = info[selected].shapenum; selframe = info[selected].framenum; } // Remove "selected" message. //gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); delete [] info; // Delete old info. list. // Get drawing area dimensions. gint winw = draw->allocation.width, winh = draw->allocation.height; // Provide more than enough room. info = new Shape_entry[1024]; // Clear window first. iwin->fill8(255); // Set to background_color. int x = 0; info_cnt = 0; // Count them. int curr_y = 0; int row_h = 0; int row = row0; // Row #. int total_cnt = get_count(); int index; // This is shapenum if there's no // filter (group). for (int index = index0; index < total_cnt; index++) { int shapenum = group ? (*group)[index] : index; int framenum = shapenum == selshape ? selframe : framenum0; Shape_frame *shape = ifile->get_shape(shapenum, framenum); if(shape) { int sh = shape->get_height(), sw = shape->get_width(); if (sh>row_h) row_h = sh; // Check if we've exceeded max width if (x + sw > winw) { // Next line. curr_y += row_h + border; row_h = sh; x = 0; row++; if (row == row_indices.size()) row_indices.push_back(index); else if (row < row_indices.size()) row_indices[row] = index; if (curr_y + 36 >= winh) break; } int sy = curr_y+border; // Get top y-coord. shape->paint(iwin, x + shape->get_xleft(), sy + shape->get_yabove()); if (sh > winh) { sy += sh - winh; sh = winh; } // Store info. about where drawn. info[info_cnt].set(index, shapenum, framenum, x, sy, sw, sh); if (shapenum == selshape) // Found the selected shape. new_selected = info_cnt; x += sw + border; info_cnt++; } } nrows = row - row0; // # rows shown. nrows += (x > 0); // Add partial row at end. if (new_selected == -1) unselect(false); else select(new_selected); adjust_vscrollbar(); // Set new scroll values. } /* * Get maximum shape height for all its frames. */ static int Get_max_height ( Shape *shape ) { int cnt = shape->get_num_frames(); int maxh = 0; for (int i = 0; i < cnt; i++) { Shape_frame *frame = shape->get_frame(i); int ht = frame ? frame->get_height() : -1; if (ht > maxh) maxh = ht; } return maxh; } /* * Get the x-offset in pixels where a frame will be drawn. * * Output: Offset from left edge of (virtual) drawing area. */ static int Get_x_offset ( Shape *shape, int framenum ) { if (!shape) return 0; int nframes = shape->get_num_frames(); if (framenum >= nframes) framenum = nframes - 1; int xoff = 0; for (int i = 0; i < framenum; i++) xoff += shape->get_frame(i)->get_width() + border; return xoff; } /* * Render one shape per row, showing its frames from left to right. */ void Shape_chooser::render_frames ( ) { // Get drawing area dimensions. gint winw = draw->allocation.width, winh = draw->allocation.height; // Look for selected frame. int selshape = -1, selframe = -1, new_selected = -1; if (selected >= 0) // Save selection info. { selshape = info[selected].shapenum; selframe = info[selected].framenum; } // Remove "selected" message. //gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); delete [] info; // Delete old info. list. iwin->set_clip(0, 0, winw, winh); // Provide more than enough room. info = new Shape_entry[4048]; //++++++Pretty risky. Use s vec!!! // Clear window first. iwin->fill8(255); // Fill with background color. info_cnt = 0; // Count them. int curr_y = 0; int row = row0; // Row #. int total_cnt = get_count(); int index; // This is shapenum if there's no // filter (group). for (int index = index0; index < total_cnt; index++) { int shapenum = group ? (*group)[index] : index; // Get all frames. Shape *shape = ifile->extract_shape(shapenum); int nframes = shape ? shape->get_num_frames() : 0; if (!nframes) continue; int row_h = Get_max_height(shape); int x = -hoffset; int sw, sh; for (int framenum = 0; framenum < nframes; framenum++, x += sw + border) { if (x >= winw - 1) // Past right edge? break; Shape_frame *frame = shape->get_frame(framenum); if (!frame) { sw = sh = 0; continue; } sh = frame->get_height(); sw = frame->get_width(); if (x < 0 && x + sw < sw/2) continue;// Skip to left of hoffset. int sy = curr_y+border; // Get top y-coord. frame->paint(iwin, x + frame->get_xleft(), sy + frame->get_yabove()); if (sh > winh) { sy += sh - winh; sh = winh; } // Store info. about where drawn. info[info_cnt].set(index, shapenum, framenum, x, sy, sw, sh); if (shapenum == selshape && framenum == selframe) // Found the selected shape. new_selected = info_cnt; info_cnt++; } // Next line. curr_y += row_h + border; x = 0; if (row == row_indices.size()) row_indices.push_back(index); else if (row < row_indices.size()) row_indices[row] = index; row++; if (curr_y + 36 >= winh) break; } int nrows = row - row0; // # rows shown. if (new_selected == -1) unselect(false); else select(new_selected); iwin->clear_clip(); adjust_vscrollbar(); // Set new scroll values. } /* * Horizontally scroll so that the selected frame is visible (in frames * mode). */ void Shape_chooser::scroll_to_frame ( ) { if (selected >= 0) // Save selection info. { int selshape = info[selected].shapenum; int selframe = info[selected].framenum; Shape *shape = ifile->extract_shape(selshape); int xoff = Get_x_offset(shape, selframe); if (xoff < hoffset) // Left of visual area? hoffset = xoff > border ? xoff - border : 0; else { gint winw = draw->allocation.width; int sw = shape->get_frame(selframe)->get_width(); if (xoff + sw + border - hoffset > winw) hoffset = xoff + sw + border - winw; } GtkAdjustment *adj = gtk_range_get_adjustment( GTK_RANGE(hscroll)); gtk_adjustment_set_value(adj, hoffset); } } /* * Find start of next row. * * Output: Index of start of next row, or -1 if given is last. */ int Shape_chooser::next_row ( int start // Index of row to start at. ) { int total_cnt = get_count(); if (frames_mode) // Easy if 1 shape/row. return start < total_cnt - 1 ? (start + 1) : -1; int selshape = -1, selframe = -1; if (selected >= 0) // Save selection info. { selshape = info[selected].shapenum; selframe = info[selected].framenum; } gint winw = draw->allocation.width; int index = start; int x = 0; while (index < total_cnt) { int shapenum = group ? (*group)[index] : index; int framenum = shapenum == selshape ? selframe : framenum0; Shape_frame *shape = ifile->get_shape(shapenum, framenum); if(shape) { int sw = shape->get_width(); if (x + sw > winw) break; // Done. x += sw + border; } index++; } if (index == start) // Always advance at least 1. index++; if (index == total_cnt) return -1; // Past end. return index; } /* * Scroll so a desired index is in view. */ void Shape_chooser::goto_index ( int index // Desired index. ) { int total = get_count(); // Total #entries. if (!total) return; // Empty. assert (index >= 0 && index < total); // Get index past what's shown. int last_index = index0 + (frames_mode ? nrows : info_cnt); if (index < index0) // Above current view? { do index0 = row_indices[--row0]; while (index < index0); } else if (index >= last_index && last_index > 0) { // Below current view. do { if (row0 < row_indices.size() - 1) index0 = row_indices[++row0]; else { int i = next_row(index0); if (i < 0) // Past end. Shouldn't happen. break; row_indices.push_back(i); row0++; index0 = i; } } while (index0 < index); if (index != index0) row0--; // We passed it. index0 = row_indices[row0]; info_cnt = 0; } // Get to right spot again! GtkAdjustment *adj = gtk_range_get_adjustment( GTK_RANGE(vscroll)); if (row0 >= adj->value) // Beyond apparent end? adjust_vscrollbar(); // Needs updating. gtk_adjustment_set_value(adj, row0); } /* * Configure the viewing window. */ static gint Configure_chooser ( GtkWidget *widget, // The drawing area. GdkEventConfigure *event, gpointer data // ->Shape_chooser ) { Shape_chooser *chooser = (Shape_chooser *) data; return chooser->configure(event); } gint Shape_chooser::configure ( GdkEventConfigure *event ) { Shape_draw::configure(); // Did the size change? if (event->width != config_width || event->height != config_height) { row_indices.resize(1); // Start over with row info. row0 = 0; info_cnt = 0; int i0 = index0; // Get back to where we were. index0 = 0; goto_index(i0); // Now goto where we were. render(); // This also adjusts scrollbar. adjust_hscrollbar(-1); config_width = event->width; config_height = event->height; } else render(); // Same size? Just render it. // Set handler for shape dropped here, // BUT not more than once. if (drop_callback != Shape_dropped_here) enable_drop(Shape_dropped_here, this); return (TRUE); } /* * Handle an expose event. */ gint Shape_chooser::expose ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; chooser->show(event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Handle a mouse drag event. */ #ifdef WIN32 static bool win32_button = false; gint Shape_chooser::win32_drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Shape_chooser. ) { if (win32_button) { win32_button = false; // prepare the dragged data windragdata wdata; // This call allows us to recycle the data transfer initialization code. // It's clumsy, but far easier to maintain. drag_data_get(NULL, NULL, (GtkSelectionData *) &wdata, U7_TARGET_SHAPEID, 0, data); POINT pnt; GetCursorPos(&pnt); LPDROPSOURCE idsrc = (LPDROPSOURCE) new Windropsource(0, pnt.x, pnt.y); LPDATAOBJECT idobj = (LPDATAOBJECT) new Winstudioobj(wdata); DWORD dndout; HRESULT res = DoDragDrop(idobj, idsrc, DROPEFFECT_COPY, &dndout); if (FAILED(res)) { g_warning ("Oops! Something is wrong with OLE2 DnD.."); } delete idsrc; idobj->Release(); // Not sure if we really need this. However, it doesn't hurt either. } return true; }; #else gint Shape_chooser::drag_motion ( GtkWidget *widget, // The view window. GdkEventMotion *event, gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; if (!chooser->dragging && chooser->selected >= 0) chooser->start_drag(U7_TARGET_SHAPEID_NAME, U7_TARGET_SHAPEID, (GdkEvent *) event); return true; } #endif /* * Handle a mouse button-press event. */ gint Shape_chooser::mouse_press ( GtkWidget *widget, // The view window. GdkEventButton *event ) { gtk_widget_grab_focus(widget); if (event->button == 4) { if (row0 > 0) scroll_vertical(row0-1); return(TRUE); } else if (event->button == 5) { scroll_vertical(row0+1); return(TRUE); } int old_selected = selected; int i; // Search through entries. for (i = 0; i < info_cnt; i++) if (info[i].box.has_point( (int) event->x, (int) event->y)) { // Found the box? // Indicate we can drag. #ifdef WIN32 // Here, we have to override GTK+'s Drag and Drop, which is non-OLE and // usually stucks outside the program window. I think it's because // the dragged shape only receives mouse motion events when the new mouse pointer // position is *still* inside the shape. So if you move the mouse too fast, // we are stuck. win32_button = true; #endif selected = i; render(); show(); // Tell client. if (sel_changed) (*sel_changed)(); break; } if (i == info_cnt && event->button == 1) unselect(true); // No selection. else if (selected == old_selected && old_selected >= 0) { // Same square. Check for dbl-click. if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS) edit_shape_info(); } if (event->button == 3) gtk_menu_popup(GTK_MENU(create_popup()), 0, 0, 0, 0, event->button, event->time); return (TRUE); } /* * Handle mouse button press/release events. */ static gint Mouse_press ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; return chooser->mouse_press(widget, event); } static gint Mouse_release ( GtkWidget *widget, // The view window. GdkEventButton *event, gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; chooser->mouse_up(); } /* * Keystroke in draw-area. */ C_EXPORT gboolean on_draw_key_press (GtkEntry *entry, GdkEventKey *event, gpointer user_data) { Shape_chooser *chooser = (Shape_chooser *) user_data; switch (event->keyval) { case GDK_Delete: chooser->del_frame(); return TRUE; case GDK_Insert: chooser->new_frame(); return TRUE; } return FALSE; // Let parent handle it. } const unsigned char transp = 255; /* * Export the currently selected frame as a .png file. * * Output: Modification time of file written, or 0 if error. */ time_t Shape_chooser::export_png ( const char *fname // File to write out. ) { ExultStudio *studio = ExultStudio::get_instance(); int shnum = info[selected].shapenum, frnum = info[selected].framenum; Shape_frame *frame = ifile->get_shape(shnum, frnum); int w = frame->get_width(), h = frame->get_height(); Image_buffer8 img(w, h); // Render into a buffer. img.fill8(transp); // Fill with transparent pixel. frame->paint(&img, frame->get_xleft(), frame->get_yabove()); int xoff = 0, yoff = 0; if (frame->is_rle()) { xoff = -frame->get_xright(); yoff = -frame->get_ybelow(); } return export_png(fname, img, xoff, yoff); } /* * Convert a GDK color map to a 3*256 byte RGB palette. */ static void Get_rgb_palette ( GdkRgbCmap *palette, unsigned char *buf // 768 bytes (3*256). ) { for (int i = 0; i < 256; i++) { buf[3*i] = (palette->colors[i]>>16)&0xff; buf[3*i + 1] = (palette->colors[i]>>8)&0xff; buf[3*i + 2] = palette->colors[i]&0xff; } } /* * Export an image as a .png file. * * Output: Modification time of file written, or 0 if error. */ time_t Shape_chooser::export_png ( const char *fname, // File to write out. Image_buffer8& img, // Image. int xoff, int yoff // Offset (from bottom-right). ) { unsigned char pal[3*256]; // Set up palette. Get_rgb_palette(palette, pal); int w = img.get_width(), h = img.get_height(); struct stat fs; // Write out to the .png. // (Rotate transp. pixel to 0 for the // Gimp's sake.) if (!Export_png8(fname, transp, w, h, w, xoff, yoff, img.get_bits(), &pal[0], 256, true) || stat(fname, &fs) != 0) { Alert("Error creating '%s'", fname); return 0; } return fs.st_mtime; } /* * Export the current shape (which better be 8x8 flat) as a tiled PNG. * * Output: modification time of file, or 0 if error. */ time_t Shape_chooser::export_tiled_png ( const char *fname, // File to write out. int tiles, // If #0, write all frames as tiles, // this many in each row (col). bool bycols // Write tiles columns-first. ) { assert (selected >= 0); int shnum = info[selected].shapenum; ExultStudio *studio = ExultStudio::get_instance(); // Low shape in 'shapes.vga'? assert (shnum < 0x96 && file_info == studio->get_vgafile()); Shape *shape = ifile->extract_shape(shnum); assert(shape != 0); cout << "Writing " << fname << " tiled" << (bycols ? ", by cols" : ", by rows") << " first" << endl; int nframes = shape->get_num_frames(); // Figure #tiles in other dim. int dim1_cnt = (nframes + tiles - 1)/tiles; int w, h; if (bycols) { h = tiles*8; w = dim1_cnt*8; } else { w = tiles*8; h = dim1_cnt*8; } Image_buffer8 img(w, h); img.fill8(transp); // Fill with transparent pixel. for (int f = 0; f < nframes; f++) { Shape_frame *frame = shape->get_frame(f); if (!frame) continue; // We'll just leave empty ones blank. if (frame->is_rle() || frame->get_width() != 8 || frame->get_height() != 8) { Alert("Can only tile 8x8 flat shapes"); return 0; } int x, y; if (bycols) { y = f%tiles; x = f/tiles; } else { x = f%tiles; y = f/tiles; } frame->paint(&img, x*8 + frame->get_xleft(), y*8 + frame->get_yabove()); } // Write out to the .png. return export_png(fname, img, 0, 0); } /* * Bring up the shape-info editor for the selected shape. */ void Shape_chooser::edit_shape_info ( ) { ExultStudio *studio = ExultStudio::get_instance(); int shnum = info[selected].shapenum, frnum = info[selected].framenum; Shape_info *info = 0; char *name = 0; if (shapes_file) { // Read info. the first time. shapes_file->read_info(false, true);//+++++BG? info = &shapes_file->get_info(shnum); name = studio->get_shape_name(shnum); } studio->open_shape_window(shnum, frnum, file_info, name, info); } /* * Bring up the user's image-editor for the selected shape. */ void Shape_chooser::edit_shape ( int tiles, // If #0, write all frames as tiles, // this many in each row (col). bool bycols // Write tiles columns-first. ) { ExultStudio *studio = ExultStudio::get_instance(); int shnum = info[selected].shapenum, frnum = info[selected].framenum; string filestr(""); // Set up filename. filestr += "/itmp"; // "Image tmp" directory. U7mkdir(filestr.c_str(), 0755); // Create if not already there. // Lookup . filestr = get_system_path(filestr); char *ext; if (!tiles) // Create name from file,shape,frame. ext = g_strdup_printf("/%s.s%d_f%d.png", file_info->get_basename(), shnum, frnum); else // Tiled. ext = g_strdup_printf("/%s.s%d_%c%d.png", file_info->get_basename(), shnum, (bycols ? 'c' : 'r'), tiles); filestr += ext; g_free(ext); const char *fname = filestr.c_str(); cout << "Writing image '" << fname << "'" << endl; time_t mtime; if (!tiles) // One frame? { mtime = export_png(fname); if (!mtime) return; // Store info. about file. editing_files.push_back(new Editing_file( file_info->get_basename(), fname, mtime, shnum, frnum)); } else { mtime = export_tiled_png(fname, tiles, bycols); if (!mtime) return; editing_files.push_back(new Editing_file( file_info->get_basename(), fname, mtime, shnum, tiles, bycols)); } string cmd(studio->get_image_editor()); cmd += ' '; cmd += fname; cmd += " &"; // Background. #ifndef WIN32 int ret = system(cmd.c_str()); if (ret == 127 || ret == -1) Alert("Can't launch '%s'", studio->get_image_editor()); #else PROCESS_INFORMATION pi; STARTUPINFO si; std::memset (&si, 0, sizeof(si)); si.cb = sizeof(si); int ret = CreateProcess (NULL, const_cast(cmd.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (!ret) Alert("Can't launch '%s'", studio->get_image_editor()); #endif if (check_editing_timer == -1) // Monitor files every 6 seconds. check_editing_timer = gtk_timeout_add(6000, Shape_chooser::check_editing_files_cb, 0L); } /* * Check the list of files being edited externally, and read in any that * have changed. * * Output: 1 always. */ gint Shape_chooser::check_editing_files_cb ( gpointer ) { ExultStudio *studio = ExultStudio::get_instance(); // Is focus in main window? if (studio->has_focus()) check_editing_files(); return 1; // Keep repeating. } // This one doesn't check focus. gint Shape_chooser::check_editing_files ( ) { bool modified = false; for (std::vector::iterator it = editing_files.begin(); it != editing_files.end(); it++) { Editing_file *ed = *it; struct stat fs; // Check mod. time of file. if (stat(ed->pathname.c_str(), &fs) != 0) { // Gone? delete ed; it = editing_files.erase(it); continue; } if (fs.st_mtime <= ed->mtime) continue; // Still not changed. ed->mtime = fs.st_mtime; read_back_edited(ed); modified = true; // Did one. } if (modified) // Repaint if modified. { ExultStudio *studio = ExultStudio::get_instance(); Object_browser *browser = studio->get_browser(); if (browser) { // Repaint main window. browser->render(); browser->show(); } studio->update_group_windows(0); } return 1; // Continue timeouts. } /* * Find the closest color in a palette to a given one. * * Output: 0-254, whichever has closest color. */ static int Find_closest_color ( unsigned char *pal, // 3*255 bytes. int r, int g, int b // Color to match. ) { int best_index = -1; long best_distance = 0xfffffff; // But don't search rotating colors. for (int i = 0; i < 0xe0; i++) { // Get deltas. long dr = r - pal[3*i], dg = g - pal[3*i + 1], db = b - pal[3*i + 2]; // Figure distance-squared. long dist = dr*dr + dg*dg + db*db; if (dist < best_distance) { // Better than prev? best_index = i; best_distance = dist; } } return best_index; } /* * Convert an 8-bit image in one palette to another. */ static void Convert_indexed_image ( unsigned char *pixels, // Pixels. int count, // # pixels. unsigned char *oldpal, // Palette pixels currently uses. int oldpalsize, // Size of old palette. unsigned char *newpal // Palette (255 bytes) to convert to. ) { if (memcmp(oldpal, newpal, oldpalsize) == 0) return; // Old palette matches new. int map[256]; // Set up old->new map. int i; for (i = 0; i < 256; i++) // Set to 'unknown'. map[i] = -1; // Go through pixels. for (i = 0; i < count; i++) { unsigned char pix = *pixels; if (map[pix] == -1) // New one? map[pix] = Find_closest_color(newpal, oldpal[3*pix], oldpal[3*pix+1], oldpal[3*pix+2]); *pixels++ = map[pix]; } } /* * Import a PNG file into a given shape,frame. */ static void Import_png ( const char *fname, // Filename. Shape_file_info *finfo, // What we're updating. unsigned char *pal, // 3*255 bytes game palette. int shapenum, int framenum // Shape, frame to update ) { ExultStudio *studio = ExultStudio::get_instance(); Vga_file *ifile = finfo->get_ifile(); if (!ifile) return; // Shouldn't happen. Shape *shape = ifile->extract_shape(shapenum); if (!shape) return; int w, h, rowsize, xoff, yoff, palsize; unsigned char *pixels, *oldpal; // Import, with 255 = transp. index. if (!Import_png8(fname, 255, w, h, rowsize, xoff, yoff, pixels, oldpal, palsize)) return; // Just return if error, for now. // Convert to game palette. Convert_indexed_image(pixels, h*rowsize, oldpal, palsize, pal); delete oldpal; // Low shape in 'shapes.vga'? bool flat = shapenum < 0x96 && finfo == studio->get_vgafile(); int xleft, yabove; if (flat) { xleft = yabove = 8; if (w != 8 || h != 8 || rowsize != 8) { char *msg = g_strdup_printf( "Shape %d must be 8x8", shapenum); studio->prompt(msg, "Continue"); g_free(msg); delete pixels; return; } } else // RLE. xoff,yoff are neg. from bottom. { xleft = w + xoff - 1; yabove = h + yoff - 1; } shape->set_frame(new Shape_frame(pixels, w, h, xleft, yabove, !flat), framenum); delete pixels; finfo->set_modified(); } /* * Import a tiled PNG file into a given shape's frames. */ static void Import_png_tiles ( const char *fname, // Filename. Shape_file_info *finfo, // What we're updating. unsigned char *pal, // 3*255 bytes game palette. int shapenum, int tiles, // #tiles per row/col. bool bycols // Write tiles columns-first. ) { ExultStudio *studio = ExultStudio::get_instance(); Vga_file *ifile = finfo->get_ifile(); if (!ifile) return; // Shouldn't happen. Shape *shape = ifile->extract_shape(shapenum); if (!shape) return; int nframes = shape->get_num_frames(); cout << "Reading " << fname << " tiled" << (bycols ? ", by cols" : ", by rows") << " first" << endl; // Figure #tiles in other dim. int dim0_cnt = tiles; int dim1_cnt = (nframes + dim0_cnt - 1)/dim0_cnt; int needw, needh; // Figure min. image dims. if (bycols) { needh = dim0_cnt*8; needw = dim1_cnt*8; } else { needw = dim0_cnt*8; needh = dim1_cnt*8; } int w, h, rowsize, xoff, yoff, palsize; unsigned char *pixels, *oldpal; // Import, with 255 = transp. index. if (!Import_png8(fname, 255, w, h, rowsize, xoff, yoff, pixels, oldpal, palsize)) { Alert("Error reading '%s'", fname); return; } // Convert to game palette. Convert_indexed_image(pixels, h*rowsize, oldpal, palsize, pal); delete oldpal; if (w < needw || h < needh) { Alert("File '%s' image is too small. %dx%d required.", fname, needw, needh); return; } for (int frnum = 0; frnum < nframes; frnum++) { int x, y; if (bycols) { y = frnum%dim0_cnt; x = frnum/dim0_cnt; } else { x = frnum%dim0_cnt; y = frnum/dim0_cnt; } unsigned char *src = pixels + w*8*y + 8*x; unsigned char buf[8*8]; // Move tile to buffer. unsigned char *ptr = &buf[0]; for (int row = 0; row < 8; row++) { // Write it out. memcpy(ptr, src, 8); ptr += 8; src += w; } shape->set_frame(new Shape_frame(&buf[0], 8, 8, 8, 8, false), frnum); } delete pixels; finfo->set_modified(); } /* * Read in a shape that was changed by an external program (i.e., Gimp). */ void Shape_chooser::read_back_edited ( Editing_file *ed ) { ExultStudio *studio = ExultStudio::get_instance(); Shape_file_info *finfo = studio->open_shape_file( ed->vga_basename.c_str()); if (!finfo) return; unsigned char pal[3*256]; // Convert to 0-255 RGB's. unsigned char *palbuf = studio->get_palbuf(); for (int i = 0; i < 3*256; i++) pal[i] = palbuf[i]*4; if (!ed->tiles) Import_png(ed->pathname.c_str(), finfo, pal, ed->shapenum, ed->framenum); else Import_png_tiles(ed->pathname.c_str(), finfo, pal, ed->shapenum, ed->tiles, ed->bycolumns); } /* * Delete all the files being edited after doing a final check. */ void Shape_chooser::clear_editing_files ( ) { check_editing_files(); // Import any that changed. while (!editing_files.empty()) { Editing_file *ed = editing_files.back(); editing_files.pop_back(); unlink(ed->pathname.c_str()); delete ed; } if (check_editing_timer != -1) gtk_timeout_remove(check_editing_timer); check_editing_timer = -1; } /* * Export current frame. */ void Shape_chooser::export_frame ( char *fname, gpointer user_data ) { Shape_chooser *ed = (Shape_chooser *) user_data; if (U7exists(fname)) { char *msg = g_strdup_printf( "'%s' already exists. Overwrite?", fname); int answer = Prompt(msg, "Yes", "No"); g_free(msg); if (answer != 0) return; } if (ed->selected < 0) return; // Shouldn't happen. ed->export_png(fname); } /* * Import current frame. */ void Shape_chooser::import_frame ( char *fname, gpointer user_data ) { Shape_chooser *ed = (Shape_chooser *) user_data; if (ed->selected < 0) return; // Shouldn't happen. int shnum = ed->info[ed->selected].shapenum, frnum = ed->info[ed->selected].framenum; unsigned char pal[3*256]; // Get current palette. Get_rgb_palette(ed->palette, pal); Import_png(fname, ed->file_info, pal, shnum, frnum); ed->render(); ed->show(); ExultStudio *studio = ExultStudio::get_instance(); studio->update_group_windows(0); } /* * Add a frame. */ void Shape_chooser::new_frame ( ) { if (selected < 0) return; int shnum = info[selected].shapenum, frnum = info[selected].framenum; Vga_file *ifile = file_info->get_ifile(); // Read entire shape. Shape *shape = ifile->extract_shape(shnum); if (!shape || // Shouldn't happen. // We'll insert AFTER frnum. frnum > shape->get_num_frames()) return; // Low shape in 'shapes.vga'? ExultStudio *studio = ExultStudio::get_instance(); bool flat = shnum < 0x96 && file_info == studio->get_vgafile(); int w = 0, h = 0; int xleft, yabove; if (flat) w = h = xleft = yabove = 8; else // Find largest frame. { int cnt = shape->get_num_frames(); for (int i = 0; i < cnt; i++) { int ht = shape->get_frame(i)->get_height(); if (ht > h) h = ht; int wd = shape->get_frame(i)->get_width(); if (wd > w) w = wd; } if (h == 0) h = 8; if (w == 0) w = 8; xleft = w - 1; yabove = h - 1; } Image_buffer8 img(w, h); img.fill8(1); // Just use color #1. if (w > 2 && h > 2) img.fill8(2, w - 2, h - 2, 1, 1); Shape_frame *frame = new Shape_frame(img.get_bits(), w, h, xleft, yabove, !flat); shape->add_frame(frame, frnum + 1); file_info->set_modified(); Object_browser *browser = studio->get_browser(); if (browser) { // Repaint main window. browser->render(); browser->show(); } studio->update_group_windows(0); } /* * Callback for new-shape 'okay'. */ C_EXPORT void on_new_shape_okay_clicked (GtkButton *button, gpointer user_data) { GtkWidget *win = gtk_widget_get_toplevel(GTK_WIDGET(button)); Shape_chooser *chooser = (Shape_chooser *) gtk_object_get_user_data(GTK_OBJECT(win)); chooser->create_new_shape(); gtk_widget_hide(win); } // Toggled 'From font' button: C_EXPORT void on_new_shape_font_toggled ( GtkToggleButton *btn, gpointer user_data ) { bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); GtkWidget *win = gtk_widget_get_toplevel(GTK_WIDGET(btn)); Shape_chooser *chooser = (Shape_chooser *) gtk_object_get_user_data(GTK_OBJECT(win)); chooser->from_font_toggled(on); } C_EXPORT gboolean on_new_shape_font_color_draw_expose_event ( GtkWidget *widget, // The draw area. GdkEventExpose *event, gpointer data ) { ExultStudio *studio = ExultStudio::get_instance(); int index = studio->get_spin("new_shape_font_color"); Shape_chooser *ed = (Shape_chooser *) gtk_object_get_user_data(GTK_OBJECT(widget)); guint32 color = ed->get_color(index); GdkGC *gc = (GdkGC *) gtk_object_get_data(GTK_OBJECT(widget), "color_gc"); if (!gc) { gc = gdk_gc_new(widget->window); gtk_object_set_data(GTK_OBJECT(widget), "color_gc", gc); } gdk_rgb_gc_set_foreground(gc, color); gdk_draw_rectangle(widget->window, gc, TRUE, event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } C_EXPORT void on_new_shape_font_color_changed ( GtkSpinButton *button, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); // Show new color. GtkWidget *draw = glade_xml_get_widget(studio->get_xml(), "new_shape_font_color_draw"); GdkRectangle area = {0, 0, draw->allocation.width, draw->allocation.height}; gtk_widget_draw(draw, &area); } /* * Font file was selected. */ static void font_file_chosen ( const char *fname, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); studio->set_entry("new_shape_font_name", fname); studio->set_spin("new_shape_nframes", 128); } /* * 'From font' toggled in 'New shape' dialog. */ void Shape_chooser::from_font_toggled ( bool on ) { ExultStudio *studio = ExultStudio::get_instance(); studio->set_sensitive("new_shape_font_name", on); if (!on) return; studio->set_sensitive("new_shape_font_color", true); studio->set_sensitive("new_shape_font_height", true); GtkFileSelection *fsel = Create_file_selection( "Choose font file", font_file_chosen, 0L); gtk_widget_show(GTK_WIDGET(fsel)); } /* * Add a new shape. */ void Shape_chooser::new_shape ( ) { ExultStudio *studio = ExultStudio::get_instance(); GladeXML *xml = studio->get_xml(); GtkWidget *win = glade_xml_get_widget(xml, "new_shape_window"); gtk_window_set_modal(GTK_WINDOW(win), true); gtk_object_set_user_data(GTK_OBJECT(win), this); // Get current selection. int shnum = selected >= 0 ? info[selected].shapenum : 0, frnum = selected >= 0 ? info[selected].framenum : 0; GtkWidget *spin = glade_xml_get_widget(xml, "new_shape_num"); GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(spin)); adj->upper = 2047; // Just a big number. gtk_adjustment_changed(adj); Vga_file *ifile = file_info->get_ifile(); int shstart; // Find an unused shape. for (shstart = shnum; shstart <= adj->upper; shstart++) if (shstart >= ifile->get_num_shapes() || !ifile->get_num_frames(shstart)) break; if (shstart > adj->upper) { for (shstart = shnum - 1; shstart >= 0; shstart--) if (!ifile->get_num_frames(shstart)) break; if (shstart < 0) shstart = shnum; } gtk_adjustment_set_value(adj, shstart); spin = glade_xml_get_widget(xml, "new_shape_nframes"); adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); bool flat = shnum < 0x96 && file_info == studio->get_vgafile(); if (flat) adj->upper = 31; else adj->upper = 255; gtk_adjustment_changed(adj); spin = glade_xml_get_widget(xml, "new_shape_font_height"); studio->set_sensitive("new_shape_font_height", false); adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); adj->lower = 4; adj->upper = 64; gtk_adjustment_changed(adj); spin = glade_xml_get_widget(xml, "new_shape_font_color"); studio->set_sensitive("new_shape_font_color", false); adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); adj->lower = 0; adj->upper = 255; gtk_adjustment_changed(adj); // Unset 'From font:'. studio->set_toggle("new_shape_font", false); #ifndef HAVE_FREETYPE2 /* No freetype? No fonts. */ studio->set_sensitive("new_shape_font", false); #endif // Store our pointer in color drawer. GtkWidget *draw = glade_xml_get_widget(xml, "new_shape_font_color_draw"); gtk_object_set_user_data(GTK_OBJECT(draw), this); gtk_widget_show(win); } /* * Add a new shape after the user has clicked 'Okay' in the new-shape * dialog. */ void Shape_chooser::create_new_shape ( ) { ExultStudio *studio = ExultStudio::get_instance(); int shnum = studio->get_spin("new_shape_num"); int nframes = studio->get_spin("new_shape_nframes"); if (nframes <= 0) nframes = 1; else if (nframes > 256) nframes = 256; Vga_file *ifile = file_info->get_ifile(); if (shnum < ifile->get_num_shapes() && ifile->get_num_frames(shnum)) { if (Prompt("Replace existing shape?", "Yes", "No") != 0) return; } Shape *shape = ifile->new_shape(shnum); if (!shape) { Alert("Can't create shape %d", shnum); return; } // Create frames. bool flat = shnum < 0x96 && file_info == studio->get_vgafile(); bool use_font = false; #ifdef HAVE_FREETYPE2 // Want to create from a font? use_font = studio->get_toggle("new_shape_font"); const char *fontname = studio->get_text_entry("new_shape_font_name"); use_font = use_font && (fontname != 0) && *fontname != 0; if (use_font) { if (flat) { Alert("Can't load font into a 'flat' shape"); return; } int ht = studio->get_spin("new_shape_font_height"); int fg = studio->get_spin("new_shape_font_color"); if (!Gen_font_shape(shape, fontname, nframes, // Use transparent color for bgnd. ht, fg, 255)) Alert("Error loading font file '%s'", fontname); } #endif if (!use_font) { int w = 8, h = 8; int xleft = flat ? 8 : w - 1; int yabove = flat ? 8 : h - 1; Image_buffer8 img(w, h); img.fill8(1); // Just use color #1. img.fill8(2, w - 2, h - 2, 1, 1); // Include some transparency. img.fill8(255, w/2, h/2, w/4, h/4); for (int i = 0; i < nframes; i++) shape->add_frame(new Shape_frame(img.get_bits(), w, h, xleft, yabove, !flat), i); } file_info->set_modified(); Object_browser *browser = studio->get_browser(); if (browser) { // Repaint main window. browser->render(); browser->show(); } studio->update_group_windows(0); } /* * Delete a frame, and the shape itself if this is its last. */ void Shape_chooser::del_frame ( ) { if (selected < 0) return; int shnum = info[selected].shapenum, frnum = info[selected].framenum; Vga_file *ifile = file_info->get_ifile(); // Read entire shape. Shape *shape = ifile->extract_shape(shnum); if (!shape || // Shouldn't happen. frnum > shape->get_num_frames() - 1) return; // 1-shape file & last frame? if (!ifile->is_flex() && shape->get_num_frames() == 1) return; shape->del_frame(frnum); file_info->set_modified(); ExultStudio *studio = ExultStudio::get_instance(); Object_browser *browser = studio->get_browser(); if (browser) { // Repaint main window. browser->render(); browser->show(); } studio->update_group_windows(0); } /* * Someone wants the dragged shape. */ void Shape_chooser::drag_data_get ( GtkWidget *widget, // The view window. GdkDragContext *context, GtkSelectionData *seldata, // Fill this in. guint info, guint time, gpointer data // ->Shape_chooser. ) { cout << "In DRAG_DATA_GET" << endl; Shape_chooser *chooser = (Shape_chooser *) data; if (chooser->selected < 0 || info != U7_TARGET_SHAPEID) return; // Not sure about this. guchar buf[30]; int file = chooser->ifile->get_u7drag_type(); if (file == U7_SHAPE_UNK) U7_SHAPE_SHAPES; // Just assume it's shapes.vga. Shape_entry& shinfo = chooser->info[chooser->selected]; int len = Store_u7_shapeid(buf, file, shinfo.shapenum, shinfo.framenum); cout << "Setting selection data (" << shinfo.shapenum << '/' << shinfo.framenum << ')' << endl; #ifdef WIN32 windragdata *wdata = (windragdata *)seldata; wdata->assign(info, len, buf); #else // Make us owner of xdndselection. gtk_selection_owner_set(widget, gdk_atom_intern("XdndSelection", 0), time); // Set data. gtk_selection_data_set(seldata, gdk_atom_intern(U7_TARGET_SHAPEID_NAME, 0), 8, buf, len); #endif } /* * Another app. has claimed the selection. */ gint Shape_chooser::selection_clear ( GtkWidget *widget, // The view window. GdkEventSelection *event, gpointer data // ->Shape_chooser. ) { // Shape_chooser *chooser = (Shape_chooser *) data; cout << "SELECTION_CLEAR" << endl; return TRUE; } /* * Beginning of a drag. */ gint Shape_chooser::drag_begin ( GtkWidget *widget, // The view window. GdkDragContext *context, gpointer data // ->Shape_chooser. ) { cout << "In DRAG_BEGIN" << endl; Shape_chooser *chooser = (Shape_chooser *) data; if (chooser->selected < 0) return FALSE; // ++++Display a halt bitmap. // Get ->shape. Shape_entry& shinfo = chooser->info[chooser->selected]; Shape_frame *shape = chooser->ifile->get_shape(shinfo.shapenum, shinfo.framenum); if (!shape) return FALSE; chooser->set_drag_icon(context, shape); // Set icon for dragging. return TRUE; } /* * Scroll to a new shape/frame. */ void Shape_chooser::scroll_vertical ( int newindex // Abs. index of row to show. ) { // Already know where this is? if (newindex < row_indices.size()) { index0 = row_indices[newindex]; row0 = newindex; } else { // Start with last known row. row0 = row_indices.size() - 1; int index = row_indices[row0]; while (row0 < newindex && (index = next_row(index)) >= 0) { index0 = index; row0++; row_indices.push_back(index); } } int total = get_count(); render(); show(); } /* * Adjust vertical scroll amounts. */ void Shape_chooser::adjust_vscrollbar ( ) { GtkAdjustment *adj = gtk_range_get_adjustment( GTK_RANGE(vscroll)); int known_rows = row_indices.size() - 1; float num_per_row = known_rows > 0 ? ((float) row_indices[known_rows])/known_rows : 1; // This may change for the group. adj->upper = 1 + get_count()/num_per_row; adj->step_increment = 1; adj->page_increment = nrows; adj->page_size = nrows; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); } /* * Adjust horizontal scroll amounts. */ void Shape_chooser::adjust_hscrollbar ( int newmax // New max., or -1 to leave alone. ) { GtkAdjustment *adj = gtk_range_get_adjustment( GTK_RANGE(hscroll)); if (newmax > 0) adj->upper = newmax; adj->page_increment = draw->allocation.width; adj->page_size = draw->allocation.width; if (adj->page_size > adj->upper) adj->upper = adj->page_size; gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); } /* * Handle a scrollbar event. */ void Shape_chooser::vscrolled // For vertical scrollbar. ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; cout << "Scrolled to " << adj->value << '\n'; gint newindex = (gint) adj->value; chooser->scroll_vertical(newindex); } void Shape_chooser::hscrolled // For horizontal scrollbar. ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; chooser->hoffset = (gint) adj->value; chooser->render_frames(); chooser->show(); } /* * Handle a change to the 'frame' spin button. */ void Shape_chooser::frame_changed ( GtkAdjustment *adj, // The adjustment. gpointer data // ->Shape_chooser. ) { Shape_chooser *chooser = (Shape_chooser *) data; gint newframe = (gint) adj->value; if (chooser->selected >= 0) { Shape_entry& shinfo = chooser->info[chooser->selected]; int nframes = chooser->ifile->get_num_frames(shinfo.shapenum); if (newframe >= nframes) // Just checking return; shinfo.framenum = newframe; if (chooser->frames_mode) // Get sel. frame in view. chooser->scroll_to_frame(); chooser->render(); chooser->show(); } } /* * 'All frames' toggled. */ void Shape_chooser::all_frames_toggled ( GtkToggleButton *btn, gpointer data ) { Shape_chooser *chooser = (Shape_chooser *) data; bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); chooser->frames_mode = on; if (on) // Frame => show horiz. scrollbar. gtk_widget_show(chooser->hscroll); else gtk_widget_hide(chooser->hscroll); chooser->row_indices.resize(1); // Start over with row info. chooser->row0 = 0; chooser->info_cnt = 0; // Make selection visible. int indx = chooser->selected >= 0 ? chooser->info[chooser->selected].index : chooser->index0; chooser->index0 = 0; chooser->goto_index(indx); // chooser->render(); // chooser->show(); } /* * Handle popup menu items. */ void Shape_chooser::on_shapes_popup_info_activate ( GtkMenuItem *item, gpointer udata ) { ((Shape_chooser *) udata)->edit_shape_info(); } void Shape_chooser::on_shapes_popup_edit_activate ( GtkMenuItem *item, gpointer udata ) { ((Shape_chooser *) udata)->edit_shape(); } void Shape_chooser::on_shapes_popup_edtiles_activate ( GtkMenuItem *item, gpointer udata ) { Shape_chooser *ch = (Shape_chooser *) udata; if (ch->selected < 0) return; // Shouldn't happen. ExultStudio *studio = ExultStudio::get_instance(); GladeXML *xml = studio->get_xml(); GtkWidget *win = glade_xml_get_widget(xml, "export_tiles_window"); gtk_window_set_modal(GTK_WINDOW(win), true); gtk_object_set_user_data(GTK_OBJECT(win), ch); // Get current selection. int shnum = ch->info[ch->selected].shapenum; Vga_file *ifile = ch->file_info->get_ifile(); int nframes = ifile->get_num_frames(shnum); GtkWidget *spin = glade_xml_get_widget(xml, "export_tiles_count"); GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(spin)); adj->lower = 1; adj->upper = nframes; gtk_adjustment_changed(adj); gtk_widget_show(win); } static void on_shapes_popup_import ( GtkMenuItem *item, gpointer udata ) { GtkFileSelection *fsel = Create_file_selection( "Import frame from a .png file", (File_sel_okay_fun) Shape_chooser::import_frame, udata); gtk_widget_show(GTK_WIDGET(fsel)); } static void on_shapes_popup_export ( GtkMenuItem *item, gpointer udata ) { GtkFileSelection *fsel = Create_file_selection( "Export frame to a .png file", (File_sel_okay_fun) Shape_chooser::export_frame, udata); gtk_widget_show(GTK_WIDGET(fsel)); } static void on_shapes_popup_new_frame ( GtkMenuItem *item, gpointer udata ) { ((Shape_chooser *) udata)->new_frame(); } static void on_shapes_popup_new_shape ( GtkMenuItem *item, gpointer udata ) { ((Shape_chooser *) udata)->new_shape(); } /* * Callback for edit-tiles 'okay'. */ C_EXPORT void on_export_tiles_okay_clicked (GtkButton *button, gpointer user_data) { GtkWidget *win = gtk_widget_get_toplevel(GTK_WIDGET(button)); Shape_chooser *chooser = (Shape_chooser *) gtk_object_get_user_data(GTK_OBJECT(win)); ExultStudio *studio = ExultStudio::get_instance(); int tiles = studio->get_spin("export_tiles_count"); bool bycol = studio->get_toggle("tiled_by_columns"); chooser->edit_shape(tiles, bycol); gtk_widget_hide(win); } /* * Handle a shape dropped on our draw area. */ void Shape_chooser::shape_dropped_here ( int file, // U7_SHAPE_SHAPES. int shape, int frame ) { // Got to be from same file type. if (ifile->get_u7drag_type() == file && group != 0) { // Add to group. group->add(shape); // Update all windows for this group. ExultStudio::get_instance()->update_group_windows(group); } } /* * Get # shapes we can display. */ int Shape_chooser::get_count ( ) { return group ? group->size() : ifile->get_num_shapes(); } /* * Search for an entry. */ void Shape_chooser::search ( const char *srch, // What to search for. int dir // 1 or -1. ) { if (!shapes_file) // Not 'shapes.vga'. return; // In future, maybe find shape #? int total = get_count(); if (!total) return; // Empty. ExultStudio *studio = ExultStudio::get_instance(); // Start with selection, or top. int start = selected >= 0 ? info[selected].index : index0; int i; start += dir; int stop = dir == -1 ? -1 : total; for (i = start; i != stop; i += dir) { int shnum = group ? (*group)[i] : i; char *nm = studio->get_shape_name(shnum); if (nm && search_name(nm, srch)) break; // Found it. } if (i == stop) return; // Not found. goto_index(i); int newsel; // Get new selection index. if (!frames_mode) // Easy if showing 1 shape/spot. newsel = i - row_indices[row0]; else { int shnum = group ? (*group)[i] : i; for (newsel = 0; newsel < info_cnt && info[newsel].shapenum != shnum; newsel++) ; } if (newsel >= 0 && newsel < info_cnt) select(newsel); show(); } /* * Locate shape on game map. */ void Shape_chooser::locate ( bool upwards ) { if (selected < 0) return; // Shouldn't happen. unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Write2(ptr, info[selected].shapenum); *ptr++ = upwards ? 1 : 0; ExultStudio *studio = ExultStudio::get_instance(); studio->send_to_server( Exult_server::locate_shape, data, ptr - data); } /* * Set up popup menu for shape browser. */ GtkWidget *Shape_chooser::create_popup ( ) { ExultStudio *studio = ExultStudio::get_instance(); Object_browser::create_popup(); // Create popup with groups, files. if (selected >= 0) // Add editing choices. { Add_menu_item(popup, "Info...", GTK_SIGNAL_FUNC(on_shapes_popup_info_activate), this); if (studio->get_image_editor()) { Add_menu_item(popup, "Edit...", GTK_SIGNAL_FUNC(on_shapes_popup_edit_activate), this); if (info[selected].shapenum < 0x96 && file_info == studio->get_vgafile()) Add_menu_item(popup, "Edit tiled...", GTK_SIGNAL_FUNC( on_shapes_popup_edtiles_activate), this); } // Separator. Add_menu_item(popup); // Add/del. Add_menu_item(popup, "New frame", GTK_SIGNAL_FUNC(on_shapes_popup_new_frame), this); // Export/import. Add_menu_item(popup, "Export frame...", GTK_SIGNAL_FUNC(on_shapes_popup_export), this); Add_menu_item(popup, "Import frame...", GTK_SIGNAL_FUNC(on_shapes_popup_import), this); } if (ifile->is_flex()) // Multiple-shapes file (.vga)? { // Separator. Add_menu_item(popup); Add_menu_item(popup, "New shape", GTK_SIGNAL_FUNC(on_shapes_popup_new_shape), this); } return popup; } /* * Create the list. */ Shape_chooser::Shape_chooser ( Vga_file *i, // Where they're kept. unsigned char *palbuf, // Palette, 3*256 bytes (rgb triples). int w, int h, // Dimensions. Shape_group *g, Shape_file_info *fi ) : Object_browser(g, fi), Shape_draw(i, palbuf, gtk_drawing_area_new()), shapes_file(0), framenum0(0), info(0), info_cnt(0), row0(0), nrows(0), sel_changed(0), frames_mode(false), hoffset(0) { row_indices.reserve(40); row_indices.push_back(0); // First row is 0. // Put things in a vert. box. GtkWidget *vbox = gtk_vbox_new(FALSE, 0); set_widget(vbox); // This is our "widget" gtk_widget_show(vbox); GtkWidget *hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); // A frame looks nice. GtkWidget *frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); // NOTE: draw is in Shape_draw. // Indicate the events we want. gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_KEY_PRESS_MASK); // Set "configure" handler. gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(Configure_chooser), this); // Set "expose" handler. gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), this); // Keystroke. gtk_signal_connect(GTK_OBJECT(draw), "key-press-event", GTK_SIGNAL_FUNC (on_draw_key_press), this); GTK_WIDGET_SET_FLAGS(draw, GTK_CAN_FOCUS); // Set mouse click handler. gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(Mouse_press), this); gtk_signal_connect(GTK_OBJECT(draw), "button_release_event", GTK_SIGNAL_FUNC(Mouse_release), this); // Mouse motion. gtk_signal_connect(GTK_OBJECT(draw), "drag_begin", GTK_SIGNAL_FUNC(drag_begin), this); #ifdef WIN32 // required to override GTK+ Drag and Drop gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(win32_drag_motion), this); #else gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(drag_motion), this); #endif // gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", // GTK_SIGNAL_FUNC(Mouse_drag_motion), this); gtk_signal_connect (GTK_OBJECT(draw), "drag_data_get", GTK_SIGNAL_FUNC(drag_data_get), this); gtk_signal_connect (GTK_OBJECT(draw), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear), this); gtk_container_add (GTK_CONTAINER (frame), draw); gtk_drawing_area_size(GTK_DRAWING_AREA(draw), w, h); gtk_widget_show(draw); // Want vert. scrollbar for the shapes. GtkObject *shape_adj = gtk_adjustment_new(0, 0, get_count()/4, 1, 1, 1); vscroll = gtk_vscrollbar_new(GTK_ADJUSTMENT(shape_adj)); // Update window when it stops. gtk_range_set_update_policy(GTK_RANGE(vscroll), GTK_UPDATE_DELAYED); gtk_box_pack_start(GTK_BOX(hbox), vscroll, FALSE, TRUE, 0); // Set scrollbar handler. gtk_signal_connect(GTK_OBJECT(shape_adj), "value_changed", GTK_SIGNAL_FUNC(vscrolled), this); gtk_widget_show(vscroll); // Horizontal scrollbar. shape_adj = gtk_adjustment_new(0, 0, 1600, 8, 16, 16); hscroll = gtk_hscrollbar_new(GTK_ADJUSTMENT(shape_adj)); // Update window when it stops. gtk_range_set_update_policy(GTK_RANGE(hscroll), GTK_UPDATE_DELAYED); gtk_box_pack_start(GTK_BOX(vbox), hscroll, FALSE, TRUE, 0); // Set scrollbar handler. gtk_signal_connect(GTK_OBJECT(shape_adj), "value_changed", GTK_SIGNAL_FUNC(hscrolled), this); //++++ gtk_widget_hide(hscroll); // Only shown in 'frames' mode. // At the bottom, status bar & frame: GtkWidget *hbox1 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0); gtk_widget_show(hbox1); // At left, a status bar. sbar = gtk_statusbar_new(); sbar_sel = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "selection"); gtk_box_pack_start(GTK_BOX(hbox1), sbar, TRUE, TRUE, 0); gtk_widget_show(sbar); GtkWidget *label = gtk_label_new("Frame:"); gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 4); gtk_widget_show(label); // A spin button for frame#. frame_adj = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 16, 1, 4, 1.0)); fspin = gtk_spin_button_new(GTK_ADJUSTMENT(frame_adj), 1, 0); gtk_signal_connect(GTK_OBJECT(frame_adj), "value_changed", GTK_SIGNAL_FUNC(frame_changed), this); gtk_box_pack_start(GTK_BOX(hbox1), fspin, FALSE, FALSE, 0); gtk_widget_show(fspin); // A toggle for 'All Frames'. GtkWidget *allframes = gtk_toggle_button_new_with_label("Frames"); gtk_box_pack_start(GTK_BOX(hbox1), allframes, FALSE, FALSE, 4); gtk_widget_show(allframes); gtk_signal_connect(GTK_OBJECT(allframes), "toggled", GTK_SIGNAL_FUNC(all_frames_toggled), this); // Add search controls to bottom. gtk_box_pack_start(GTK_BOX(vbox), create_controls(find_controls | locate_controls), FALSE, FALSE, 0); } /* * Delete. */ Shape_chooser::~Shape_chooser ( ) { gtk_widget_destroy(get_widget()); delete [] info; } /* * Unselect. */ void Shape_chooser::unselect ( bool need_render // 1 to render and show. ) { if (selected >= 0) { selected = -1; // Update spin button for frame #. gtk_adjustment_set_value(frame_adj, 0); gtk_widget_set_sensitive(fspin, false); if (need_render) { render(); show(); } if (sel_changed) // Tell client. (*sel_changed)(); } char buf[150]; // Show new selection. if (info_cnt > 0) { // gtk_statusbar_pop(GTK_STATUSBAR(sbar), sbar_sel); g_snprintf(buf, sizeof(buf), "Shapes %d to %d", info[0].shapenum, info[info_cnt - 1].shapenum); gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf); } } exult-1.2/mapedit/logo.xpm0000644000175000001440000000432407452541525011317 /* XPM */ static char * logo_xpm[] = { "33 52 19 1", " c None", ". c #000000", "+ c #180800", "@ c #DC1428", "# c #B08010", "$ c #341800", "% c #FC1C34", "& c #FC00F1", "* c #FC7880", "= c #C49418", "- c #FCB8B8", "; c #FCD8D8", "> c #FC989C", ", c #FC384C", "' c #FC5864", ") c #FCECD8", "! c #6C3400", "~ c #502400", "{ c #F8FCFC", " ... ", " +@#@@@@+ ", " $@%&**&%@$ ", " +#=--;--->%$ ", " @*>-----;-->,$ ", " @#-;->*'=-;;-=)$ ", " &>;;-*%@%&--;-*$. ", " $,-;->,$..!*-;->@$ ", " #=;;>&@. @>---#$. ", " .'-;-=%$. +&--;*@. ", " +*-;-*@. .@*-;>%+ ", " $>;;;'!. @&-;-,$ ", " $>;;-,@ !&;;-,$ ", " +*-;-#@ !';;-,$ ", " .,-;-#@ !*;;-#$ ", " ,>;-#@ @*;;>@. ", " )*;;'@. @=;;'!. ", " !&;;*@. .%>;-#$ ", " $&-;=@. .,-->@$ ", " >-;>%$ +*--'$. ", " ),;-*@. $#--=@+. ", " #=--'$++@---,$. ", " #-;-,!@&;-*%+ ", "$$@@@@@@@@@>;;-'=;-=,@@@@@@@@!$..", "$@*=======>------;-->>>>>>>>*#$..", " @#>----->===>-;;->=>-------*@+. ", " +,>->=',%%#&--->,##&*=>>->#$. ", " .@'=,@!$+.+@---=@+++$!@,',!. ", " $!@$ +@-;-=~ $$@$$ ", " $$. +@-;-=$ .$+ ", " $@-;-=$ ", " $@-;;=$ ", " $@-;;=! ", " $@;;;>@ ", " $);;;>@ ", " $%;;;>@ ", " @#;;;>@ ", " @,;;;>@ ", " %&{;;-% ", " #'{;;-#+. ", " .@>{;;-'$. ", " .%-;;;;>@+ ", " $&;;;;;-@$ ", " )={;;;;;,$. ", " .&-;{{{;;*@+ ", " .,-;{{{;;'@+ ", " .@*-;{;-*%$+ ", " .!';;;*@+. ", " +@>;-#+ ", " $%>'@. ", " +%@+ ", " .$+. "}; exult-1.2/mapedit/shapegroup.cc0000644000175000001440000004315607664343445012331 /** ** A group of shapes/chunks that can be used as a 'palette'. ** ** Written: 1/22/02 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "shapegroup.h" #include "Flex.h" #include "utils.h" #include "exceptions.h" #include "studio.h" #include "objbrowse.h" #include "shapefile.h" using std::vector; using std::ios; using std::string; using std::cout; using std::endl; using EStudio::Alert; /* * Create an empty group. */ Shape_group::Shape_group ( const char *nm, // Name. Copied. Shape_group_file *f ) : name(nm), file(f) { } /* * Remove i'th entry. */ void Shape_group::del ( int i ) { assert(i >= 0 && i < size()); std::vector::erase(begin() + i); file->modified = true; } /* * Swap two entries. */ void Shape_group::swap ( int i // Lower one. ) { int x0 = (*this)[i]; (*this)[i] = (*this)[i + 1]; (*this)[i + 1] = x0; file->modified = true; } /* * Add a new entry if not already there. */ void Shape_group::add ( int id ) { for (vector::const_iterator it = begin(); it != end(); ++it) if ((*it) == id) return; // Already there. push_back(id); file->modified = true; } /* * Init. and read in (if it exists) a groups file. */ Shape_group_file::Shape_group_file ( const char *nm // Basename. ) : name(nm), modified(false) { Flex *flex = 0; std::string patchname = "/" + name; std::string staticname = "/" + name; if (U7exists(patchname)) // First try 'patch' directory. flex = new Flex(patchname); else if (U7exists(staticname)) flex = new Flex(staticname); if (flex) // Exists? { int cnt = flex->number_of_objects(); for (int i = 0; i < cnt; i++) { // Get each group. std::size_t len; char *buf = flex->retrieve(i, len); char *gname = buf; // Starts with name. unsigned char *ptr = (unsigned char *) gname + strlen(gname) + 1; int sz = Read2(ptr); // Get # entries. assert ((len - ((char *) ptr - buf))/2 == sz); Shape_group *grp = new Shape_group(gname, this); grp->reserve(sz); for (int j = 0; j < sz; j++) grp->push_back(Read2(ptr)); groups.push_back(grp); delete buf; } delete flex; } } /* * Search for a group with a given name. * * Output: Index if found, else -1. */ int Shape_group_file::find ( const char *nm ) { for (vector::const_iterator it = groups.begin(); it != groups.end(); ++it) if ((*it)->name == nm) return (it - groups.begin()); return -1; } /* * Clean up. */ Shape_group_file::~Shape_group_file ( ) { for (vector::iterator it = groups.begin(); it != groups.end(); ++it) delete (*it); // Delete each group. } /* * Remove and delete a group. */ void Shape_group_file::remove ( int index, bool del // True to delete the group. ) { modified = true; assert(index >= 0 && index < groups.size()); Shape_group *grp = groups[index]; groups.erase(groups.begin() + index); if (del) delete grp; } /* * Write out to the 'patch' directory. */ void Shape_group_file::write ( ) { std::ofstream out; std::string patchname = "/" + name; U7open(out, patchname.c_str()); int cnt = groups.size(); // # groups. Flex_writer gfile(out, "ExultStudio shape groups", cnt); int i; // Write each group. for (i = 0; i < cnt; i++) { Shape_group *grp = groups[i]; const char *nm = grp->get_name(); int sz = grp->size(); // Name, #entries, entries(2-bytes). long len = strlen(nm) + 1 + 2 + 2*sz; unsigned char *buf = new unsigned char[len]; strcpy((char *) buf, nm); unsigned char *ptr = buf + strlen(nm) + 1; Write2(ptr, sz); // # entries. for (vector::iterator it = grp->begin(); it != grp->end(); it++) Write2(ptr, *it); assert(ptr - buf == len); // Write out to file. out.write(reinterpret_cast(buf), len); delete buf; gfile.mark_section_done(); } if (!gfile.close()) Alert("Error writing '%s'", patchname.c_str()); modified = false; } /* * Get the tree row # (assuming just a simple list) for a given tree- * model position. */ static int Get_tree_row ( GtkTreePath *path ) { gchar *str = gtk_tree_path_to_string(path); int row = atoi(str); g_free(str); return row; } static int Get_tree_row ( GtkTreeModel *model, GtkTreeIter *iter // Position we want. ) { GtkTreePath *path = gtk_tree_model_get_path(model, iter); int row = Get_tree_row(path); gtk_tree_path_free(path); return row; } /* * Group buttons: */ C_EXPORT void on_groups_add_clicked (GtkToggleButton *button, gpointer user_data) { ExultStudio::get_instance()->add_group(); } C_EXPORT void on_groups_del_clicked (GtkToggleButton *button, gpointer user_data) { ExultStudio::get_instance()->del_group(); } C_EXPORT gboolean on_groups_new_name_key_press (GtkEntry *entry, GdkEventKey *event, gpointer user_data) { if (event->keyval == GDK_Return) { ExultStudio::get_instance()->add_group(); return TRUE; } return FALSE; // Let parent handle it. } /* * Groups list signals: */ C_EXPORT void on_group_list_cursor_changed (GtkTreeView *tview) { ExultStudio::get_instance()->setup_group_controls(); } void on_group_list_row_inserted (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { ExultStudio::get_instance()->groups_changed(model, path, iter); } void on_group_list_row_changed (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { ExultStudio::get_instance()->groups_changed(model, path, iter, true); } void on_group_list_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer user_data) { ExultStudio::get_instance()->groups_changed(model, path, 0); } C_EXPORT void on_group_list_row_activated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { ExultStudio::get_instance()->open_group_window(); } /* columns */ enum { GRP_FILE_COLUMN = 0, GRP_GROUP_COLUMN, GRP_NUM_COLUMNS }; /* * Initialize the list of shape groups for the file being shown in the * browser. */ void ExultStudio::setup_groups ( ) { Shape_group_file *groups = curfile->get_groups(); if (!groups) // No groups? { set_visible("groups_frame", FALSE); return; } GtkTreeView *tview = GTK_TREE_VIEW( glade_xml_get_widget(app_xml, "group_list")); GtkTreeModel *oldmod = gtk_tree_view_get_model(tview); GtkTreeStore *model; gulong addsig = 0, delsig = 0, chgsig = 0; if (!oldmod) // Create model first time. { model = gtk_tree_store_new(GRP_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER); gtk_tree_view_set_model(tview, GTK_TREE_MODEL(model)); g_object_unref(model); // Create column. GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); g_object_set (renderer, "xalign", 0.0, NULL); gint col_offset = gtk_tree_view_insert_column_with_attributes( tview, -1, "Names", renderer, "text", GRP_FILE_COLUMN, NULL); GtkTreeViewColumn *column = gtk_tree_view_get_column(tview, col_offset - 1); gtk_tree_view_column_set_clickable(column, TRUE); addsig = g_signal_connect(G_OBJECT(model), "row-inserted", GTK_SIGNAL_FUNC(on_group_list_row_inserted), this); // Store signal id with model. g_object_set_data(G_OBJECT(model), "row-inserted", (gpointer) addsig); delsig = g_signal_connect(G_OBJECT(model), "row-deleted", GTK_SIGNAL_FUNC(on_group_list_row_deleted), this); g_object_set_data(G_OBJECT(model), "row-deleted", (gpointer) delsig); chgsig = g_signal_connect(G_OBJECT(model), "row-changed", GTK_SIGNAL_FUNC(on_group_list_row_changed), this); g_object_set_data(G_OBJECT(model), "row-changed", (gpointer) delsig); } else { model = GTK_TREE_STORE(oldmod); addsig = (gulong) g_object_get_data(G_OBJECT(model), "row-inserted"); delsig = (gulong) g_object_get_data(G_OBJECT(model), "row-deleted"); chgsig = (gulong) g_object_get_data(G_OBJECT(model), "row-changed"); } // Block this signal during creation. g_signal_handler_block(model, addsig); g_signal_handler_block(model, delsig); g_signal_handler_block(model, chgsig); gtk_tree_store_clear(model); set_visible("groups_frame", TRUE); gtk_tree_view_set_reorderable(tview, TRUE); int cnt = groups->size(); // Add groups from file. GtkTreeIter iter; for (int i = 0; i < cnt; i++) { Shape_group *grp = groups->get(i); gtk_tree_store_append(model, &iter, NULL); gtk_tree_store_set(model, &iter, GRP_FILE_COLUMN, grp->get_name(), GRP_GROUP_COLUMN, grp, -1); } gtk_tree_view_set_rules_hint(tview, TRUE); g_signal_handler_unblock(model, addsig); g_signal_handler_unblock(model, delsig); g_signal_handler_unblock(model, chgsig); setup_group_controls(); // Enable/disable the controls. } /* * Enable/disable the controls based on whether there's a selection. */ void ExultStudio::setup_group_controls ( ) { set_visible("groups_frame", true); GtkTreeView *tview = GTK_TREE_VIEW( glade_xml_get_widget(app_xml, "group_list")); GtkTreeSelection *list = gtk_tree_view_get_selection(tview); if (list) { // int row = (int) list->data; // set_sensitive("groups_open", true); set_sensitive("groups_del", true); // set_sensitive("groups_up_arrow", row > 0); // set_sensitive("groups_down_arrow", row < clist->rows); } else { // set_sensitive("groups_open", false); set_sensitive("groups_del", false); // set_sensitive("groups_up_arrow", false); // set_sensitive("groups_down_arrow", false); } } /* * Add/delete a new group. */ void ExultStudio::add_group ( ) { if (!curfile) return; GtkTreeView *tview = GTK_TREE_VIEW( glade_xml_get_widget(app_xml, "group_list")); GtkTreeStore *model = GTK_TREE_STORE(gtk_tree_view_get_model(tview)); const char *nm = get_text_entry("groups_new_name"); Shape_group_file *groups = curfile->get_groups(); // Make sure name isn't already there. if (nm && *nm && groups->find(nm) < 0) { Shape_group *grp = new Shape_group(nm, groups); GtkTreeIter iter; gtk_tree_store_append(model, &iter, NULL); gtk_tree_store_set(model, &iter, GRP_FILE_COLUMN, nm, GRP_GROUP_COLUMN, grp, -1); } set_entry("groups_new_name", ""); } void ExultStudio::del_group ( ) { if (!curfile) return; GtkTreeView *tview = GTK_TREE_VIEW( glade_xml_get_widget(app_xml, "group_list")); GtkTreeSelection *list = gtk_tree_view_get_selection(tview); if (!list) return; GtkTreeModel *model; GtkTreeIter iter; if (!gtk_tree_selection_get_selected(list, &model, &iter)) return; int row = Get_tree_row(model, &iter); Shape_group_file *groups = curfile->get_groups(); Shape_group *grp = groups->get(row); string msg("Delete group '"); msg += grp->get_name(); msg += "'?"; int choice = prompt(msg.c_str(), "Yes", "No"); if (choice != 0) // Yes? return; delete groups->get(row); // Delete the group. gtk_tree_store_remove(GTK_TREE_STORE(model), &iter); // Close the group's windows. vector toclose; vector::const_iterator it; for (it = group_windows.begin(); it != group_windows.end(); ++it) { Object_browser *chooser = (Object_browser *) gtk_object_get_data(GTK_OBJECT(*it), "browser"); if (chooser->get_group() == grp) // A match? toclose.push_back(*it); } for (it = toclose.begin(); it != toclose.end(); ++it) close_group_window(GTK_WIDGET(*it)); } /* * A group has been inserted or deleted from the list. */ void ExultStudio::groups_changed ( GtkTreeModel *model, GtkTreePath *path, // Position. GtkTreeIter *loc, // Insert/change location, or 0. bool value // True if value changed at loc. ) { if (!curfile) return; Shape_group_file *groups = curfile->get_groups(); int row = Get_tree_row(path); if (!loc) groups->remove(row, false); else { void *grpaddr = 0; gtk_tree_model_get(model, loc, GRP_GROUP_COLUMN, &grpaddr, -1); Shape_group *grp = (Shape_group *) grpaddr; if (value) // Changed? groups->set(grp, row); else groups->insert(grp, row); } } /* * Events on 'group' window: */ /* * Npc window's close button. */ C_EXPORT gboolean on_group_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_group_window(widget); return TRUE; } C_EXPORT void on_group_up_clicked (GtkToggleButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *)gtk_object_get_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), "browser"); Shape_group *grp = chooser->get_group(); int i = chooser->get_selected(); if (grp && i > 0) // Moving item up. { grp->swap(i - 1); ExultStudio::get_instance()->update_group_windows(grp); } } C_EXPORT void on_group_down_clicked (GtkToggleButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *)gtk_object_get_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), "browser"); Shape_group *grp = chooser->get_group(); int i = chooser->get_selected(); if (grp && i < grp->size() - 1) // Moving down. { grp->swap(i); ExultStudio::get_instance()->update_group_windows(grp); } } C_EXPORT void on_group_shape_remove_clicked (GtkToggleButton *button, gpointer user_data) { Object_browser *chooser = (Object_browser *)gtk_object_get_data( GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), "browser"); Shape_group *grp = chooser->get_group(); int i = chooser->get_selected(); if (grp && i >= 0) { grp->del(i); ExultStudio::get_instance()->update_group_windows(grp); } } /* * Open a 'group' window for the currently selected group. */ void ExultStudio::open_group_window ( ) { GtkTreeView *tview = GTK_TREE_VIEW( glade_xml_get_widget(app_xml, "group_list")); GtkTreeSelection *list = gtk_tree_view_get_selection(tview); if (!list || !curfile || !vgafile || !palbuf) return; GtkTreeModel *model; GtkTreeIter iter; if (!gtk_tree_selection_get_selected(list, &model, &iter)) return; int row = Get_tree_row(model, &iter); Shape_group_file *groups = curfile->get_groups(); Shape_group *grp = groups->get(row); GladeXML *xml = glade_xml_new(glade_path, "group_window", NULL); glade_xml_signal_autoconnect(xml); GtkWidget *grpwin = glade_xml_get_widget(xml, "group_window"); Object_browser *chooser = curfile->create_browser(vgafile,palbuf, grp); // Set xml as data on window. gtk_object_set_data(GTK_OBJECT(grpwin), "xml", xml); gtk_object_set_data(GTK_OBJECT(grpwin), "browser", chooser); // Set window title, name field. string title("Exult Group: "); title += grp->get_name(); gtk_window_set_title(GTK_WINDOW(grpwin), title.c_str()); GtkWidget *field = glade_xml_get_widget(xml, "group_name"); if (field) gtk_entry_set_text(GTK_ENTRY(field), grp->get_name()); // Attach browser. GtkWidget *browser_box = glade_xml_get_widget(xml, "group_shapes" ); gtk_widget_show(browser_box); gtk_box_pack_start(GTK_BOX(browser_box), chooser->get_widget(), TRUE, TRUE, 0); // Auto-connect doesn't seem to work. gtk_signal_connect (GTK_OBJECT(grpwin), "delete_event", GTK_SIGNAL_FUNC (on_group_window_delete_event), this); group_windows.push_back(GTK_WINDOW(grpwin)); gtk_widget_show(grpwin); } /* * Close a 'group' window. */ void ExultStudio::close_group_window ( GtkWidget *grpwin ) { // Remove from list. for (vector::iterator it = group_windows.begin(); it != group_windows.end(); ++it) { if (*it == GTK_WINDOW(grpwin)) { group_windows.erase(it); break; } } GladeXML *xml = (GladeXML *) gtk_object_get_data(GTK_OBJECT(grpwin), "xml"); Object_browser *chooser = (Object_browser *) gtk_object_get_data( GTK_OBJECT(grpwin), "browser"); delete chooser; gtk_widget_destroy(grpwin); g_object_unref(G_OBJECT(xml)); } /* * Save all modified group files. */ void ExultStudio::save_groups ( ) { if (!files) return; int cnt = files->size(); for (int i = 0; i < cnt; i++) // Check each file. { Shape_file_info *info = (*files)[i]; Shape_group_file *gfile = info->get_groups(); if (gfile && gfile->is_modified()) gfile->write(); } } /* * Return TRUE if any groups have been modified. */ bool ExultStudio::groups_modified ( ) { if (!files) return false; int cnt = files->size(); for (int i = 0; i < cnt; i++) // Check each file. { Shape_file_info *info = (*files)[i]; Shape_group_file *gfile = info->get_groups(); if (gfile && gfile->is_modified()) return true; } return false; } /* * Update all windows showing a given group. */ void ExultStudio::update_group_windows ( Shape_group *grp // Group, or 0 for all. ) { for (vector::const_iterator it = group_windows.begin(); it != group_windows.end(); ++it) { Object_browser *chooser = (Object_browser *) gtk_object_get_data(GTK_OBJECT(*it), "browser"); if (!grp || chooser->get_group() == grp) { // A match? chooser->render(); chooser->show(); } } } exult-1.2/mapedit/chunklst.h0000644000175000001440000001202107762470521011627 /** ** A GTK widget showing the chunks from 'u7chunks'. ** ** Written: 7/8/01 - JSF **/ #ifndef INCL_CHUNKLST #define INCL_CHUNKLST 1 /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "objbrowse.h" #include "rect.h" #include "shapedraw.h" class Image_buffer8; class Shape_group; #include /* * Store information about an individual chunk shown in the list. */ class Chunk_info { friend class Chunk_chooser; int num; Rectangle box; // Box where drawn. Chunk_info() { } void set(int n, int rx, int ry, int rw, int rh) { num = n; box = Rectangle(rx, ry, rw, rh); } }; /* * This class manages the list of chunks. */ class Chunk_chooser: public Object_browser, public Shape_draw { std::istream& chunkfile; // Where chunks are read from (each is // 256 shape ID's = 512 bytes). GtkWidget *sbar; // Status bar. guint sbar_sel; // Status bar context for selection. int num_chunks; // Total # of chunks. // List of chunks we've read in. std::vector chunklist; Chunk_info *info; // An entry for each chunk drawn. int info_cnt; // # entries in info. int locate_cx, locate_cy; // Last chunk found by 'locate'. bool drop_enabled; // So we only do it once. int to_del; // Terrain # to delete, or -1. void (*sel_changed)(); // Called when selection changes. // Blit onto screen. virtual void show(int x, int y, int w, int h); virtual void show() { Chunk_chooser::show(0, 0, draw->allocation.width, draw->allocation.height);} void tell_server(); void select(int new_sel); // Show new selection. virtual void render(); // Draw list. virtual void set_background_color(guint32 c) { Shape_draw::set_background_color(c); } virtual int get_selected_id() { return selected < 0 ? -1 : info[selected].num; } unsigned char *get_chunk(int chunknum); void update_num_chunks(int new_num_chunks); void set_chunk(unsigned char *data, int datalen); void render_chunk(int chunknum, int xoff, int yoff); void scroll(int newindex); // Scroll. void scroll(bool upwards); void enable_controls(); // Enable/disable controls after sel. // has changed. virtual GtkWidget *create_popup(); // Popup menu. public: Chunk_chooser(Vga_file *i, std::istream& cfile, unsigned char *palbuf, int w, int h, Shape_group *g = 0); virtual ~Chunk_chooser(); virtual bool server_response(int id, unsigned char *data, int datalen); virtual void end_terrain_editing(); // Turn off selection. void unselect(bool need_render = true); int is_selected() // Is a chunk selected? { return selected >= 0; } void set_selected_callback(void (*fun)()) { sel_changed = fun; } int get_count(); // Get # chunks we can display. // Configure when created/resized. static gint configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data); // Blit to screen. static gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); // Handle mouse press. static gint mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data); // Give dragged chunk. static void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, gpointer data); // Someone else selected. static gint selection_clear(GtkWidget *widget, GdkEventSelection *event, gpointer data); static gint drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); // Handler for drop. static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer udata); void enable_drop(); // Handle scrollbar. static void scrolled(GtkAdjustment *adj, gpointer data); void locate(int dir); // Locate terrain on game map. virtual void locate(bool upwards); void locate_response(unsigned char *data, int datalen); void insert(bool dup); // Insert new chunk. void del(); // Delete current chunk. void insert_response(unsigned char *data, int datalen); void delete_response(unsigned char *data, int datalen); virtual void move(bool upwards); // Move current selected chunk. void swap_response(unsigned char *data, int datalen); #ifdef WIN32 static gint win32_drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #else static gint drag_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); #endif }; #endif exult-1.2/mapedit/u7shp.c0000644000175000001440000005645010054030563011035 /* * SHP loading file filter for The GIMP version 1.2.x and 1.3.11+ * * (C) 2000-2001 Tristan Tarrant * (C) 2001-2004 Willem Jan Palenstijn * * You can find the most recent version of this file in the Exult sources, * available from http://exult.sf.net/ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #ifdef HAVE_GIMP_1_2 #define GIMP20_CONST #else #define GIMP20_CONST const #endif /* Declare some local functions. */ static void query (void); static void run (GIMP20_CONST gchar *name, gint nparams, GIMP20_CONST GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); static void load_palette(gchar *filename); static void choose_palette (void); static gint32 load_image (gchar *filename); static gint32 save_image (gchar *filename, gint32 image_ID, gint32 drawable_ID, gint32 orig_image_ID); #ifdef HAVE_GIMP_1_2 static GimpRunModeType run_mode; #else static GimpRunMode run_mode; #endif static guchar gimp_cmap[768] = { 0x00, 0x00, 0x00, 0xF8, 0xF0, 0xCC, 0xF4, 0xE4, 0xA4, 0xF0, 0xDC, 0x78, 0xEC, 0xD0, 0x50, 0xEC, 0xC8, 0x28, 0xD8, 0xAC, 0x20, 0xC4, 0x94, 0x18, 0xB0, 0x80, 0x10, 0x9C, 0x68, 0x0C, 0x88, 0x54, 0x08, 0x74, 0x44, 0x04, 0x60, 0x30, 0x00, 0x4C, 0x24, 0x00, 0x38, 0x14, 0x00, 0xF8, 0xFC, 0xFC, 0xFC, 0xD8, 0xD8, 0xFC, 0xB8, 0xB8, 0xFC, 0x98, 0x9C, 0xFC, 0x78, 0x80, 0xFC, 0x58, 0x64, 0xFC, 0x38, 0x4C, 0xFC, 0x1C, 0x34, 0xDC, 0x14, 0x28, 0xC0, 0x0C, 0x1C, 0xA4, 0x08, 0x14, 0x88, 0x04, 0x0C, 0x6C, 0x00, 0x04, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x18, 0x00, 0x00, 0xFC, 0xEC, 0xD8, 0xFC, 0xDC, 0xB8, 0xFC, 0xCC, 0x98, 0xFC, 0xBC, 0x7C, 0xFC, 0xAC, 0x5C, 0xFC, 0x9C, 0x3C, 0xFC, 0x8C, 0x1C, 0xFC, 0x7C, 0x00, 0xE0, 0x6C, 0x00, 0xC0, 0x60, 0x00, 0xA4, 0x50, 0x00, 0x88, 0x44, 0x00, 0x6C, 0x34, 0x00, 0x50, 0x24, 0x00, 0x34, 0x18, 0x00, 0x18, 0x08, 0x00, 0xFC, 0xFC, 0xD8, 0xF4, 0xF4, 0x9C, 0xEC, 0xEC, 0x60, 0xE4, 0xE4, 0x2C, 0xDC, 0xDC, 0x00, 0xC0, 0xC0, 0x00, 0xA4, 0xA4, 0x00, 0x88, 0x88, 0x00, 0x6C, 0x6C, 0x00, 0x50, 0x50, 0x00, 0x34, 0x34, 0x00, 0x18, 0x18, 0x00, 0xD8, 0xFC, 0xD8, 0xB0, 0xFC, 0xAC, 0x8C, 0xFC, 0x80, 0x6C, 0xFC, 0x54, 0x50, 0xFC, 0x28, 0x38, 0xFC, 0x00, 0x28, 0xDC, 0x00, 0x1C, 0xC0, 0x00, 0x14, 0xA4, 0x00, 0x0C, 0x88, 0x00, 0x04, 0x6C, 0x00, 0x00, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x18, 0x00, 0xD4, 0xD8, 0xFC, 0xB8, 0xB8, 0xFC, 0x98, 0x98, 0xFC, 0x7C, 0x7C, 0xFC, 0x5C, 0x5C, 0xFC, 0x3C, 0x3C, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x88, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x18, 0xE8, 0xC8, 0xE8, 0xD4, 0x98, 0xD4, 0xC4, 0x6C, 0xC4, 0xB0, 0x48, 0xB0, 0xA0, 0x28, 0xA0, 0x8C, 0x10, 0x8C, 0x7C, 0x00, 0x7C, 0x6C, 0x00, 0x6C, 0x60, 0x00, 0x60, 0x50, 0x00, 0x50, 0x44, 0x00, 0x44, 0x34, 0x00, 0x34, 0x24, 0x00, 0x24, 0x18, 0x00, 0x18, 0xF4, 0xE8, 0xE4, 0xEC, 0xDC, 0xD4, 0xE4, 0xCC, 0xC0, 0xE0, 0xC0, 0xB0, 0xD8, 0xB0, 0xA0, 0xD0, 0xA4, 0x90, 0xC8, 0x98, 0x80, 0xC4, 0x8C, 0x74, 0xAC, 0x7C, 0x64, 0x98, 0x6C, 0x58, 0x80, 0x5C, 0x4C, 0x6C, 0x4C, 0x3C, 0x54, 0x3C, 0x30, 0x3C, 0x2C, 0x24, 0x28, 0x1C, 0x14, 0x10, 0x0C, 0x08, 0xEC, 0xEC, 0xEC, 0xDC, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0xBC, 0xBC, 0xBC, 0xAC, 0xAC, 0xAC, 0x9C, 0x9C, 0x9C, 0x8C, 0x8C, 0x8C, 0x7C, 0x7C, 0x7C, 0x6C, 0x6C, 0x6C, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x44, 0x44, 0x44, 0x34, 0x34, 0x34, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0xE8, 0xE0, 0xD4, 0xD8, 0xC8, 0xB0, 0xC8, 0xB0, 0x90, 0xB8, 0x98, 0x70, 0xA8, 0x84, 0x58, 0x98, 0x70, 0x40, 0x88, 0x5C, 0x2C, 0x7C, 0x4C, 0x18, 0x6C, 0x3C, 0x0C, 0x5C, 0x34, 0x0C, 0x4C, 0x2C, 0x0C, 0x3C, 0x24, 0x0C, 0x2C, 0x1C, 0x08, 0x20, 0x14, 0x08, 0xEC, 0xE8, 0xE4, 0xDC, 0xD4, 0xD0, 0xCC, 0xC4, 0xBC, 0xBC, 0xB0, 0xAC, 0xAC, 0xA0, 0x98, 0x9C, 0x90, 0x88, 0x8C, 0x80, 0x78, 0x7C, 0x70, 0x68, 0x6C, 0x60, 0x5C, 0x60, 0x54, 0x50, 0x50, 0x48, 0x44, 0x44, 0x3C, 0x38, 0x34, 0x30, 0x2C, 0x24, 0x20, 0x20, 0x18, 0x14, 0x14, 0xE0, 0xE8, 0xD4, 0xC8, 0xD4, 0xB4, 0xB4, 0xC0, 0x98, 0x9C, 0xAC, 0x7C, 0x88, 0x98, 0x60, 0x70, 0x84, 0x4C, 0x5C, 0x70, 0x38, 0x4C, 0x5C, 0x28, 0x40, 0x50, 0x20, 0x38, 0x44, 0x1C, 0x30, 0x3C, 0x18, 0x28, 0x30, 0x14, 0x20, 0x24, 0x10, 0x18, 0x1C, 0x08, 0x0C, 0x10, 0x04, 0xEC, 0xD8, 0xCC, 0xDC, 0xB8, 0xA0, 0xCC, 0x98, 0x7C, 0xBC, 0x80, 0x5C, 0xAC, 0x64, 0x3C, 0x9C, 0x50, 0x24, 0x8C, 0x3C, 0x0C, 0x7C, 0x2C, 0x00, 0x6C, 0x24, 0x00, 0x60, 0x20, 0x00, 0x50, 0x1C, 0x00, 0x44, 0x14, 0x00, 0x34, 0x10, 0x00, 0x24, 0x0C, 0x00, 0xF0, 0xF0, 0xFC, 0xE4, 0xE4, 0xFC, 0xD8, 0xD8, 0xFC, 0xCC, 0xCC, 0xFC, 0xC0, 0xC0, 0xFC, 0xB4, 0xB4, 0xFC, 0xA8, 0xA8, 0xFC, 0x9C, 0x9C, 0xFC, 0x84, 0xD0, 0x00, 0x84, 0xB0, 0x00, 0x7C, 0x94, 0x00, 0x68, 0x78, 0x00, 0x50, 0x58, 0x00, 0x3C, 0x40, 0x00, 0x2C, 0x24, 0x00, 0x1C, 0x08, 0x00, 0x20, 0x00, 0x00, 0xEC, 0xD8, 0xC4, 0xDC, 0xC0, 0xB4, 0xCC, 0xB4, 0xA0, 0xBC, 0x9C, 0x94, 0xAC, 0x90, 0x80, 0x9C, 0x84, 0x74, 0x8C, 0x74, 0x64, 0x7C, 0x64, 0x58, 0x6C, 0x54, 0x4C, 0x60, 0x48, 0x44, 0x50, 0x40, 0x38, 0x44, 0x34, 0x2C, 0x34, 0x2C, 0x24, 0x24, 0x18, 0x18, 0x18, 0x10, 0x10, 0xFC, 0xF8, 0xFC, 0xAC, 0xD4, 0xF0, 0x70, 0xAC, 0xE4, 0x34, 0x8C, 0xD8, 0x00, 0x6C, 0xD0, 0x30, 0x8C, 0xD8, 0x6C, 0xB0, 0xE4, 0xB0, 0xD4, 0xF0, 0xFC, 0xFC, 0xF8, 0xFC, 0xEC, 0x40, 0xFC, 0xC0, 0x28, 0xFC, 0x8C, 0x10, 0xFC, 0x50, 0x00, 0xC8, 0x38, 0x00, 0x98, 0x28, 0x00, 0x68, 0x18, 0x00, 0x7C, 0xDC, 0x7C, 0x44, 0xB4, 0x44, 0x18, 0x90, 0x18, 0x00, 0x6C, 0x00, 0xF8, 0xB8, 0xFC, 0xFC, 0x64, 0xEC, 0xFC, 0x00, 0xB4, 0xCC, 0x00, 0x70, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0x61, 0x61, 0x61, 0xC0, 0xC0, 0xC0, 0xFC, 0x00, 0xF1 }; GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; struct u7frame { gint16 leftX; gint16 leftY; gint16 rightX; gint16 rightY; gint16 width; gint16 height; gint32 datalen; guchar *pixels; }; struct u7shape { int num_frames; struct u7frame *frames; }; MAIN () static void query (void) { static GimpParamDef load_args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_STRING, "filename", "The name of the file to load" }, { GIMP_PDB_STRING, "raw_filename", "The name entered" } }; static GimpParamDef load_return_vals[] = { { GIMP_PDB_IMAGE, "image", "Output image" } }; static gint nload_args = sizeof (load_args) / sizeof (load_args[0]); static gint nload_return_vals = (sizeof (load_return_vals) / sizeof (load_return_vals[0])); static GimpParamDef save_args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_IMAGE, "image", "Image to save" }, { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" }, { GIMP_PDB_STRING, "filename", "The name of the file to save" }, { GIMP_PDB_STRING, "raw_filename", "The name entered" } }; static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]); gimp_install_procedure ("file_shp_load", "loads files in Ultima 7 SHP format", "FIXME: write help for shp_load", "Tristan Tarrant", "Tristan Tarrant", "2000", "/SHP", NULL, GIMP_PLUGIN, nload_args, nload_return_vals, load_args, load_return_vals); gimp_register_magic_load_handler ("file_shp_load", "shp", "", ""); gimp_install_procedure ("file_shp_save", "Save files in Ultima 7 SHP format", "FIXME: write help for shp_save", "Tristan Tarrant", "Tristan Tarrant", "2000", "/SHP", "INDEXEDA", GIMP_PLUGIN, nsave_args, 0, save_args, NULL); gimp_register_save_handler ("file_shp_save", "shp", ""); } static void run (GIMP20_CONST gchar *name, gint nparams, GIMP20_CONST GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[2]; GimpPDBStatusType status = GIMP_PDB_SUCCESS; gint32 image_ID; gint32 drawable_ID; gint32 orig_image_ID; run_mode = param[0].data.d_int32; *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (strcmp (name, "file_shp_load") == 0) { gimp_ui_init ("u7shp", FALSE); choose_palette(); image_ID = load_image (param[1].data.d_string); if (image_ID != -1) { *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; } else { status = GIMP_PDB_EXECUTION_ERROR; } } else if (strcmp (name, "file_shp_save") == 0) { image_ID = orig_image_ID = param[1].data.d_int32; drawable_ID = param[2].data.d_int32; save_image (param[3].data.d_string, image_ID, drawable_ID, orig_image_ID); } else{ status = GIMP_PDB_CALLING_ERROR; } values[0].data.d_status = status; } unsigned int read1(FILE *f) { unsigned char b0; b0 = fgetc(f); return b0; } unsigned int read2(FILE *f) { unsigned char b0, b1; b0 = fgetc(f); b1 = fgetc(f); return (b0 + (b1<<8)); } /* Flauschepelz */ signed int read2signed(FILE *f) { unsigned char b0, b1; signed int i0; b0 = fgetc(f); b1 = fgetc(f); i0 = b0 + (b1<<8); if (i0 >= 32768) { i0 = i0 - 65536; } return (i0); } unsigned int read4(FILE *f) { unsigned char b0, b1, b2, b3; b0 = fgetc(f); b1 = fgetc(f); b2 = fgetc(f); b3 = fgetc(f); return (b0 + (b1<<8) + (b2<<16) + (b3<<24)); } void write1(FILE *f, unsigned char b) { fputc(b, f); } void write2(FILE *f, unsigned int b) { fputc(b & 0xFF, f); fputc((b >> 8) & 0xFF, f); } void write4(FILE *f, unsigned int b) { fputc(b & 0xFF, f); fputc((b >> 8) & 0xFF, f); fputc((b >> 16) & 0xFF, f); fputc((b >> 24) & 0xFF, f); } unsigned char *out1(unsigned char *p, unsigned char b) { *p++ = b; return p; } unsigned char *out2(unsigned char *p, unsigned int b) { *p++ = b & 0xFF; *p++ = (b >> 8) & 0xFF; return p; } unsigned char *out4(unsigned char *p, unsigned int b) { *p++ = b & 0xFF; *p++ = (b >> 8) & 0xFF; *p++ = (b >> 16) & 0xFF; *p++ = (b >> 24) & 0xFF; return p; } static void load_palette (gchar *filename) { FILE *fp; long len; int i; fp = fopen (filename, "rb"); if (!fp) { return; } fseek(fp, 0, SEEK_END); len = ftell(fp); fseek(fp, 0, SEEK_SET); if(len==768) { for(i=0;i<256;i++) { gimp_cmap[i*3]=read1(fp) << 2; gimp_cmap[i*3+1]=read1(fp) << 2; gimp_cmap[i*3+2]=read1(fp) << 2; } } else if(len==1536) { for(i=0;i<256;i++) { gimp_cmap[i*3]=read1(fp) << 2; read1(fp); gimp_cmap[i*3+1]=read1(fp) << 2; read1(fp); gimp_cmap[i*3+2]=read1(fp) << 2; read1(fp); } } fclose(fp); } static void file_sel_delete( GtkWidget *widget, GtkWidget **file_sel ) { gtk_widget_destroy( *file_sel ); *file_sel = NULL; } static void file_selected( GtkWidget *widget, gboolean *selected ) { *selected = TRUE; } gchar* file_select( gchar *title ) { GtkWidget *file_sel; gchar *filename; gboolean selected = FALSE; file_sel = gtk_file_selection_new( title ); gtk_window_set_modal( GTK_WINDOW( file_sel ), TRUE ); gtk_signal_connect( GTK_OBJECT( file_sel ), "destroy", GTK_SIGNAL_FUNC( file_sel_delete ), &file_sel ); gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->cancel_button ), "clicked", GTK_SIGNAL_FUNC( file_sel_delete ), &file_sel ); gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->ok_button ), "clicked", GTK_SIGNAL_FUNC( file_selected ), &selected ); gtk_widget_show( file_sel ); while( ( ! selected ) && ( file_sel ) ) gtk_main_iteration(); /* canceled or window was closed */ if( ! selected ) return NULL; /* ok */ filename = g_strdup( gtk_file_selection_get_filename( GTK_FILE_SELECTION( file_sel ) ) ); gtk_widget_destroy( file_sel ); return filename; } static void choose_palette() { load_palette(file_select("Choose palette")); } static gint32 load_image (gchar *filename) { FILE *fp; gint32 file_size; gint32 shape_size; gint32 hdr_size; guchar *pixptr, *eod; gint32 frame_offset; gint16 slice; gint32 image_ID = -1; gint32 layer_ID = -1; gint16 slice_type; gint16 slice_length; gint16 block_type; gint16 block_length; /* gint32 max_width; gint32 max_height;*/ gint16 max_leftX = -1, max_rightX = -1; gint16 max_leftY = -1, max_rightY = -1; signed int offsetX; signed int offsetY; gchar *framename; guchar block; guchar pix; GimpDrawable *drawable; GimpPixelRgn pixel_rgn; GimpImageType image_type; int i; int j; /* Flauschepelz */ signed int temp_int; struct u7shape shape; struct u7frame *frame; fp = fopen (filename, "rb"); if (!fp) { g_message ("SHP: can't open \"%s\"\n", filename); return -1; } fseek(fp, 0, SEEK_END); file_size = ftell(fp); fseek(fp, 0, SEEK_SET); shape_size = read4(fp); if(file_size!=shape_size) { /* 8x8 tile */ image_type = GIMP_INDEXED_IMAGE; shape.num_frames = file_size/64; fseek(fp, 0, SEEK_SET); /* Return to start of file */ #ifdef DEBUG printf("num_frames = %d\n", shape.num_frames); #endif shape.frames = g_new(struct u7frame, shape.num_frames); max_leftX = 0; max_leftY = 0; max_rightX = 7; max_rightY = 7; /* max_width = 8; max_height = 8;*/ for(i=0; iwidth = 8; frame->height = 8; frame->leftX = 0; frame->leftY = 0; frame->pixels = (char *)g_malloc(64); fread(frame->pixels, 1, 64, fp); } } else { image_type = GIMP_INDEXEDA_IMAGE; hdr_size = read4(fp); shape.num_frames = (hdr_size-4)/4; /* max_width = -1; max_height = -1;*/ #ifdef DEBUG printf("num_frames = %d\n", shape.num_frames); #endif shape.frames = g_new(struct u7frame, shape.num_frames); for(i=0; irightX = read2(fp); frame->leftX = read2(fp); frame->leftY = read2(fp); frame->rightY = read2(fp); if (frame->leftX > max_leftX) max_leftX = frame->leftX; if (frame->rightX > max_rightX) max_rightX = frame->rightX; if (frame->leftY > max_leftY) max_leftY = frame->leftY; if (frame->rightY > max_rightY) max_rightY = frame->rightY; frame->width = frame->leftX+frame->rightX+1; /* if(frame->width>max_width) max_width = frame->width;*/ frame->height = frame->leftY+frame->rightY+1; /* if(frame->height>max_height) max_height = frame->height;*/ pixptr = frame->pixels = g_new0(char, frame->width*frame->height*2); eod = frame->pixels+frame->width*frame->height*2; while((slice=read2(fp))!=0) { slice_type = slice & 0x1; slice_length = slice >> 1; /* Flauschepelz */ offsetX = read2signed(fp); offsetY = read2signed(fp); temp_int = (frame->leftY + offsetY)*frame->width*2 + (frame->leftX + offsetX)*2; pixptr = frame->pixels; pixptr = pixptr + temp_int; /* pixptr = frame->pixels+(offsetY*frame->width+offsetX)*2; */ if(pixptrpixels) pixptr = frame->pixels; if(slice_type) { // Compressed while(slice_length>0) { block = read1(fp); block_type = block & 0x1; block_length = block >> 1; if(block_type) { pix = read1(fp); for(j=0;jwidth, frame->height, image_type, 100, GIMP_NORMAL_MODE); g_free (framename); gimp_image_add_layer (image_ID, layer_ID, 0); gimp_layer_translate (layer_ID, (gint)(max_leftX-frame->leftX), (gint)(max_leftY-frame->leftY)); drawable = gimp_drawable_get (layer_ID); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); gimp_pixel_rgn_set_rect (&pixel_rgn, frame->pixels, 0, 0, drawable->width, drawable->height); gimp_drawable_flush (drawable); gimp_drawable_detach (drawable); } fclose(fp); for(i=0; i0) { int orientation; #ifdef DEBUG printf("Found guide %d:", guide_ID); #endif orientation = gimp_image_get_guide_orientation(image_ID, guide_ID); switch(orientation) { #ifdef HAVE_GIMP_1_2 case GIMP_HORIZONTAL: #else case GIMP_ORIENTATION_HORIZONTAL: #endif if(hoty<0) { hoty = gimp_image_get_guide_position(image_ID, guide_ID); #ifdef DEBUG printf(", horizontal=%d\n", hoty); #endif } break; #ifdef HAVE_GIMP_1_2 case GIMP_VERTICAL: #else case GIMP_ORIENTATION_VERTICAL: #endif if(hotx<0) { hotx = gimp_image_get_guide_position(image_ID, guide_ID); #ifdef DEBUG printf(", vertical=%d\n", hotx); #endif } break; default: break; } guide_ID = gimp_image_find_next_guide(image_ID, guide_ID); } /* get a list of layers for this image_ID */ layers = gimp_image_get_layers (image_ID, &nlayers); if (nlayers > 0 && !gimp_drawable_is_indexed(layers[0])) { g_message ("SHP: You can only save indexed images!"); return -1; } max_width = gimp_image_width (image_ID); max_height = gimp_image_height (image_ID); shape.num_frames = nlayers; hdr_size = (nlayers+1)*4; shape.frames = (struct u7frame *)malloc(sizeof(struct u7frame)*shape.num_frames); for (k=0;kwidth = drawable->width; frame->height = drawable->height; frame->leftX = hotx - offsetX; frame->leftY = hoty - offsetY; frame->rightX = frame->width-frame->leftX-1; frame->rightY = frame->height-frame->leftY-1; pix = (gchar *)malloc(frame->width*frame->height*2); pixptr = pix; out = (gchar *)malloc(frame->width*frame->height*8); outptr = out; gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE); gimp_pixel_rgn_get_rect (&pixel_rgn, pixptr, 0, 0, drawable->width, drawable->height); newx = 0; for (y = 0; y < frame->height; y++) { for (x = 0; (x = skip_transparent(&pixptr, x, frame->width)) < frame->width; x = newx) { short runs[100]; newx = find_runs(runs, pixptr, x, frame->width); if (!runs[1] && !(runs[0]&1)) { int len = runs[0] >> 1; outptr = out2(outptr, runs[0]); outptr = out2(outptr, x - frame->leftX); outptr = out2(outptr, y - frame->leftY); for(i=0; ileftX); outptr = out2(outptr, y - frame->leftY); for (i = 0; runs[i]; i++) { int len = runs[i]>>1; if (runs[i]&1) { while (len) { int c = len > 127 ? 127 : len; *outptr++ = (c<<1)|1; *outptr++ = *pixptr; pixptr += (c*2); len -= c; } } else while (len > 0) { int c; c = len > 127 ? 127 : len; *outptr++ = c<<1; for(j=0; jdatalen = outptr - out; frame->pixels = (gchar *) malloc(frame->datalen); memcpy(frame->pixels, out, frame->datalen); free(out); free(pix); gimp_drawable_detach(drawable); } fp = fopen (filename, "wb"); if (!fp) { g_message ("SHP: can't create \"%s\"\n", filename); return -1; } shape_size = 0; write4(fp, shape_size); // Fill in later for(i=0; irightX); write2(fp, frame->leftX); write2(fp, frame->leftY); write2(fp, frame->rightY); fwrite(frame->pixels, 1, frame->datalen, fp); } pos = ftell(fp); // Get the file size fseek(fp, 0, SEEK_SET); write4(fp, pos); // Write it in the right place fclose(fp); for(i=0; i #include #include #include "vgafile.h" #include "servemsg.h" class Shape_info; class Shapes_vga_file; class Equip_row_widgets; class Shape_file_set; class Shape_file_info; class Shape_group_file; class Shape_draw; class Object_browser; class Shape_group; class Locator; class Combo_editor; class Exec_box; // Callback for msgs. typedef void (*Msg_callback)(Exult_server::Msg_type id, unsigned char *data, int datalen, void *client); #ifndef WIN32 #define C_EXPORT extern "C" #else #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include "windrag.h" #define C_EXPORT extern "C" __declspec(dllexport) #endif class ExultStudio { private: char *glade_path; // Where our .glade file is. GtkWidget *app; GladeXML *app_xml; char *static_path; char *image_editor; char *default_game; guint32 background_color; static ExultStudio *self; // Modified one of the .dat's? bool shape_info_modified, shape_names_modified; Shape_file_set *files; // All the shape files. std::vector group_windows; // All 'group' windows. Shape_file_info *curfile; // Current browser file info. Shape_file_info *vgafile; // Main 'shapes.vga'. Shape_file_info *facefile; // 'faces.vga'. std::vector names; Object_browser *browser; unsigned char *palbuf; // 3*256 rgb's, each 0-63. // Egg editor: GtkWidget *eggwin;// Egg window. Shape_draw *egg_monster_draw; int egg_ctx; // Npc editor: GtkWidget *npcwin; Shape_draw *npc_draw, *npc_face_draw; int npc_ctx; guint npc_status_id; // Object editor: GtkWidget *objwin; Shape_draw *obj_draw; // Shape info. editor: GtkWidget *shapewin; Shape_draw *shape_draw; GtkWidget *equipwin; // Map locator: Locator *locwin; // Combo editor: Combo_editor *combowin; // Compile window: GtkWidget *compilewin; Exec_box *compile_box; // For Win32 DND #ifdef WIN32 HWND egghwnd; Windnd *eggdnd; HWND npchwnd; Windnd *npcdnd; HWND objhwnd; Windnd *objdnd; HWND shphwnd; Windnd *shpdnd; #endif // Server data. int server_socket; gint server_input_tag; Msg_callback waiting_for_server; void *waiting_client; public: ExultStudio(int argc, char **argv); ~ExultStudio(); bool okay_to_close(); static ExultStudio *get_instance() { return self; } GladeXML *get_xml() { return app_xml; } int get_server_socket() const { return server_socket; } guint32 get_background_color() const { return background_color; } char *get_shape_name(int shnum) { return shnum >= 0 && shnum < names.size() ?names[shnum] : 0;} const char *get_image_editor() { return image_editor; } Shape_file_set *get_files() { return files; } Object_browser *get_browser() { return browser; } unsigned char *get_palbuf() { return palbuf; } Shape_file_info *get_vgafile() // 'shapes.vga'. { return vgafile; } Combo_editor *get_combowin() { return combowin; } void set_msg_callback(Msg_callback cb, void *client) { waiting_for_server = cb; waiting_client = client; } Shape_group_file *get_cur_groups(); void set_browser(const char *name, Object_browser *obj); bool has_focus(); // Any of our windows has focus? void create_new_game(const char *dir); void new_game(); void choose_game_path(); Object_browser *create_browser(const char *fname); void set_game_path(const char *path, const char *patchpath = 0); void setup_file_list(); void save_all(); // Write out everything. bool need_to_save(); // Anything modified? void write_map(); void read_map(); void write_shape_info(bool force = false); void reload_usecode(); void set_play(gboolean play); void set_tile_grid(gboolean grid); void set_edit_lift(int lift); void set_hide_lift(int lift); void set_edit_terrain(gboolean terrain); void set_edit_mode(int md); void show_unused_shapes(unsigned char *data, int datalen); // Open/create shape files: Shape_file_info *open_shape_file(const char *fname); void new_shape_file(bool single); static void create_shape_file(char *nm, gpointer udata); // Groups: void setup_groups(); void setup_group_controls(); void add_group(); void del_group(); void groups_changed(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *loc, bool value = false); void open_group_window(); void close_group_window(GtkWidget *gtkwin); void save_groups(); bool groups_modified(); void update_group_windows(Shape_group *grp); // Objects: void open_obj_window(unsigned char *data, int datalen); void close_obj_window(); int init_obj_window(unsigned char *data, int datalen); int save_obj_window(); void show_obj_shape(int x = 0, int y = 0, int w = -1, int h = -1); void set_obj_shape(int shape, int frame); // Eggs: void open_egg_window(unsigned char *data = 0, int datalen = 0); void close_egg_window(); int init_egg_window(unsigned char *data, int datalen); int save_egg_window(); void show_egg_monster(int x = 0, int y = 0, int w = -1, int h = -1); void set_egg_monster(int shape, int frame); // NPC's: void open_npc_window(unsigned char *data = 0, int datalen = 0); void close_npc_window(); void init_new_npc(); int init_npc_window(unsigned char *data, int datalen); int save_npc_window(); void show_npc_shape(int x = 0, int y = 0, int w = -1, int h = -1); void set_npc_shape(int shape, int frame); void show_npc_face(int x = 0, int y = 0, int w = -1, int h = -1); void set_npc_face(int shape, int frame); static void schedule_btn_clicked(GtkWidget *btn, gpointer data); // Shapes: void init_equip_window(int recnum); void save_equip_window(); void open_equip_window(int recnum); void close_equip_window(); void show_equip_shape(Equip_row_widgets *eq, int x = 0, int y = 0, int w = -1, int h = -1); void set_shape_notebook_frame(int frnum); void init_shape_notebook(Shape_info& info, GtkWidget *book, int shnum, int frnum); void save_shape_notebook(Shape_info& info, int shnum, int frnum); void open_shape_window(int shnum, int frnum, Shape_file_info *file_info, char *shname, Shape_info *info = 0); void save_shape_window(); void close_shape_window(); void show_shinfo_shape(int x = 0, int y = 0, int w = -1, int h = -1); // Map locator. void open_locator_window(); void open_combo_window(); // Combo-object editor. void save_combos(); // Compile. void open_compile_window(); void compile(bool if_needed = false); void halt_compile(); void run(); bool send_to_server(Exult_server::Msg_type id, unsigned char *data = 0, int datalen = 0); void read_from_server(); bool connect_to_server(); // Message from Exult. void info_received(unsigned char *data, int datalen); void set_edit_menu(bool sel, bool clip); // Preferences. static void background_color_okay(GtkWidget *dlg, gpointer data); void open_preferences(); void save_preferences(); // GTK/Glade utils: bool get_toggle(char *name); void set_toggle(char *name, bool val); void set_bit_toggles(char **names, int num, unsigned char bits); unsigned char get_bit_toggles(char **names, int num); int get_optmenu(char *name); void set_optmenu(char *name, int val); int get_spin(char *name); void set_spin(char *name, int val, bool sensitive = true); void set_spin(char *name, int val, int low, int high); int get_num_entry(char *name); const gchar *get_text_entry(char *name); void set_entry(char *name, int val, bool hex = false, bool sensitive = true); void set_entry(char *name, const char *val, bool sensitive = true); guint set_statusbar(char *name, int context, char *msg); void remove_statusbar(char *name, int context, guint msgid); void set_button(char *name, const char *text); void set_visible(char *name, bool vis); void set_sensitive(char *name, bool vis); int prompt(const char *msg, const char *choice0, const char *choice1 = 0,const char *choice2 = 0); }; // Utilities: namespace EStudio { int Prompt(const char *msg, const char *choice0, const char *choice1 = 0,const char *choice2 = 0); void Alert(const char *msg, ...); GtkWidget *Add_menu_item(GtkWidget *menu, const char *label = 0, GtkSignalFunc func = 0, gpointer func_data = 0); GtkWidget *Create_arrow_button(GtkArrowType dir, GtkSignalFunc clicked, gpointer func_data); } #endif exult-1.2/mapedit/eggedit.cc0000644000175000001440000002732607711562441011555 /** ** Eggedit.cc - Egg-editing methods. ** ** Written: 6/8/01 - JSF **/ /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "studio.h" #include "u7drag.h" #include "servemsg.h" #include "objserial.h" #include "exult_constants.h" #include "shapefile.h" #include "shapedraw.h" using std::cout; using std::cerr; using std::endl; /* * Open egg window. */ C_EXPORT void on_open_egg_activate ( GtkMenuItem *menuitem, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); studio->open_egg_window(); } /* * Egg window's Apply button. */ C_EXPORT void on_egg_apply_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->save_egg_window(); } /* * Egg window's Cancel button. */ C_EXPORT void on_egg_cancel_btn_clicked ( GtkButton *btn, gpointer user_data ) { ExultStudio::get_instance()->close_egg_window(); } /* * Egg window's close button. */ C_EXPORT gboolean on_egg_window_delete_event ( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { ExultStudio::get_instance()->close_egg_window(); return TRUE; } /* * Draw shape in egg 'monster' area. */ C_EXPORT gboolean on_egg_monster_draw_expose_event ( GtkWidget *widget, // The view window. GdkEventExpose *event, gpointer data // ->Shape_chooser. ) { ExultStudio::get_instance()->show_egg_monster( event->area.x, event->area.y, event->area.width, event->area.height); return (TRUE); } /* * Monster shape # lost focus, so update shape displayed. */ C_EXPORT gboolean on_monst_shape_focus_out_event ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data ) { ExultStudio::get_instance()->show_egg_monster(); return FALSE; } /* * "Teleport coords" toggled. */ C_EXPORT void on_teleport_coord_toggled ( GtkToggleButton *btn, gpointer user_data ) { ExultStudio *studio = ExultStudio::get_instance(); bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)); studio->set_sensitive("teleport_x", on); studio->set_sensitive("teleport_y", on); studio->set_sensitive("teleport_eggnum", !on); } /* * Callback for when a shape is dropped on the Egg 'monster' area. */ static void Egg_monster_dropped ( int file, // U7_SHAPE_SHAPES. int shape, int frame, void *udata ) { if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024) ((ExultStudio *) udata)->set_egg_monster(shape, frame); } #ifdef WIN32 static void Drop_dragged_shape(int shape, int frame, int x, int y, void *data) { cout << "Dropped a shape: " << shape << "," << frame << " " << data << endl; Egg_monster_dropped(U7_SHAPE_SHAPES, shape, frame, data); } #endif /* * Open the egg-editing window. */ void ExultStudio::open_egg_window ( unsigned char *data, // Serialized egg, or null. int datalen ) { bool first_time = false; if (!eggwin) // First time? { first_time = true; eggwin = glade_xml_get_widget( app_xml, "egg_window" ); if (vgafile && palbuf) { egg_monster_draw = new Shape_draw(vgafile->get_ifile(), palbuf, glade_xml_get_widget(app_xml, "egg_monster_draw")); egg_monster_draw->enable_drop(Egg_monster_dropped, this); } egg_ctx = gtk_statusbar_get_context_id( GTK_STATUSBAR(glade_xml_get_widget( app_xml, "egg_status")), "Egg Editor"); } // Init. egg address to null. gtk_object_set_user_data(GTK_OBJECT(eggwin), 0); // Make 'apply' sensitive. gtk_widget_set_sensitive(glade_xml_get_widget(app_xml, "egg_apply_btn"), true); if (data) { if (!init_egg_window(data, datalen)) return; } else if (first_time) // Init. empty dialog first time. { set_toggle("teleport_coord", true); set_sensitive("teleport_x", true); set_sensitive("teleport_y", true); set_sensitive("teleport_eggnum", false); } gtk_widget_show(eggwin); #ifdef WIN32 if (first_time || !eggdnd) Windnd::CreateStudioDropDest(eggdnd, egghwnd, Drop_dragged_shape, NULL, NULL, (void*) this); #endif } /* * Close the egg-editing window. */ void ExultStudio::close_egg_window ( ) { if (eggwin) { gtk_widget_hide(eggwin); #ifdef WIN32 Windnd::DestroyStudioDropDest(eggdnd, egghwnd); #endif } } /* * Init. the egg editor with data from Exult. * * Output: 0 if error (reported). */ int ExultStudio::init_egg_window ( unsigned char *data, int datalen ) { unsigned long addr; int tx, ty, tz; int shape, frame; int type; int criteria; int probability; int distance; bool nocturnal, once, hatched, auto_reset; int data1, data2; if (!Egg_object_in(data, datalen, addr, tx, ty, tz, shape, frame, type, criteria, probability, distance, nocturnal, once, hatched, auto_reset, data1, data2)) { cout << "Error decoding egg" << endl; return 0; } // Store address with window. gtk_object_set_user_data(GTK_OBJECT(eggwin), (gpointer) addr); GtkWidget *notebook = glade_xml_get_widget(app_xml, "notebook1"); if (notebook) // 1st is monster (1). gtk_notebook_set_page(GTK_NOTEBOOK(notebook), type - 1); set_spin("probability", probability); set_spin("distance", distance); set_optmenu("criteria", criteria); set_toggle("nocturnal", nocturnal); set_toggle("once", once); set_toggle("hatched", hatched); set_toggle("autoreset", auto_reset); switch (type) // Set notebook page. { case 1: // Monster: { int shnum = data2&1023, frnum = data2>>10; set_entry("monst_shape", shnum); set_entry("monst_frame", frnum); set_optmenu("monst_schedule", data1>>8); set_optmenu("monst_align", data1&3); set_spin("monst_count", (data1&0xff)>>2); break; } case 2: // Jukebox: set_spin("juke_song", data1&0xff); set_toggle("juke_cont", (data1>>8)&0x01); break; case 3: // Sound effect: set_spin("sfx_number", data1&0xff); set_toggle("sfx_cont", (data1>>8)&0x01); break; case 4: // Voice: set_spin("speech_number", data1&0xff); break; case 5: // Usecode: set_entry("usecode_number", data2, true); set_spin("usecode_quality", data1&0xff); break; case 6: // Missile: set_entry("missile_shape", data1); set_optmenu("missile_dir", data2&0xff); set_spin("missile_delay", data2>>8); break; case 7: // Teleport: { int qual = data1&0xff; if (qual == 255) { set_toggle("teleport_coord", true); int schunk = data1 >> 8; set_entry("teleport_x", (schunk%12)*c_tiles_per_schunk +(data2&0xff), true); set_entry("teleport_y", (schunk/12)*c_tiles_per_schunk +(data2>>8), true); set_spin("teleport_eggnum", 0, false); } else // Egg #. { set_toggle("teleport_coord", false); set_entry("teleport_x", 0, false, false); set_entry("teleport_y", 0, false, false); set_spin("teleport_eggnum", qual); } break; } case 8: // Weather: set_optmenu("weather_type", data1&0xff); set_spin("weather_length", data1>>8); break; case 9: // Path: set_spin("pathegg_num", data1&0xff); break; case 10: // Button: set_spin("btnegg_distance", data1&0xff); break; default: break; } return 1; } /* * Callback for when user clicked where egg should be inserted. */ static void Egg_response ( Exult_server::Msg_type id, unsigned char *data, int datalen, void * /* client */ ) { if (id == Exult_server::user_responded) ExultStudio::get_instance()->close_egg_window(); //+++++cancel?? } /* * Send updated egg info. back to Exult. * * Output: 0 if error (reported). */ int ExultStudio::save_egg_window ( ) { cout << "In save_egg_window()" << endl; unsigned char data[Exult_server::maxlength]; // Get egg (null if creating new). unsigned long addr = (unsigned long) gtk_object_get_user_data( GTK_OBJECT(eggwin)); int tx = -1, ty = -1, tz = -1; // +++++For now. int shape = -1, frame = -1; // For now. int type = -1; GtkWidget *notebook = glade_xml_get_widget(app_xml, "notebook1"); if (notebook) // 1st is monster (1). type = 1 + gtk_notebook_get_current_page( GTK_NOTEBOOK(notebook)); else { cout << "Can't find notebook widget" << endl; return 0; } int criteria = get_optmenu("criteria"); int probability = get_spin("probability"); int distance = get_spin("distance"); bool nocturnal = get_toggle("nocturnal"), once = get_toggle("once"), hatched = get_toggle("hatched"), auto_reset = get_toggle("autoreset"); int data1 = -1, data2 = -1; switch (type) // Set notebook page. { case 1: // Monster: data2 = (get_num_entry("monst_shape")&1023) + (get_num_entry("monst_frame")<<10); data1 = (get_optmenu("monst_schedule")<<8) + (get_optmenu("monst_align")&3) + (get_spin("monst_count")<<2); break; case 2: // Jukebox: data1 = (get_spin("juke_song")&0xff) + (get_toggle("juke_cont")<<8); break; case 3: // Sound effect: data1 = (get_spin("sfx_number")&0xff) + (get_toggle("sfx_cont")<<8); break; case 4: // Voice: data1 = get_spin("speech_number")&0xff; break; case 5: // Usecode: data2 = get_num_entry("usecode_number"); data1 = get_spin("usecode_quality")&0xff; break; case 6: // Missile: data1 = get_num_entry("missile_shape"); data2 = (get_optmenu("missile_dir")&0xff) + (get_spin("missile_delay")<<8); break; case 7: // Teleport: if (get_toggle("teleport_coord")) { // Abs. coords. int tx = get_num_entry("teleport_x"), ty = get_num_entry("teleport_y"); data2 = (tx&0xff) + ((ty&0xff)<<8); int sx = tx/c_tiles_per_schunk, sy = ty/c_tiles_per_schunk; data1 = 255 + ((sy*12 + sx)<<8); } else // Egg #. data1 = get_spin("teleport_eggnum")&0xff; break; case 8: // Weather: data1 = (get_optmenu("weather_type")&0xff) + (get_spin("weather_length")<<8); break; case 9: // Path: data1 = get_spin("pathegg_num")&0xff; break; case 10: // Button: data1 = get_spin("btnegg_distance")&0xff; break; default: cout << "Unknown egg type" << endl; return 0; } if (Egg_object_out(server_socket, addr, tx, ty, tz, shape, frame, type, criteria, probability, distance, nocturnal, once, hatched, auto_reset, data1, data2) == -1) { cout << "Error sending egg data to server" <configure(); // Yes, this is kind of redundant... int shnum = get_num_entry("monst_shape"); int frnum = get_num_entry("monst_frame"); egg_monster_draw->draw_shape_centered(shnum, frnum); if (w != -1) egg_monster_draw->show(x, y, w, h); else egg_monster_draw->show(); } /* * Set egg monster shape. */ void ExultStudio::set_egg_monster ( int shape, int frame ) { set_entry("monst_shape", shape); set_entry("monst_frame", frame); show_egg_monster(); } exult-1.2/actions.cc0000644000175000001440000004664710002261713010152 /* * actions.cc - Action controllers for actors. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gamewin.h" #include "actions.h" #include "actors.h" #include "Zombie.h" #include "Astar.h" #include "paths.h" #include "dir.h" #include "ucmachine.h" #include "frameseq.h" #include "ucmachine.h" #include "cheat.h" #include "party.h" using std::cout; using std::endl; long Actor_action::seqcnt = 0; /* * Handle an event and check to see if we were deleted. * * Output: Delay value from handle_event (0 if we've been deleted). */ int Actor_action::handle_event_safely ( Actor *actor, bool& deleted // True returned if we're gone! ) { Actor_action *old_action = actor->get_action(); long old_seq = old_action->seq; // Do current action. int delay = handle_event(actor); if (actor->get_action() != old_action || old_action->seq != old_seq) { deleted = true; // We've been deleted. return 0; } deleted = false; return delay; } /* * Set to walk from one point to another the dumb way. * * Output: ->this, or 0 if unsuccessful. */ Actor_action *Actor_action::walk_to_tile ( Actor * /* npc */, Tile_coord src, Tile_coord dest, int /* dist */ // Ignored. ) { Zombie *path = new Zombie(); get_party = false; // Set up new path. if (path->NewPath(src, dest, 0)) return (new Path_walking_actor_action(path)); else { delete path; return (0); } } /* * Set up an action to get an actor to a location (via pathfinding), and * then execute another action when he gets there. * * Output: ->action. */ Actor_action *Actor_action::create_action_sequence ( Actor *actor, // Whom to activate. Tile_coord dest, // Where to walk to. Actor_action *when_there, // What to do when he gets there. bool from_off_screen // Have actor walk from off-screen. ) { Actor_action *act = when_there; Tile_coord actloc = actor->get_tile(); if (from_off_screen) actloc.tx = actloc.ty = -1; if (dest != actloc) // Get to destination. { Actor_action *w = new Path_walking_actor_action(new Astar()); Actor_action *w2 = w->walk_to_tile(actor, actloc, dest); if (w2 != w) delete w; if (!w2) // Failed? Teleport. w2 = new Move_actor_action(dest); // And teleport if blocked walking. Actor_action *tel = new Move_actor_action(dest); // Walk there, then do whatever. Sequence_actor_action *seq; act = seq = new Sequence_actor_action(w2, tel, act); seq->set_speed(0); // No delay between actions. } return act; } /* * Null action. */ int Null_action::handle_event ( Actor *actor ) { return 0; } /* * Create action to follow a path. */ Path_walking_actor_action::Path_walking_actor_action ( PathFinder *p, // Pathfinder, or 0 for Astar. int maxblk // Max. retries when blocked. ) : reached_end(false), path(p), from_offscreen(false), subseq(0), blocked(0), max_blocked(maxblk) { if (!path) path = new Astar(); Tile_coord src = path->get_src(), dest = path->get_dest(); original_dir = static_cast(Get_direction4( src.ty - dest.ty, dest.tx - src.tx)); } /* * Delete. */ Path_walking_actor_action::~Path_walking_actor_action ( ) { delete path; delete subseq; subseq = 0; // (Debugging). original_dir = -1; } /* * Create action for walking to given destination using Astar. * Note: This is a static method. * * Output: Action if successful, else 0. */ Path_walking_actor_action *Path_walking_actor_action::create_path ( Tile_coord src, // Starting position. Tile_coord dest, // Destination. Pathfinder_client& cost // Cost for Astar. ) { Astar *path = new Astar(); // Get to within 1 tile. if (path->NewPath(src, dest, &cost)) return new Path_walking_actor_action(path); else { delete path; return 0; } } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Path_walking_actor_action::handle_event ( Actor *actor ) { if (subseq) // Going through a door? { int delay = subseq->handle_event(actor); if (delay) return delay; // Still going. set_subseq(0); // He was stopped, so restore speed. actor->set_frame_time(speed); return speed; // Come back in a moment. } Tile_coord tile; if (blocked) { #if 0 std::cout << "Actor " << actor->get_name() << " blocked. Retrying." << std::endl; #endif if (actor->step(blocked_tile, blocked_frame)) { // Successful? blocked = 0; // He was stopped, so restore speed. actor->set_frame_time(speed); return speed; } // Wait up to 1.6 secs. return (blocked++ > max_blocked ? 0 : 100 + blocked*(std::rand()%500)); } speed = actor->get_frame_time();// Get time between frames. if (!speed) return 0; // Not moving. bool done; // So we'll know if this is the last. if (!path->GetNextStep(tile, done)) { reached_end = true; // Did it. return (0); } if (done) // In case we're deleted. reached_end = true; Tile_coord cur = actor->get_tile(); int newdir = static_cast(Get_direction4(cur.ty - tile.ty, tile.tx - cur.tx)); Frames_sequence *frames = actor->get_frames(newdir); int& step_index = actor->get_step_index(); if (!step_index) // First time? Init. step_index = frames->find_unrotated(actor->get_framenum()); // Get next (updates step_index). int frame = frames->get_next(step_index); int cur_speed = speed; // Step() might delete us! if (from_offscreen) // Teleport to 1st spot. { from_offscreen = false; actor->move(tile.tx, tile.ty, tile.tz); return cur_speed; } else if (actor->step(tile, frame)) // Successful. { if (get_party) // MUST be the Avatar. Game_window::get_instance()->get_party_man()-> get_followers(newdir); if (done) // Was this the last step? return (0); return cur_speed; } reached_end = false; frames->decrement(step_index); // We didn't take the step. // Blocked by a door? if (actor->get_tile().distance(tile) == 1 && !cheat.in_map_editor()) // And NOT map-editing? // +++++Check for intelligence? { Game_object *door = Game_object::find_door(tile); if (door != 0 && door->is_closed_door() && // Make sure it's not locked! door->get_framenum()%4 < 2) // Try to open it. { if (open_door(actor, door)) return speed; } } if (!max_blocked || // No retries allowed? actor->is_dormant()) // Or actor off-screen? return 0; blocked = 1; blocked_tile = tile; blocked_frame = frame; return (100 + std::rand()%500); // Wait .1 to .6 seconds. } /* * Open door that's blocking the NPC, and set action to walk past and * close it. * * Output: 1 if successful. */ int Path_walking_actor_action::open_door ( Actor *actor, Game_object *door ) { Game_window *gwin = Game_window::get_instance(); Tile_coord cur = actor->get_tile(); // Get door's footprint in tiles. Rectangle foot = door->get_footprint(); // Open it, but kludge quality to // avoid unwanted usecode. int savequal = door->get_quality(); door->set_quality(0); door->activate(); door->set_quality(savequal); Tile_coord past; // Tile on other side of door. past.tz = cur.tz; int dir; // Get dir to face door afterwards. if (foot.w > foot.h) // Horizontal? { past.tx = foot.x + foot.w/2; if (cur.ty <= foot.y) // N. of door? { past.ty = foot.y + foot.h; dir = 0; } else // S. of door? { past.ty = foot.y - 1; dir = 4; } } else // Vertical. { past.ty = foot.y + foot.h/2; if (cur.tx <= foot.x) // W. of door? { past.tx = foot.x + foot.w; dir = 6; } else // E. of door? { past.tx = foot.x - 1; dir = 2; } } Tile_coord tmp = Map_chunk::find_spot(past, 1, actor, 1); if (past.tx != -1) // Succeeded. Walk past and close it. { #ifdef DEBUG cout << "Path_walking_actor_action::open_door()" << endl; #endif signed char frames[2]; frames[0] = actor->get_dir_framenum(dir, Actor::standing); frames[1] = actor->get_dir_framenum(dir, 3); signed char standframe = frames[0]; set_subseq(create_action_sequence(actor, past, new Sequence_actor_action( new Frames_actor_action(frames, sizeof(frames)), new Activate_actor_action(door), new Frames_actor_action(&standframe, 1)))); return 1; } return 0; } /* * Stopped moving. */ void Path_walking_actor_action::stop ( Actor *actor ) { // Don't set slimes. if (!actor->get_info().has_strange_movement()) { // ++++For now, just use original dir. Frames_sequence *frames = actor->get_frames(original_dir); actor->change_frame(frames->get_resting()); } } /* * Set to walk from one point to another, using the same pathfinder. * * Output: ->this, or 0 if unsuccessful. */ Actor_action *Path_walking_actor_action::walk_to_tile ( Actor *npc, Tile_coord src, // tx=-1 or ty=-1 means don't care. Tile_coord dest, // Same here. int dist // Distance to get to within dest. ) { Game_window *gwin = Game_window::get_instance(); blocked = 0; // Clear 'blocked' count. reached_end = false; // Starting new path. get_party = false; from_offscreen = false; //+++++Should dist be used below??: // Set up new path. // Don't care about 1 coord.? if (dest.tx == -1 || dest.ty == -1) { if (dest.tx == dest.ty) // Completely off-screen? { Offscreen_pathfinder_client cost(npc); if (!path->NewPath(src, dest, &cost)) return (0); } else { Onecoord_pathfinder_client cost(npc); if (!path->NewPath(src, dest, &cost)) return (0); } } // How about from source? else if (src.tx == -1 || src.ty == -1) { // Figure path in opposite dir. if (src.tx == src.ty) // Both -1? { // Aim from NPC's current pos. Offscreen_pathfinder_client cost(npc, npc->get_tile()); if (!path->NewPath(dest, src, &cost)) return (0); } else { Onecoord_pathfinder_client cost(npc); if (!path->NewPath(dest, src, &cost)) return (0); } from_offscreen = true; // Set to go backwards. if (!path->set_backwards()) return (0); } else { Actor_pathfinder_client cost(npc, dist); if (!path->NewPath(src, dest, &cost)) return (0); } // Reset direction (but not index). original_dir = static_cast(Get_direction4( src.ty - dest.ty, dest.tx - src.tx)); return (this); } /* * Return current destination. * * Output: 0 if none. */ int Path_walking_actor_action::get_dest ( Tile_coord& dest // Returned here. ) { dest = path->get_dest(); return (1); } /* * Following an Astar path? */ int Path_walking_actor_action::following_smart_path ( ) { return path != 0 && path->following_smart_path(); } /* * Create action to follow a path towards another object. */ Approach_actor_action::Approach_actor_action ( PathFinder *p, // Path to follow. Game_object *d // Destination object. ) : Path_walking_actor_action(p, 0), // (Stop if blocked.) dest_obj(d), orig_dest_pos(d->get_tile()), cur_step(0) { // Get length of path. int nsteps = path->get_num_steps(); if (nsteps >= 6) // (May have to play with this). check_step = nsteps > 18 ? 9 : nsteps/2; else check_step = 10000; } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Approach_actor_action::handle_event ( Actor *actor ) { int delay = Path_walking_actor_action::handle_event(actor); if (!delay) // Done or blocked. return 0; if (++cur_step == check_step) // Time to check. { if (dest_obj->get_tile().distance(orig_dest_pos) > 2) return 0; // Moved too much, so stop. // Figure next check. int nsteps = path->get_num_steps(); if (nsteps >= 6) check_step += nsteps/2; } return delay; } /* * Create if-then-else path. */ If_else_path_actor_action::If_else_path_actor_action ( Actor *actor, Tile_coord dest, Actor_action *s, Actor_action *f ) : Path_walking_actor_action(0, 6), // Maxblk = 6. succeeded(false), failed(false), done(false), success(s), failure(f) { if (!walk_to_tile(actor, actor->get_tile(), dest)) { done = failed = true; } } /* * Delete. */ If_else_path_actor_action::~If_else_path_actor_action ( ) { delete success; delete failure; } /* * Set failure action. */ void If_else_path_actor_action::set_failure ( Actor_action *f ) { delete failure; failure = f; done = false; // So it gets executed. } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int If_else_path_actor_action::handle_event ( Actor *actor ) { if (done) return 0; // Shouldn't really get here. bool del; int delay; if (succeeded) // Doing the success action? { if ((delay = success->handle_event_safely(actor, del)) == 0 && !del) done = true; return delay; } else if (failed) { if ((delay = failure->handle_event_safely(actor, del)) == 0 && !del) done = true; return delay; } delay = Path_walking_actor_action::handle_event(actor); if (delay) return delay; if (!reached_end) { // Didn't get there. if (failure) { failed = true; #if DEBUG cout << "Executing 'failure' path usecode" << endl; #endif delay = failure->handle_event_safely(actor, del); if (del) // Are we gone? return 0; } } else // Success. { if (success) { succeeded = true; delay = success->handle_event_safely(actor, del); if (del) // Are we gone? return 0; } } if (!delay) done = true; // All done now. return delay; } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Move_actor_action::handle_event ( Actor *actor ) { if (dest.tx < 0 || actor->get_tile() == dest) return (0); // Done. actor->move(dest); // Zip right there. Game_window *gwin = Game_window::get_instance(); if (actor == gwin->get_main_actor()) // Teleported Avatar? gwin->center_view(dest); dest.tx = -1; // Set to stop. return (100); // Wait 1/10 sec. } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Activate_actor_action::handle_event ( Actor *actor ) { obj->activate(); return 0; // That's all. } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Usecode_actor_action::handle_event ( Actor *actor ) { Game_window *gwin = Game_window::get_instance(); gwin->get_usecode()->call_usecode(fun, item, (Usecode_machine::Usecode_events) eventid); gwin->set_all_dirty(); // Clean up screen. return 0; // That's all. } /* * Create sequence of frames. */ Frames_actor_action::Frames_actor_action ( signed char *f, // Frames. -1 means don't change. int c, // Count. int spd, // Frame delay in 1/1000 secs. Game_object *o ) : cnt(c), index(0), speed(spd), obj(o) { frames = new signed char[cnt]; std::memcpy(frames, f, cnt); } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Frames_actor_action::handle_event ( Actor *actor ) { Game_object *o = obj; if (index == cnt) return (0); // Done. int frnum = frames[index++]; // Get frame. if (frnum >= 0) { Game_window *gwin = Game_window::get_instance(); if (o) o->change_frame(frnum); else actor->change_frame(frnum); } return (speed); } /* * Create a sequence with up to 4 actions. */ Sequence_actor_action::Sequence_actor_action ( Actor_action *a0, // (These will be deleted when done.) Actor_action *a1, Actor_action *a2, Actor_action *a3 ) : index(0), speed(100) { actions = new Actor_action *[5];// Create list. actions[0] = a0; actions[1] = a1; actions[2] = a2; actions[3] = a3; actions[4] = 0; // 0-delimit. } /* * Delete. */ Sequence_actor_action::~Sequence_actor_action ( ) { for (int i = 0; actions[i]; i++) delete actions[i]; delete [] actions; } /* * Handle a time event. * * Output: 0 if done with this action, else delay for next frame. */ int Sequence_actor_action::handle_event ( Actor *actor ) { if (!actions[index]) // Done? return (0); // Do current action. bool deleted; int delay = actions[index]->handle_event_safely(actor, deleted); if (deleted) return 0; // We've been deleted! if (!delay) { index++; // That one's done now. if (!speed) // Immediately? Run with next. return handle_event(actor); delay = speed; } return (delay); } /* * Create object animator. */ Object_animate_actor_action::Object_animate_actor_action ( Game_object *o, int cy, // # of cycles. int spd // Time between frames. ) : obj(o), cycles(cy), speed(spd) { Game_window *gwin = Game_window::get_instance(); nframes = obj->get_num_frames(); } Object_animate_actor_action::Object_animate_actor_action ( Game_object *o, int nfr, int cy, int spd ) : obj(o), nframes(nfr), cycles(cy), speed(spd) { } /* * Handle tick of the clock. */ int Object_animate_actor_action::handle_event ( Actor *actor ) { if (!cycles) return 0; int frnum = (obj->get_framenum() + 1) % nframes; if (!frnum) // New cycle? --cycles; obj->change_frame(frnum); return (cycles ? speed : 0); } /* * Pick up/put down an object. */ Pickup_actor_action::Pickup_actor_action(Game_object *o, int spd) : obj(o), pickup(1), speed(spd), cnt(0), objpos(obj->get_tile()), dir(0) { } // To put down an object: Pickup_actor_action::Pickup_actor_action(Game_object *o, Tile_coord opos, int spd) : obj(o), pickup(0), speed(spd), cnt(0), objpos(opos), dir(0) { } /* * Pick up an item (or put it down). */ int Pickup_actor_action::handle_event ( Actor *actor ) { Game_window *gwin = Game_window::get_instance(); int frnum = -1; switch (cnt) { case 0: // Face object. dir = actor->get_direction(objpos); frnum = actor->get_dir_framenum(dir, Actor::standing); cnt++; break; case 1: // Bend down. frnum = actor->get_dir_framenum(dir, Actor::bow_frame); cnt++; if (pickup) { if (actor->distance(obj) > 8) { // No longer nearby. actor->notify_object_gone(obj); break; } gwin->add_dirty(obj); obj->remove_this(1); actor->add(obj, 1); } else { obj->remove_this(1); obj->move(objpos); gwin->add_dirty(obj); } break; default: return 0; // Done. } actor->change_frame(frnum); return speed; } /* * Action to turn towards a position or an object. */ Face_pos_actor_action::Face_pos_actor_action(Tile_coord p, int spd) : speed(spd), pos(p) { } Face_pos_actor_action::Face_pos_actor_action(Game_object *o, int spd) : speed(spd), pos(o->get_tile()) { } /* * Just turn to face a tile. */ int Face_pos_actor_action::handle_event ( Actor *actor ) { Game_window *gwin = Game_window::get_instance(); int dir = actor->get_direction(pos); int frnum = actor->get_dir_framenum(dir, Actor::standing); if (actor->get_framenum() == frnum) return 0; // There. actor->change_frame(frnum); return speed; } exult-1.2/configure.ac0000644000175000001440000005530110061526020010454 dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.53) AC_INIT(exult.cc) # --------------------------------------------------------------------- # System/version info # --------------------------------------------------------------------- PACKAGE=exult VER_MAJOR=1 VER_MINOR=2 VER_EXTRA= VERSION=$VER_MAJOR.$VER_MINOR$VER_EXTRA # check host/target systems # (build = system we're building on, host = system we're building for, # target = system the program we're building will build for) AC_CANONICAL_HOST AC_CANONICAL_TARGET AM_INIT_AUTOMAKE($PACKAGE,$VERSION,no-define) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Package Name]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Package Version]) AC_DEFINE_UNQUOTED(VER_MAJOR, "$VER_MAJOR", [Version Number Major]) AC_DEFINE_UNQUOTED(VER_MINOR, "$VER_MINOR", [Version Number Minor]) AC_DEFINE_UNQUOTED(VER_EXTRA, "$VER_EXTRA", [Version Number Extra]) AM_CONFIG_HEADER(config.h) AH_BOTTOM([ #ifdef ALPHA_LINUX_CXX #include "alpha_kludges.h" #endif #define USE_FMOPL_MIDI ]) # --------------------------------------------------------------------- # Host system settings # --------------------------------------------------------------------- AC_EXEEXT SYSLIBS="" ICON_FILE="" EXE_TARGET="exult$EXEEXT" EXULT_DATADIR="$datadir/exult" ARCH="" # determine windowing system from 'host' AC_MSG_CHECKING("windowing system") case "$host_os" in linux*) WINDOWING_SYSTEM="-DXWIN" if test "$host_vendor" = "embeddix"; then AC_MSG_RESULT(Qtopia (Sharp Zaurus)) CXXFLAGS="$CXXFLAGS -fsigned-char -DDISABLE_X11 -DQWS -D__zaurus__ -DUSE_FMOPL_MIDI" enable_kmid="no" enable_timidity="no" enable_exult_studio_support="no" enable_exult_studio="no" enable_gimp_plugin="no" enable_debug="no" enable_data="yes" else AC_MSG_RESULT(X11 (GNU/Linux)) fi ;; beos*) WINDOWING_SYSTEM="-DBEOS" AC_MSG_RESULT(BeOS) SYSLIBS="-lbe -lmidi" enable_kmid="no" enable_timidity="no" ;; mingw32* ) WINDOWING_SYSTEM="-DWIN32" AC_MSG_RESULT(Win32 (mingw32)) SYSLIBS="-lwinmm -lstdc++" ICON_FILE="win32/exultico.o" enable_kmid="no" enable_timidity="no" ;; cygwin* ) WINDOWING_SYSTEM="-DWIN32" AC_DEFINE(CYGWIN, 1, [Using Cygwin]) AC_MSG_RESULT(Win32 (cygwin)) CXXFLAGS="$CXXFLAGS -mno-cygwin" SYSLIBS="-lwinmm" ICON_FILE="win32/exultico.o" enable_kmid="no" enable_timidity="no" ;; openbsd* ) WINDOWING_SYSTEM="-DXWIN" AC_DEFINE(OPENBSD, 1, [Using OpenBSD]) AC_MSG_RESULT(X11 (OpenBSD)) SYSLIBS="-L/usr/X11R6/lib -lX11 -lXext -lXxf86vm -lXxf86dga" ;; freebsd* ) WINDOWING_SYSTEM="-DXWIN" AC_MSG_RESULT(X11 (FreeBSD)) CXXFLAGS="$CXXFLAGS -I/usr/X11R6/include" ;; solaris* ) WINDOWING_SYSTEM="-DXWIN" AC_MSG_RESULT(X11 (Solaris)) SYSLIBS="-lsocket -lX11" ;; darwin*) dnl We have a problem here: both MacOS X and Darwin report dnl the same signature "powerpc-apple-darwin*" - so we have dnl to do more to distinguish them. Plain Darwin will propably dnl use X-Windows; and it is of course lacking Cocoa. For dnl now I am lazy and do not add proper detection code. WINDOWING_SYSTEM="-DMACOSX" AC_DEFINE(MACOSX, 1, [Using MacOSX]) AC_MSG_RESULT(Mac OS X) SYSLIBS="-framework QuickTime" CXXFLAGS="$CXXFLAGS" EXULT_DATADIR="data" ARCH=macosx ;; *) WINDOWING_SYSTEM="-DXWIN" AC_MSG_RESULT(not sure... guessing X11) ;; esac AM_CONDITIONAL(MACOSX, test x$ARCH = xmacosx) # --------------------------------------------------------------------- # Compilers and other tools # --------------------------------------------------------------------- AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AM_PROG_LEX AC_PROG_YACC AM_CONDITIONAL(LEXYACC, test -n "$YACC") AC_ARG_WITH(cxx, [ --with-cxx=COMMAND Explicitly specify the C++ compiler to use], CXX="") if test -z "$CXX"; then AC_PROG_CXX else AC_PROG_CXX([$CXX]) fi AM_DISABLE_SHARED AM_PROG_LIBTOOL AC_SUBST(LIBTOOL_DEPS) # --------------------------------------------------------------------- # Compilation environment # --------------------------------------------------------------------- AC_DEFUN(AC_CHECK_ALPHA_LINUX_CXX, [ AC_MSG_CHECKING([for Alpha/Linux with DEC CXX]) AC_TRY_RUN([ int main(int argc, char **argv) { #if defined (__DECCXX) && defined(__linux__) && defined(__alpha__) return 0; #endif return 1; }], [ AC_MSG_RESULT([yes]) AC_DEFINE(ALPHA_LINUX_CXX, 1, [Using Alpha Linux with cxx]) ], AC_MSG_RESULT([no]), AC_MSG_RESULT([cross compiling- assuming \"no\"])) ]) # --------------------------------------------------------------------- # Check sizes of integer types. # Cross-compiling sizes set to 2,4,4,8. (May need to be changed...) # --------------------------------------------------------------------- AC_CHECK_SIZEOF(short, 2) AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(long, 4) AC_CHECK_SIZEOF(long long, 8) # --------------------------------------------------------------------- # Checks for header files. # --------------------------------------------------------------------- AC_HEADER_DIRENT AC_HEADER_STDC AC_CHECK_HEADERS(limits.h sys/time.h unistd.h) AC_CHECK_HEADERS(sys/types.h sys/socket.h netdb.h) AC_CHECK_HEADERS(sys/wait.h signal.h) AM_CONDITIONAL(HAVE_PNG, false) AC_CHECK_HEADERS(png.h, AM_CONDITIONAL(HAVE_PNG,true)) AC_CHECK_ALPHA_LINUX_CXX AC_LANG_CPLUSPLUS AC_CHECK_HEADERS(hash_map hash_set ext/hash_map ext/hash_set sstream) AC_LANG_C # --------------------------------------------------------------------- # Checks for typedefs, structures, and compiler characteristics. # --------------------------------------------------------------------- AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_HEADER_TIME AC_STRUCT_TM dnl If this is a gnu compiler, pass -Wall if test "$ac_cv_c_compiler_gnu" = "yes"; then CFLAGS="$CFLAGS -Wall" fi # --------------------------------------------------------------------- # Checks for library functions # --------------------------------------------------------------------- dnl Disabled this for now (undefined in autoconf < 2.5) dnl AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_CHECK_FUNCS([atexit dup2 getcwd isascii memchr memmove memset mkdir pow select socket strcasecmp strchr strstr strtol strtoul]) AC_MSG_CHECKING(for getaddrinfo()) AC_TRY_COMPILE([ #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETDB_H #include #endif ], [ struct addrinfo a; //getaddrinfo(0, 0, 0, 0); ], ac_cv_func_getaddrinfo=yes, ac_cv_func_getaddrinfo=no) AC_MSG_RESULT($ac_cv_func_getaddrinfo) if test x$ac_cv_func_getaddrinfo = xyes ; then AC_DEFINE(HAVE_GETADDRINFO, 1, [Have addrinfo/getaddrinfo]) fi AC_MSG_CHECKING(for mkstemp()) AC_TRY_LINK([ #if HAVE_UNISTD_H #include #endif #include ], [ mkstemp(0); ], ac_cv_func_mkstemp=yes, ac_cv_func_mkstemp=no) AC_MSG_RESULT($ac_cv_func_mkstemp) if test x$ac_cv_func_mkstemp = xyes ; then AC_DEFINE(HAVE_MKSTEMP, 1, [Have mkstemp]) fi AC_MSG_CHECKING(for snprintf()) AC_TRY_LINK([ #include ], [ snprintf(0,0,0,0); ], ac_cv_func_snprintf=yes, ac_cv_func_snprintf=no) AC_MSG_RESULT($ac_cv_func_snprintf) if test x$ac_cv_func_snprintf = xyes ; then AC_DEFINE(HAVE_SNPRINTF, 1, [Have snprintf]) AM_CONDITIONAL(HAVE_SNPRINTF,true) else AM_CONDITIONAL(HAVE_SNPRINTF,false) fi # do we need special X11 libraries? AC_MSG_CHECKING(for special X11 libraries) if test x$x_libraries = xNONE; then AC_MSG_RESULT(no) unset x_libraries else x_libraries="-L$x_libraries -lX11 -lXext" AC_MSG_RESULT($x_libraries) AC_SUBST(x_libraries) fi # --------------------------------------------------------------------- # SDL # --------------------------------------------------------------------- SDL_VERSION=1.2.0 AM_PATH_SDL($SDL_VERSION, :, AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) ) AC_CHECK_LIB(SDL_mixer, Mix_QuickLoad_RAW, SDL_LIBS="$SDL_LIBS -lSDL_mixer", AC_MSG_ERROR([*** SDL_mixer version 1.2.4 or later not found!]), $SDL_LIBS ) # --------------------------------------------------------------------- # Optional components # --------------------------------------------------------------------- # Timidity MIDI driver AC_MSG_CHECKING(whether to enable timidity) AC_ARG_ENABLE(timidity, [ --enable-timidity Use timidity [default yes]],,enable_timidity=yes) if test x$enable_timidity = xyes; then AC_MSG_RESULT(yes) AC_CHECK_PROG(HAVE_TIMIDITY_BIN, timidity, found it, not found) if test "$HAVE_TIMIDITY_BIN" = "found it"; then AC_DEFINE(HAVE_TIMIDITY_BIN, 1, [Have timidity binary]) fi else AC_MSG_RESULT(no) fi # zipped savegame support AC_ARG_ENABLE(zip-support, [ --enable-zip-support Enable zipped savegame support [default yes]],,enable_zip_support=yes) if test x$enable_zip_support = xyes ; then AC_CHECK_HEADER(zlib.h,,enable_zip_support=no) fi AC_MSG_CHECKING(for zipped savegame support) if test x$enable_zip_support = xyes ; then # disabled for now (non-portable): # link statically against zlib if using gcc # if test x$GCC = xyes ; then # ZLIB_LIBS="-Wl,-Bstatic -lz -Wl,-Bdynamic" # else ZLIB_LIBS="-lz" # fi AC_DEFINE(HAVE_ZIP_SUPPORT, 1, [Have zip support]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi # OpenGL rendering AC_ARG_ENABLE(opengl, [ --enable-opengl Enable OpenGL rendering support [EXPERIMENTAL]],,enable_opengl=no) AC_MSG_CHECKING(for OpenGL rendering support) if test x$enable_opengl = xyes; then AC_DEFINE(HAVE_OPENGL, 1, [Have OpenGL]) # Mac OS X gets OpenGL through a framework (which appears to be pulled in by SDL) if test x$ARCH != xmacosx; then OPENGL_LIBS="-lGL" fi AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi # --------------------------------------------------------------------- # support for Exult Studio # --------------------------------------------------------------------- AC_MSG_CHECKING(whether to enable support for Exult Studio) AC_ARG_ENABLE(exult-studio-support, [ --enable-exult-studio-support Enable ExultStudio support [default yes]],,enable_exult_studio_support=yes) if test "$WINDOWING_SYSTEM" != -DXWIN ; then enable_exult_studio_support=no fi if test x$enable_exult_studio_support = xyes ; then AC_MSG_RESULT(yes) AC_DEFINE(USE_EXULTSTUDIO, 1, [Use ExultStudio]) else AC_MSG_RESULT(no) fi # --------------------------------------------------------------------- # Memory allocation scheme # --------------------------------------------------------------------- AC_MSG_CHECKING(checking memory allocation scheme) # For the alternate allocator AC_ARG_ENABLE(alternate-allocator, [ --enable-alternate-allocator Use alternate memory allocator [default no]],,enable_alternate_allocator=no) if test x$enable_alternate_allocator = xyes; then AC_DEFINE(WANT_ALTERNATE_ALLOCATOR, 1, [Use alternate allocator]) fi # For storage initialisation AC_ARG_ENABLE(storage-initialisation, [ --enable-storage-initialisation Clear storage when allocated [default no]],,enable_storage_initialisation=no) if test x$enable_storage_initialisation = xyes; then AC_DEFINE(WANT_ALTERNATE_ALLOCATOR, 1, [Use alternate allocator]) AC_DEFINE(INITIALISE_ALLOCATED_BLOCKS,0, [Initialize allocated blocks]) fi # For storage poisoning AC_ARG_ENABLE(storage-poisoning, [ --enable-storage-poisoning Poison storage when allocated [default no]],,enable_storage_poisoning=no) if test x$enable_storage_poisoning = xyes; then if test x$enable_storage_initialisation = xyes; then AC_MSG_RESULT(poisoned. (Disabling storage initialisation. Can't poison and init to zero.)) fi AC_DEFINE(WANT_ALTERNATE_ALLOCATOR, 1, [Use alternate allocator]) AC_DEFINE(POISON_ALLOCATED_BLOCKS, 1, [Poison allocated blocks]) fi # output result if test x$enable_storage_poisoning = xyes; then if test x$enable_storage_initialisation = xno; then AC_MSG_RESULT(poisoned) fi else if test x$enable_storage_initialisation = xyes; then AC_MSG_RESULT(initialized) else if test x$enable_alternate_allocator = xyes; then AC_MSG_RESULT(alternate) else AC_MSG_RESULT(normal) fi fi fi # --------------------------------------------------------------------- # Debugging options # --------------------------------------------------------------------- # basic debugging mode AC_ARG_ENABLE(debug, [ --enable-debug Enable debug messages [default no]],,enable_debug=no) AC_MSG_CHECKING(whether to enable debugging mode) if test x$enable_debug = xyes; then AC_MSG_RESULT(yes) AC_DEFINE(DEBUG, 1, [Enable debug mode]) DEBUG_FLAGS="-g" else AC_MSG_RESULT(no) DEBUG_FLAGS="-O2" fi # optimized debugging mode AC_ARG_ENABLE(optimized-debug, [ --enable-optimized-debug Enable optimized debug build [default no]],,enable_optimized_debug=no) AC_MSG_CHECKING(whether to do an optimized debug build) if test x$enable_optimized_debug = xyes; then AC_MSG_RESULT(yes) AC_DEFINE(DEBUG, 1, [Enable debug mode]) DEBUG_FLAGS="-g -O2 -fno-default-inline -fno-inline" else AC_MSG_RESULT(no) fi # SDL parachute? AC_ARG_ENABLE(sdl-parachute, [ --enable-sdl-parachute Use SDL parachute [default yes]],,enable_sdl_parachute=yes) AC_MSG_CHECKING(if we should disable the SDL parachute) if test x$enable_sdl_parachute = xno; then AC_MSG_RESULT(yes) AC_DEFINE(NO_SDL_PARACHUTE, 1, [Disable SDL parachute]) else AC_MSG_RESULT(no) fi # Usecode debugger #AC_ARG_ENABLE(usecode-debugger, [ --enable-usecode-debugger Support for usecode debugging [default no]],,enable_usecode_debugger=no) #AC_MSG_CHECKING(whether to enable the usecode debugger) #if test x$enable_usecode_debugger = xyes; then # AC_MSG_RESULT(yes) # AC_DEFINE(USECODE_DEBUGGER, 1, [Enable Usecode debugging]) #else # AC_MSG_RESULT(no) #fi # --------------------------------------------------------------------- # Warning level # --------------------------------------------------------------------- # determine warning level AC_MSG_CHECKING(warning level) WARNING_LEVEL="normal" # more warnings AC_ARG_ENABLE(warnings, [ --enable-warnings Enable all warnings [default no]],,enable_warnings=no) if test x$enable_warnings = xyes; then DEBUG_FLAGS="$DEBUG_FLAGS -Wall -O -Wunused -Wuninitialized -Woverloaded-virtual -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Winline" WARNING_LEVEL="all" fi # Weep into your beer warnings AC_ARG_ENABLE(awful-warnings, [ --enable-awful-warnings Enable warnings for violations of Scott Meyers' Effective C++ style guidelines [default no]],,enable_awful_warnings=no) if test x$enable_awful_warnings = xyes; then DEBUG_FLAGS="$DEBUG_FLAGS -Weffc++" if test x$WARNING_LEVEL = xall; then WARNING_LEVEL="all, including Scott Meyers' 'effective C++'" else WARNING_LEVEL="Scott Meyers' 'effective C++'" fi fi AC_ARG_ENABLE(paranoid-warnings, [ --enable-paranoid-warnings Enable paranoid warnings [default no]],,enable_paranoid_warnings=no) if test x$enable_paranoid_warnings = xyes; then WARNINGS="-Wall -W -Wcast-qual -Wwrite-strings -Wconversion -Wredundant-decls -Winline -Wdisabled-optimization -fcheck-new -Wctor-dtor-privacy -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual" # DEBUG_FLAGS="$DEBUG_FLAGS -Wall -O -Wunused -Wuninitialized -Woverloaded-virtual -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Winline" WARNING_LEVEL="paranoid" fi # Output result AC_MSG_RESULT($WARNING_LEVEL) # Ignore long-long warnings (for SDL header files...) AC_ARG_ENABLE(long-long-warnings, [ --enable-long-long-warnings Enable long long warnings- needed for Compaq's cxx with GNU ld [default no]], ,,enable_long_long_warnings=no) AC_MSG_CHECKING(if we should disable long-long warnings) if test x$enable_long_long_warnings = xyes; then AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) DEBUG_FLAGS="$DEBUG_FLAGS -Wno-long-long" fi # Heavy namespaces. Most installations probably can't take this option AC_ARG_ENABLE(std-namespace, [ --enable-std-namespace Honour the std namespace. [default no]],,enable_std_namespace=no) AC_MSG_CHECKING(if we should honour the std namespace) if test x$enable_std_namespace = xyes; then AC_MSG_RESULT(yes) DEBUG_FLAGS="$DEBUG_FLAGS -fhonor-std" else AC_MSG_RESULT(no) fi # repo AC_ARG_ENABLE(repo, [ --enable-repo Repo type template instantiation. [default no]],,enable_repo=no) AC_MSG_CHECKING(if we should use repo type template instantiation) if test x$enable_repo = xyes; then AC_MSG_RESULT(yes) DEBUG_FLAGS="$DEBUG_FLAGS -frepo" else AC_MSG_RESULT(no) fi # external templates (alt) AC_ARG_ENABLE(external-templates, [ --enable-external-templates external template instantiation. [default no]],,enable_external_templates=no) AC_MSG_CHECKING(if we should use (alternate) external template instantiation) if test x$enable_external_templates = xyes; then AC_MSG_RESULT(yes) DEBUG_FLAGS="$DEBUG_FLAGS -falt-external-templates" else AC_MSG_RESULT(no) fi # Architecture dependent optimisations AC_MSG_CHECKING(if we should optimise for MMX) AC_ARG_ENABLE(timidity, [ --enable-mmx Use MMX optimisations [default no]],,enable_mmx=no) if test x$enable_mmx = xyes; then AC_MSG_RESULT(yes) CXXFLAGS="$CXXFLAGS -mmmx" else AC_MSG_RESULT(no) fi # Architecture dependent optimisations AC_MSG_CHECKING(if we should optimise for 3DNOW) AC_ARG_ENABLE(timidity, [ --enable-3dnow Use 3DNOW optimisations [default no]],,enable_3dnow=no) if test x$enable_3dnow = xyes; then AC_MSG_RESULT(yes) CXXFLAGS="$CXXFLAGS -m3dnow" else AC_MSG_RESULT(no) fi # -------------------- # External features # -------------------- # Build any external programs? AC_ARG_ENABLE(tools, [ --disable-tools Only build the main program],,enable_tools=yes) AC_MSG_CHECKING(whether to build only the main program) if test x$enable_tools = xno; then AC_MSG_RESULT(yes) AM_CONDITIONAL(BUILD_TOOLS, false) enable_gtk_interface=no enable_gimp_plugin=no enable_compiler=no else AM_CONDITIONAL(BUILD_TOOLS, true) AC_MSG_RESULT(no) fi # Build compiler? AC_ARG_ENABLE(compiler, [ --enable-compiler Build the usecode compiler [default yes]],,enable_compiler=yes) AC_MSG_CHECKING(whether to build the usecode compiler) if test x$enable_compiler = xno; then AC_MSG_RESULT(no) AM_CONDITIONAL(BUILD_COMPILER, false) else AC_MSG_RESULT(yes) AM_CONDITIONAL(BUILD_COMPILER, true) fi # Build data files? AC_ARG_ENABLE(data, [ --enable-data Create the data files [default yes]],,enable_data=yes) AC_MSG_CHECKING(whether to build the data files) if test x$enable_data = xno; then AC_MSG_RESULT(no) AM_CONDITIONAL(DATA_FILES, false) else AM_CONDITIONAL(DATA_FILES, true) AC_MSG_RESULT(yes) fi # pkg-config AC_MSG_CHECKING(for pkg-config) if test "x`pkg-config --version`" = "x"; then AC_MSG_RESULT(no pkg-config) else AC_MSG_RESULT(ok) AC_MSG_CHECKING(for GTK+/GLADE development files) if pkg-config --atleast-version 2.0 libglade-2.0; then have_glade=yes AC_MSG_RESULT(yes...) AC_DEFINE(HAVE_GLADE, 1, [Have Glade support libraries]) GLADE_INCLUDES=`pkg-config --cflags libglade-2.0` GLADE_LIBS=`pkg-config --libs libglade-2.0` AC_SUBST(GLADE_INCLUDES) AC_SUBST(GLADE_LIBS) else have_glade=no AC_MSG_RESULT(no gtk+/libglade) fi fi # Freetype2 (optional, used in ExultStudio, shapes/fontgen.cc) AC_PATH_PROG(FT2CONFIG, freetype-config) if test -n "$FT2CONFIG"; then AC_DEFINE(HAVE_FREETYPE2, 1, [Have freetype2]) FREETYPE2_LIBS=`freetype-config --libs` AC_SUBST(FREETYPE2_LIBS) FREETYPE2_INCLUDES=`freetype-config --cflags` AC_SUBST(FREETYPE2_INCLUDES) fi # exult-studio AC_ARG_ENABLE(exult-studio, [ --enable-exult-studio Build Exult Studio [default no]],,enable_exult_studio=no) AC_MSG_CHECKING(whether to build Exult Studio) if test x$enable_exult_studio = xyes; then AC_MSG_RESULT(yes) if test x$have_glade = xno; then echo "Umm, but we don't have any libglade stuff." echo "Try again, either with libglade, or with --disable-exult-studio" exit 1 fi AM_CONDITIONAL(BUILD_STUDIO, true) else AM_CONDITIONAL(BUILD_STUDIO, false) AC_MSG_RESULT(no) fi # GIMP plugin AM_CONDITIONAL(GIMP_PLUGIN, false) AC_ARG_ENABLE(gimp-plugin, [ --enable-gimp-plugin Build the GIMP plugin [default no]],,enable_gimp_plugin=no) AC_MSG_CHECKING(whether to build the GIMP plugin) if test x$enable_gimp_plugin = xyes; then AC_MSG_RESULT(yes) AC_MSG_CHECKING(for gimptool) AC_CHECK_PROGS(GIMPTOOL, gimptool-2.0 gimptool-1.3 gimptool-1.2 gimptool) if test -z "$GIMPTOOL"; then AC_MSG_RESULT(no, not building GIMP plugin) else AC_MSG_CHECKING(for GIMP version) gimp_version=`$GIMPTOOL --version | awk 'BEGIN { FS = "."; } { print $1 * 1000 + $2*100+$3;}'` if test "$gimp_version" -ge 1312; then AC_MSG_RESULT(found >= 1.3.12) AC_SUBST(GIMPTOOL) AM_CONDITIONAL(GIMP_PLUGIN, true) CPPFLAGS="$save_cppflags" GIMP_PLUGIN_PREFIX=`$GIMPTOOL --gimpplugindir` GIMP_PLUGIN_PREFIX="$GIMP_PLUGIN_PREFIX/plug-ins" AC_SUBST(GIMP_PLUGIN_PREFIX) AC_DEFINE(HAVE_GIMP, 1, [Have GIMP]) GIMP_INCLUDES=`$GIMPTOOL --cflags` GIMP_LIBS=`$GIMPTOOL --libs` AC_SUBST(GIMP_INCLUDES) AC_SUBST(GIMP_LIBS) elif test "$gimp_version" -ge 1200 -a \ "$gimp_version" -lt 1300; then AC_MSG_RESULT(found 1.2.x) AC_SUBST(GIMPTOOL) AM_CONDITIONAL(GIMP_PLUGIN, true) CPPFLAGS="$save_cppflags" GIMP_PLUGIN_PREFIX=`$GIMPTOOL --gimpplugindir` GIMP_PLUGIN_PREFIX="$GIMP_PLUGIN_PREFIX/plug-ins" AC_SUBST(GIMP_PLUGIN_PREFIX) AC_DEFINE(HAVE_GIMP, 1, [Have GIMP]) AC_DEFINE(HAVE_GIMP_1_2, 1, [Have GIMP 1.2.x]) GIMP_INCLUDES=`$GIMPTOOL --cflags` GIMP_LIBS=`$GIMPTOOL --libs` AC_SUBST(GIMP_INCLUDES) AC_SUBST(GIMP_LIBS) else AC_MSG_RESULT(found < 1.3.12 - disabling plugin) fi fi else AC_MSG_RESULT(no) fi # ------------------ # Generate output # ------------------ AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) AC_SUBST(WINDOWING_SYSTEM) AC_SUBST(KMID_INCLUDES) AC_SUBST(KMID_LIBS) AC_SUBST(EXE_TARGET) AC_SUBST(EXULT_DATADIR) AC_SUBST(SYSLIBS) AC_SUBST(ICON_FILE) AC_SUBST(DEBUG_FLAGS) AC_SUBST(ZLIB_LIBS) AC_SUBST(OPENGL_LIBS) AC_SUBST(WARNINGS) AC_OUTPUT([ exult.spec Info.plist Makefile audio/Makefile audio/midi_drivers/Makefile conf/Makefile files/Makefile files/zip/Makefile gumps/Makefile pathfinder/Makefile flic/Makefile tools/Makefile data/Makefile docs/Makefile desktop/Makefile objs/Makefile imagewin/Makefile shapes/Makefile usecode/Makefile usecode/compiler/Makefile usecode/ucxt/Makefile usecode/ucxt/Docs/Makefile usecode/ucxt/data/Makefile usecode/ucxt/include/Makefile usecode/ucxt/src/Makefile mapedit/Makefile server/Makefile debian/Makefile ]) dnl **************** dnl Configure Status dnl **************** echo echo Exult v$VERSION echo echo SDL ....................... : `$SDL_CONFIG --version` if test x$have_glade = xyes; then echo GLIB ...................... : `pkg-config --modversion glib-2.0` echo GTK+ ...................... : `pkg-config --modversion gtk+-2.0` echo libGlade .................. : `pkg-config --modversion libglade-2.0` echo fi echo Build tools................ : $enable_tools echo Build ExultStudio.......... : $enable_exult_studio echo echo "Now type 'make' to build Exult" exult-1.2/cheat.cc0000644000175000001440000005127610054030527007574 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "SDL_mouse.h" #include "cheat.h" #include "exult.h" #include "gamewin.h" #include "gameclk.h" #include "gamemap.h" #include "party.h" #include "Configuration.h" #include "game.h" #include "actors.h" #include "mouse.h" #include "browser.h" #include "soundtest.h" #include "cheat_screen.h" #include "Gump_manager.h" #include "Gump.h" #include "drag.h" #include "effects.h" #ifdef USE_EXULTSTUDIO /* Only needed for exult studio. */ #include "server.h" #include "servemsg.h" #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #endif // WIN32 #endif //USE_EXULTSTUDIO #ifndef UNDER_CE using std::cout; using std::endl; using std::strcpy; using std::strcat; #endif Cheat cheat; Cheat::Cheat() { enabled = false; god_mode = false; wizard_mode = false; map_editor = false; tile_grid = false; edit_mode = move; edit_lift = 0; edit_shape = edit_frame = edit_chunknum = 0; infravision = false; pickpocket = false; grab_actor = true; browser = NULL; tester = NULL; } Cheat::~Cheat() { if (browser) delete browser; if (tester) delete tester; if (cscreen) delete cscreen; } void Cheat::init (void) { enabled = false; std::string cheating; config->value("config/gameplay/cheat",cheating,"no"); if (cheating == "yes") enabled = true; } void Cheat::finish_init (void) { gwin = Game_window::get_instance(); eman = gwin->get_effects(); browser = new ShapeBrowser(); tester = new SoundTester(); cscreen = new CheatScreen(); if (enabled) cout << "Cheats enabled." << endl; } void Cheat::set_enabled (bool en) { enabled = en; std::string cheating; if(enabled) cheating = "yes"; else cheating = "no"; config->set("config/gameplay/cheat",cheating,true); } void Cheat::toggle_god (void) { if (!enabled) return; god_mode = !god_mode; if (god_mode) { eman->center_text("God Mode Enabled"); Actor *party[9]; // Set attack mode to 'nearest'. int cnt = gwin->get_party(party, 1); for (int i = 0; i < cnt; i++) party[i]->set_attack_mode(Actor::nearest); } else eman->center_text("God Mode Disabled"); } void Cheat::toggle_wizard (void) { if (!enabled) return; wizard_mode = !wizard_mode; if (wizard_mode) eman->center_text("Archwizard Mode Enabled"); else eman->center_text("Archwizard Mode Disabled"); } void Cheat::toggle_map_editor (void) { if (!enabled) return; map_editor = !map_editor; if (map_editor) { eman->center_text("Map Editor Mode Enabled"); // Stop time. gwin->set_time_stopped(-1); #ifdef USE_EXULTSTUDIO /* Launch ExultStudio! */ if (!gwin->paint_eggs) // Show eggs too. { gwin->paint_eggs = 1; gwin->paint(); } if (client_socket < 0 && !gwin->get_win()->is_fullscreen()) { char cmnd[256]; // Set up command. strcpy(cmnd, "exult_studio -x"); std::string data_path; config->value("config/disk/data_path",data_path,EXULT_DATADIR); strcat(cmnd, data_path.c_str());// Path to where .glade file should be. strcat(cmnd, " -g"); // Now want game name. std::string gamenamestr = Game::get_gametitle(); strcat(cmnd, gamenamestr.c_str()); strcat(cmnd, " &"); cout << "Executing: " << cmnd << endl; #ifndef WIN32 int ret = system(cmnd); if (ret == 127 || ret == -1) cout << "Couldn't run Exult Studio" << endl; #elif !(defined(UNDER_CE)) PROCESS_INFORMATION pi; STARTUPINFO si; std::memset (&si, 0, sizeof(si)); si.cb = sizeof(si); int ret = CreateProcess (NULL, cmnd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (!ret) cout << "Couldn't run Exult Studio" << endl; #endif } #endif } else { clear_selected(); // Selection goes away. eman->center_text("Map Editor Mode Disabled"); // Stop time-stop. gwin->set_time_stopped(0); } } void Cheat::toggle_tile_grid (void) { if (!enabled) return; tile_grid = !tile_grid; gwin->set_all_dirty(); } void Cheat::set_edit_lift(int lift) { if (!enabled) return; edit_lift = lift; gwin->set_all_dirty(); } void Cheat::set_edit_shape(int sh, int fr) { edit_shape = sh; edit_frame = fr; } void Cheat::toggle_infravision (void) { if (!enabled) return; infravision = !infravision; if (infravision) { eman->center_text("Infravision Enabled"); gwin->get_pal()->set(0); } else eman->center_text("Infravision Disabled"); } void Cheat::toggle_pickpocket (void) { if (!enabled) return; pickpocket = !pickpocket; if (pickpocket) { eman->center_text("Pick Pocket Enabled"); gwin->get_pal()->set(0); } else eman->center_text("Pick Pocket Disabled"); } void Cheat::toggle_hack_mover (void) { if (!enabled) return; hack_mover = !hack_mover; if (hack_mover) { eman->center_text("Hack mover Enabled"); } else { eman->center_text("Hack mover Disabled"); } } void Cheat::change_gender (void) const { if (!enabled) return; if (gwin->get_main_actor()->get_type_flag(Actor::tf_sex)) { gwin->get_main_actor()->clear_type_flag(Actor::tf_sex); eman->center_text("Avatar is now male"); } else { gwin->get_main_actor()->set_type_flag(Actor::tf_sex); eman->center_text("Avatar is now female"); } gwin->set_all_dirty(); } void Cheat::toggle_eggs (void) const { if (!enabled) return; gwin->paint_eggs = !gwin->paint_eggs; if(gwin->paint_eggs) eman->center_text("Eggs display enabled"); else eman->center_text("Eggs display disabled"); gwin->paint(); } void Cheat::toggle_Petra (void) const { if (!enabled || (Game::get_game_type() != SERPENT_ISLE)) return; if (gwin->get_main_actor()->get_flag(Obj_flags::petra)) gwin->get_main_actor()->clear_flag(Obj_flags::petra); else gwin->get_main_actor()->set_flag(Obj_flags::petra); gwin->set_all_dirty(); } void Cheat::toggle_naked (void) const { if (!enabled || (Game::get_game_type() != SERPENT_ISLE)) return; if (gwin->get_main_actor()->get_siflag(Actor::naked)) gwin->get_main_actor()->clear_siflag(Actor::naked); else gwin->get_main_actor()->set_siflag(Actor::naked); gwin->set_all_dirty(); } void Cheat::change_skin (void) const { if (!enabled || (Game::get_game_type() != SERPENT_ISLE && !Shape_manager::get_instance()->can_use_multiracial())) return; int color = gwin->get_main_actor()->get_skin_color(); if (GAME_BG) color = (color+1) %4; else color = (color+1) %3; gwin->get_main_actor()->set_skin_color(color); gwin->set_all_dirty(); } void Cheat::levelup_party (void) const { if (!enabled) return; Actor* party[9]; int level, newexp; bool leveledup = false; // get party, including Avatar int cnt = gwin->get_party(party, 1); for (int i=0; iget_level(); if (level < 10) { leveledup = true; newexp = 25 * (2 << level); // one level higher party[i]->set_property(Actor::exp, newexp); } } if (leveledup) { eman->center_text("Level up!"); } else { eman->center_text("Maximum level reached"); } } void Cheat::fake_time_period (void) const { if (!enabled) return; gwin->get_clock()->fake_next_period(); eman->center_text("Game clock incremented"); } void Cheat::dec_skip_lift (void) const { if (!enabled) return; if (gwin->skip_lift == 16) gwin->skip_lift = 11; else gwin->skip_lift--; if (gwin->skip_lift < 0) // 0 means 'terrain-editing'. gwin->skip_lift = 16; #ifdef DEBUG cout << "Skip_lift = " << gwin->skip_lift << endl; #endif gwin->paint(); } void Cheat::set_skip_lift (int skip) const { if (!enabled) return; if ((skip >= 1 && skip <= 11) || skip == 16) gwin->skip_lift = skip; #ifdef DEBUG cout << "Skip_lift = " << gwin->skip_lift << endl; #endif gwin->paint(); } /* * Tell EStudio whether there's a selection and clipboard. */ void Cheat::send_select_status() { #ifdef USE_EXULTSTUDIO if (client_socket >= 0) { unsigned char msg[2]; msg[0] = selected.empty() ? 0 : 1; msg[1] = clipboard.empty() ? 0 : 1; Exult_server::Send_data(client_socket, Exult_server::select_status, &msg[0], 2); } #endif } /* * Add an object to the selected list without checking. */ void Cheat::append_selected(Game_object *obj) { selected.push_back(obj); if (selected.size() == 1) // First one? send_select_status(); } /* * Toggle the selection of an object. */ void Cheat::toggle_selected(Game_object *obj) { if (!obj->get_owner()) gwin->add_dirty(obj); else gwin->set_all_dirty(); // In list? for (Game_object_vector::iterator it = selected.begin(); it != selected.end(); ++it) if (*it == obj) { // Yes, so remove it. selected.erase(it); if (selected.empty()) // Last one? send_select_status(); return; } selected.push_back(obj); // No, so add it. if (selected.size() == 1) // 1st one? send_select_status(); } /* * Clear out selection. */ void Cheat::clear_selected() { if (selected.empty()) return; for (Game_object_vector::iterator it = selected.begin(); it != selected.end(); ++it) { Game_object *obj = *it; if (!obj->get_owner()) gwin->add_dirty(obj); else gwin->set_all_dirty(); } selected.clear(); send_select_status(); } /* * Delete all selected objects. */ void Cheat::delete_selected() { if (selected.empty()) return; while (!selected.empty()) { Game_object *obj = selected.back(); selected.pop_back(); if (obj->get_owner()) gwin->add_dirty(obj); else // In a gump? gwin->set_all_dirty(); obj->remove_this(); } send_select_status(); } /* * Move the selected objects by given #tiles. Objects inside another are * treated as being at the location of their owner. */ void Cheat::move_selected(int dx, int dy, int dz) { if (selected.empty()) return; // Nothing to do. std::vector tiles; // Store locations here. int lowz = 1000, highz = -1000; // Get min/max lift. // Remove & store old locations. Game_object_vector::iterator it; for (it = selected.begin(); it != selected.end(); ++it) { Game_object *obj = *it; Game_object *owner = obj->get_outermost(); // Get location. Use owner if inside. Tile_coord tile = owner->get_tile(); tiles.push_back(tile); if (obj == owner) // Not inside? gwin->add_dirty(obj); else // In a gump. Repaint all for now. gwin->set_all_dirty(); obj->remove_this(true); if (tile.tz < lowz) lowz = tile.tz; if (tile.tz > highz) highz = tile.tz; } if (lowz + dz < 0) // Too low? dz = -lowz; if (highz + dz > 15) // Too high? dz = 15 - highz; // Add back in new locations. for (it = selected.begin(); it != selected.end(); ++it) { Tile_coord tile = tiles[it - selected.begin()]; int newtx = (tile.tx + dx + c_num_tiles)%c_num_tiles; int newty = (tile.ty + dy + c_num_tiles)%c_num_tiles; int newtz = (tile.tz + dz + 16)%16; (*it)->set_invalid(); (*it)->move(newtx, newty, newtz); } } /* * Want lowest, southmost, then eastmost first. */ class Clip_compare { public: bool operator()(const Game_object *o1, const Game_object *o2) { Tile_coord t1 = o1->get_tile(), t2 = o2->get_tile(); if (t1.tz != t2.tz) return t1.tz < t2.tz; else if (t1.ty != t2.ty) return t1.ty > t2.ty; else return t1.tx >= t2.tx; } }; /* * Cut/copy. */ void Cheat::cut(bool copy) { if (selected.empty()) return; // Nothing selected. bool clip_was_empty = clipboard.empty(); Game_object_vector::iterator it; // Clear out old clipboard. for (it = clipboard.begin(); it != clipboard.end(); ++it) gwin->delete_object(*it); // Careful here. clipboard.resize(0); clipboard.reserve(selected.size()); if (!copy) // Removing? Force repaint. gwin->set_all_dirty(); // Go through selected objects. for (it = selected.begin(); it != selected.end(); ++it) { Game_object *obj = *it; Tile_coord t = obj->get_outermost()->get_tile(); if (copy) // TEST+++++REALLY want a 'clone()'. obj = gwin->get_map()->create_ireg_object( obj->get_shapenum(), obj->get_framenum()); else // Cut: Remove but don't delete. obj->remove_this(true); // Set pos. & add to list. obj->set_shape_pos(t.tx%c_tiles_per_chunk, t.ty%c_tiles_per_chunk); obj->set_chunk(t.tx/c_tiles_per_chunk, t.ty/c_tiles_per_chunk); clipboard.push_back(obj); } // Sort. std::sort(selected.begin(), selected.end(), Clip_compare()); if (!copy) // Cut? Remove selection. clear_selected(); // (This will send status.) else if (clip_was_empty) // First clipboard object? send_select_status(); } /* * Create an object as moveable (IREG) or fixed. * ++++++++Goes away when we have obj->clone()++++++++++ */ static Game_object *Create_object ( Game_window *gwin, int shape, int frame // What to create. ) { Shape_info& info = ShapeID::get_info(shape); int sclass = info.get_shape_class(); // Is it an ireg (changeable) obj? bool ireg = (sclass != Shape_info::unusable && sclass != Shape_info::building); Game_object *newobj; if (ireg) newobj = gwin->get_map()->create_ireg_object(info, shape, frame, 0, 0, 0); else newobj = gwin->get_map()->create_ifix_object(shape, frame); return newobj; } /* * Paste selection. */ void Cheat::paste ( int mx, int my // Mouse position. ) { if (clipboard.empty()) return; // Nothing there. // Use lowest/south/east for position. Tile_coord hot = clipboard[0]->get_tile(); clear_selected(); // Remove old selected. #if 0 // First see if spot is in a gump. Gump *on_gump = gwin->get_gump_man()->find_gump(mx, my); #endif Game_object_vector::iterator it; for (it = clipboard.begin(); it != clipboard.end(); ++it) { Game_object *obj = *it; Tile_coord t = obj->get_tile(); // Figure spot rel. to hot-spot. int liftpix = ((t.tz - hot.tz)*c_tilesize)/2; int x = mx + (t.tx - hot.tx)*c_tilesize - liftpix, y = my + (t.ty - hot.ty)*c_tilesize - liftpix; // +++++Use clone(). obj = Create_object(gwin, obj->get_shapenum(), obj->get_framenum()); Dragging_info drag(obj); if (drag.drop(x, y, true)) // (Dels if it fails.) #if 0 bool ok = false; if (on_gump) ok = on_gump->add(obj, mx, my, x, y)!=0; else // Try to drop at increasing hts. for (int lift = edit_lift; !ok && lift <= 11; lift++) ok = gwin->drop_at_lift(obj, x, y, lift); if (ok) #endif append_selected(obj); #if 0 else delete obj; #endif } gwin->set_all_dirty(); // Just repaint all. } /* * Prompt for spot to paste to. */ void Cheat::paste() { if (clipboard.empty()) return; int x, y; // Allow dragging while here: if (Get_click(x, y, Mouse::greenselect, 0, true)) paste(x, y); } const int border=2; // For showing map. const int worldsize = c_tiles_per_chunk * c_num_chunks; /* * Show 'cheat' map. */ class Cheat_map : public Game_singletons, public Paintable { public: int x, y; // Where it's painted. int w, h; Shape_frame *map; virtual void paint() { #if 0 ShapeID mapid(game->get_shape("sprites/map"), 0, SF_SPRITES_VGA); #else ShapeID mapid(game->get_shape("sprites/cheatmap"), 1, SF_GAME_FLX); #endif map = mapid.get_shape(); // Get coords. for centered view. w = map->get_width(); h = map->get_height(); x = (gwin->get_width() - w)/2 + map->get_xleft(); y = (gwin->get_height() - h)/2 + map->get_yabove(); mapid.paint_shape(x, y, 1); // mark current location int xx, yy; Tile_coord t = gwin->get_main_actor()->get_tile(); xx = ((t.tx * (w - border*2)) / worldsize); yy = ((t.ty * (h - border*2)) / worldsize); xx += x - map->get_xleft() + border; yy += y - map->get_yabove() + border; gwin->get_win()->fill8(255, 1, 5, xx, yy - 2); gwin->get_win()->fill8(255, 5, 1, xx - 2, yy); } }; void Cheat::map_teleport (void) const { if (!enabled) return; Cheat_map map; int xx, yy; if (!Get_click(xx, yy, Mouse::greenselect, 0, false, &map)) { gwin->paint(); return; } xx -= map.x - map.map->get_xleft() + border; yy -= map.y - map.map->get_yabove() + border; Tile_coord t; t.tx = static_cast(((xx + 0.5)*worldsize) / (map.w - 2*border)); t.ty = static_cast(((yy + 0.5)*worldsize) / (map.h - 2*border)); // World-wrapping. t.tx = (t.tx + c_num_tiles)%c_num_tiles; t.ty = (t.ty + c_num_tiles)%c_num_tiles; cout << "Teleporting to " << t.tx << "," << t.ty << "!" << endl; t.tz = 0; gwin->teleport_party(t); eman->center_text("Teleport!!!"); } void Cheat::cursor_teleport (void) const { if (!enabled) return; int x, y; SDL_GetMouseState(&x, &y); x /= gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); y /= gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); Tile_coord t(gwin->get_scrolltx() + x/c_tilesize, gwin->get_scrollty() + y/c_tilesize, 0); gwin->teleport_party(t); eman->center_text("Teleport!!!"); } void Cheat::create_coins (void) const { if (!enabled) return; gwin->get_main_actor()->add_quantity(100, 644); eman->center_text("Added 100 gold coins"); } void Cheat::create_last_shape (void) const { if (!enabled) return; int current_shape = 0; int current_frame = 0; if(browser->get_shape(current_shape, current_frame)) { gwin->get_main_actor()->add( gwin->get_map()->create_ireg_object( current_shape, current_frame), 1); eman->center_text("Object created"); } else eman->center_text("Can only create from 'shapes.vga'"); } void Cheat::delete_object (void) { if (!enabled) return; int x, y; SDL_GetMouseState(&x, &y); x /= gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); y /= gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale(); Game_object *obj; Gump *gump = gwin->get_gump_man()->find_gump(x, y); if (gump) { obj = gump->find_object(x, y); } else { // Search rest of world. obj = gwin->find_object(x, y); } if (obj) { clear_selected(); // Unselect all. obj->remove_this(); eman->center_text("Object deleted"); gwin->paint(); } } void Cheat::heal_party (void) const { if (!enabled) return; int i; // for MSVC Party_manager *partyman = gwin->get_party_man(); // NOTE: dead_party_count decrs. as we // resurrect. int count = partyman->get_dead_count(); int dead[16]; // Save in separate list. if (count > 16) count = 16; for (i = 0; i < count; i++) dead[i] = partyman->get_dead_member(i); for (i = 0; i < count; i++) { int npc_num = dead[i]; Dead_body *body = gwin->get_body(npc_num); Actor *live_npc = gwin->get_npc(npc_num); if (body && live_npc) { Tile_coord avpos = gwin->get_main_actor()->get_tile(); body->move(avpos); live_npc->resurrect(body); } } // heal everyone Actor* party[9]; count = gwin->get_party(party, 1); for (i = 0; i < count; i++) { if (!party[i]->is_dead()) { // heal party[i]->set_property(Actor::health, party[i]->get_property(Actor::strength)); // cure poison party[i]->clear_flag(Obj_flags::poisoned); // remove hunger +++++ what is "normal" food level?? party[i]->set_property(Actor::food_level, 30); } } // restore mana Main_actor* avatar = gwin->get_main_actor(); avatar->set_property(Actor::mana, avatar->get_property(Actor::magic)); eman->center_text("Party healed"); gwin->paint(); } void Cheat::shape_browser (void) const { if (!enabled) return; browser->browse_shapes(); gwin->paint(); gwin->get_pal()->set(-1,-1); } bool Cheat::get_browser_shape (int &shape, int &frame) const { if (!enabled) return false; return browser->get_shape(shape, frame); } void Cheat::sound_tester (void) const { if (!enabled) return; tester->test_sound(); gwin->paint(); } void Cheat::cheat_screen (void) const { if (!enabled) return; cscreen->show_screen(); gwin->set_all_dirty(); gwin->paint(); } void Cheat::toggle_grab_actor (void) { if (!enabled) return; grab_actor = !grab_actor; if (grab_actor) eman->center_text("NPC Tool Actor Grabbing Enabled"); else eman->center_text("NPC Tool Actor Grabbing Disabled"); } void Cheat::set_grabbed_actor (Actor *actor) const { if (!enabled||!cscreen) return; cscreen->SetGrabbedActor(actor); } void Cheat::clear_this_grabbed_actor(Actor *actor) const { if (!enabled||!cscreen) return; cscreen->ClearThisGrabbedActor(actor); } void Cheat::toggle_number_npcs (void) { if (!enabled) return; npc_numbers = !npc_numbers; if (npc_numbers) eman->center_text("NPC Numbers Enabled"); else eman->center_text("NPC Numbers Disabled"); } exult-1.2/readnpcs.cc0000644000175000001440000001745710054030531010305 /* * readnpcs.cc - Read in NPC's from npc.dat & schedule.dat. Also writes npc.dat back out. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "gamewin.h" #include "game.h" #include "monsters.h" #include "ucmachine.h" #include "utils.h" #include "fnames.h" #include "schedule.h" #include "databuf.h" //#include "items.h" /* Debugging only */ #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::ifstream; using std::ios; using std::memset; using std::ofstream; #endif /* * Read in the NPC's, plus the monster info. */ void Game_window::read_npcs ( ) { npcs.resize(1); // Create main actor. camera_actor = npcs[0] = main_actor = new Main_actor("", 0); ifstream nfile_stream; StreamDataSource nfile(&nfile_stream); int num_npcs; bool fix_unused = false; // Get set for old savegames. try { U7open(nfile_stream, NPC_DAT); num_npcs1 = nfile.read2(); // Get counts. num_npcs = num_npcs1 + nfile.read2(); main_actor->read(&nfile, 0, false, fix_unused); } catch(exult_exception &e) { if (!Game::is_editing()) throw e; num_npcs1 = num_npcs = 1; if (Game::get_avname()) main_actor->set_npc_name(Game::get_avname()); main_actor->set_shape(721); // FOR NOW. main_actor->set_invalid(); // Put in middle of world. main_actor->move(c_num_tiles/2, c_num_tiles/2, 0); } npcs.resize(num_npcs); bodies.resize(num_npcs); int i; // Don't like it... no i don't. center_view(main_actor->get_tile()); for (i = 1; i < num_npcs; i++) // Create the rest. { npcs[i] = new Npc_actor("", 0); npcs[i]->read(&nfile, i, i < num_npcs1, fix_unused); if (npcs[i]->is_unused()) { // Not part of the game. npcs[i]->remove_this(1); npcs[i]->set_schedule_type(Schedule::wait); } else npcs[i]->restore_schedule(); CYCLE_RED_PLASMA(); } nfile_stream.close(); main_actor->set_actor_shape(); try { U7open(nfile_stream, MONSNPCS); // Monsters. // (Won't exist the first time; in this case U7open throws int cnt = nfile.read2(); char tmp = nfile.read1();// Read 1 ahead to test. int okay = nfile_stream.good(); nfile.skip(-1); while (okay && cnt--) { // Read ahead to get shape. nfile.skip(2); unsigned short shnum = nfile.read2()&0x3ff; okay = nfile_stream.good(); nfile.skip(-4); ShapeID sid(shnum, 0); if (!okay || sid.get_num_frames() < 16) break; // Watch for corrupted file. Monster_actor *act = Monster_actor::create(shnum); act->read(&nfile, -1, false, fix_unused); act->restore_schedule(); CYCLE_RED_PLASMA(); } } catch(exult_exception &e) { #ifdef DEBUG cerr << "Error reading saved monsters. Clearing list." << endl; #endif Monster_actor::give_up(); } if (moving_barge) // Gather all NPC's on barge. { Barge_object *b = moving_barge; moving_barge = 0; set_moving_barge(b); } read_schedules(); // Now get their schedules. center_view(main_actor->get_tile()); } /* * Write NPC (and monster) data back out. * * Output: false if error, already reported. */ void Game_window::write_npcs ( ) { int num_npcs = npcs.size(); ofstream nfile_stream; U7open(nfile_stream, NPC_DAT); StreamDataSource nfile(&nfile_stream); nfile.write2(num_npcs1); // Start with counts. nfile.write2(num_npcs - num_npcs1); int i; for (i = 0; i < num_npcs; i++) npcs[i]->write(&nfile); nfile_stream.flush(); bool result = nfile_stream.good(); if (!result) throw file_write_exception(NPC_DAT); nfile_stream.close(); write_schedules(); // Write schedules // Now write out monsters in world. U7open(nfile_stream, MONSNPCS); int cnt = 0; nfile.write2(0); // Write 0 as a place holder. for (Monster_actor *mact = Monster_actor::get_first_in_world(); mact; mact = mact->get_next_in_world()) if (!mact->is_dead()) // Alive? { mact->write(&nfile); cnt++; } nfile.seek(0); // Back to start. nfile.write2(cnt); // Write actual count. nfile_stream.flush(); result = nfile_stream.good(); nfile_stream.close(); if (!result) throw file_write_exception(NPC_DAT); } /* * Read NPC schedules. */ void Game_window::read_schedules ( ) { ifstream sfile_stream; int num_npcs = 0; try { U7open(sfile_stream, GSCHEDULE); } catch(exult_exception e) { #ifdef DEBUG cerr << "Couldn't open " << GSCHEDULE << ". Falling back to " << SCHEDULE_DAT << "." << endl; #endif try { U7open(sfile_stream, SCHEDULE_DAT); } catch(exult_exception e1) { if (!Game::is_editing()) throw e1; else return; } } StreamDataSource sfile(&sfile_stream); num_npcs = sfile.read4(); // # of NPC's, not include Avatar. short *offsets = new short[num_npcs]; int i; // Read offsets with list of scheds. for (i = 0; i < num_npcs; i++) offsets[i] = sfile.read2(); for (i = 0; i < num_npcs - 1; i++) // Do each NPC, except Avatar. { // Avatar isn't included here. Actor *npc = npcs[i + 1]; int cnt = offsets[i + 1] - offsets[i]; // Read schedules into this array. Schedule_change *schedules = cnt?new Schedule_change[cnt]:0; for (int j = 0; j < cnt; j++) { unsigned char ent[4]; sfile.read(reinterpret_cast(ent), 4); schedules[j].set(ent); } // Store in NPC. if (npc) npc->set_schedules(schedules, cnt); else delete schedules; CYCLE_RED_PLASMA(); } delete [] offsets; // Done with this. cout.flush(); } /* * Write NPC schedules. */ void Game_window::write_schedules () { ofstream sfile_stream; Schedule_change *schedules; int cnt; short offset = 0; int i; int num; // So do I allow for all NPCs (type1 and type2) - Yes i will num = npcs.size(); U7open(sfile_stream, GSCHEDULE); StreamDataSource sfile(&sfile_stream); sfile.write4(num); // # of NPC's, not include Avatar. sfile.write2(0); // First offfset for (i = 1; i < num; i++) // write offsets with list of scheds. { npcs[i]->get_schedules(schedules, cnt); offset += cnt; sfile.write2(offset); } for (i = 1; i < num; i++) // Do each NPC, except Avatar. { npcs[i]->get_schedules(schedules, cnt); for (int j = 0; j < cnt; j++) { unsigned char ent[4]; schedules[j].get(ent); sfile.write(reinterpret_cast(ent), 4); } } } void Game_window::revert_schedules(Actor *npc) { // Can't do this if <= 0 if (npc->get_npc_num() <= 0) return; int i; ifstream sfile_stream; U7open(sfile_stream, SCHEDULE_DAT); StreamDataSource sfile(&sfile_stream); // # of NPC's, not include Avatar. int num_npcs = sfile.read4(); short *offsets = new short[num_npcs]; for (i = 0; i < num_npcs; i++) offsets[i] = sfile.read2(); // Seek to the right place sfile.skip(offsets[npc->get_npc_num()-1]*4); // Get the count that we want to use int cnt = offsets[npc->get_npc_num()] - offsets[npc->get_npc_num()-1]; // Read schedules into this array. Schedule_change *schedules = cnt?new Schedule_change[cnt]:0; for (i = 0; i < cnt; i++) { unsigned char ent[4]; sfile.read(reinterpret_cast(ent), 4); schedules[i].set(ent); } // Store in NPC. npc->set_schedules(schedules, cnt); // Done delete [] offsets; } exult-1.2/npcnear.cc0000644000175000001440000001150410054030531010117 /* * npcnear.cc - At random times, run proximity usecode functions on nearby NPC's. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "npcnear.h" #include "gamewin.h" #include "actors.h" #include "ucmachine.h" #include "schedule.h" #include "items.h" #include "game.h" #include "cheat.h" #include "SDL_timer.h" #ifndef UNDER_CE using std::rand; #endif bool Bg_dont_wake(Game_window *gwin, Actor *npc); /* * Add an npc to the time queue. */ void Npc_proximity_handler::add ( unsigned long curtime, // Current time (msecs). Npc_actor *npc, int additional_secs // More secs. to wait. ) { int msecs; // Hostile? Wait 0-2 secs. if (npc->get_alignment() >= Npc_actor::hostile) msecs = rand() % 2000; else // Wait between 2 & 6 secs. msecs = (rand() % 4000) + 2000; unsigned long newtime = curtime + msecs; newtime += 1000*additional_secs; gwin->get_tqueue()->add(newtime, this, reinterpret_cast(npc)); } /* * Remove entry for an npc. */ void Npc_proximity_handler::remove ( Npc_actor *npc ) { npc->clear_nearby(); gwin->get_tqueue()->remove(this, reinterpret_cast(npc)); } /* * Is this a Black Gate (Skara Brae) ghost, or Penumbra? */ bool Bg_dont_wake ( Game_window *gwin, Actor *npc ) { int num; return (Game::get_game_type() == BLACK_GATE && (npc->get_info().has_translucency() || // Horace or Penumbra? (num = npc->Actor::get_npc_num()) == 141 || num == 150)); } /* * Run proximity usecode function for the NPC now. */ void Npc_proximity_handler::handle_event ( unsigned long curtime, long udata ) { Npc_actor *npc = (Npc_actor *) udata; int extra_delay = 5; // For next time. // See if still on visible screen. Rectangle tiles = gwin->get_win_tile_rect().enlarge(10); Tile_coord t = npc->get_tile(); if (!tiles.has_point(t.tx, t.ty) || // No longer visible? npc->is_dead()) // Or no longer living? { npc->clear_nearby(); return; } Schedule::Schedule_types sched = (Schedule::Schedule_types) npc->get_schedule_type(); // Sleep schedule? if (npc->get_schedule() && sched == Schedule::sleep && // But not under a sleep spell? !npc->get_flag(Obj_flags::asleep) && gwin->is_main_actor_inside() && !Bg_dont_wake(gwin, npc) && npc->distance(gwin->get_main_actor()) < 6 && rand()%3 != 0) { // Trick: Stand, but stay in // sleep_schedule. npc->get_schedule()->ending(Schedule::stand); npc->say(first_awakened, last_awakened); // In 10 seconds, go back to sleep. npc->start(0, 10000); extra_delay = 11; // And don't run Usecode while up. } else if (!(curtime < wait_until) && !cheat.in_map_editor() && // Do it 50% of the time OR if // a rabbit (SI start). (rand()%2 == 1 || npc->get_shapenum() == 811) && // And not for party members. !npc->is_in_party() && // And not if walking to sched. spot. sched != Schedule::walk_to_schedule && // And not for patrollers/monsters // in SI. !!Guessing. (Game::get_game_type() != SERPENT_ISLE || (sched != Schedule::patrol && sched != Schedule::wait && sched != Schedule::horiz_pace && sched != Schedule::vert_pace && !npc->is_monster()))) { int ucfun = npc->get_usecode(); gwin->get_usecode()->call_usecode(ucfun, npc, Usecode_machine::npc_proximity); extra_delay += 3; curtime = Game::get_ticks();// Time may have passed. } add(curtime, npc, extra_delay); // Add back for next time. } /* * Set a time to wait for before running any usecodes. This is to * skip all the text events that would happen at the end of a conver- * sation. */ void Npc_proximity_handler::wait ( int secs // # of seconds. ) { wait_until = Game::get_ticks() + 1000*secs; } /* * Fill a list with all the nearby NPC's. */ void Npc_proximity_handler::get_all ( Actor_queue& alist // They're appended to this. ) { Time_queue_iterator next(gwin->get_tqueue(), this); Time_sensitive *obj; long data; // NPC is the data. while (next(obj, data)) alist.push((Npc_actor *) data); } exult-1.2/exult.spec0000644000175000001440000001024110061527044010204 # # Note that this is NOT a relocatable package # %define ver 1.2 %define rel 1 %define name exult Summary: Ultima VII Engine Name: %name Version: %ver Release: %rel Copyright: GPL Group: Amusements/Games Source: http://download.sourceforge.net/projects/exult/exult-%{ver}.tar.gz BuildRoot: %{_tmppath}/%{name}-root Packager: Willem Jan Palenstijn URL: http://exult.sourceforge.net Prereq: /sbin/install-info %description Exult: an implementation of the Ultima VII engine for modern Operating Systems. %package tools Summary: Tools and utilities for playing with Exult/Ultima VII data files Group: Amusements/Games %description tools Exult Tools: a set of utilities for playing with Exult/Ultima VII data files. Included in the tools are: expack (archiver), ucxt (decompiler), ucc (compiler), splitshp (frame splitter), shp2pcx (shape converter), ipack (image archiver), textpack (text archiver) %package studio Summary: An editor for the Exult engine. Group: Amusements/Games %description studio Exult Studio: an editor for the Exult engine. # Also included is a plugin for the Gimp for the .shp image format. # (not yet...) %changelog * Tue Jul 22 2003 Willem Jan Palensitjn - updated for 1.1Beta1 - added a 'studio' package * Wed Nov 06 2002 Willem Jan Palensitjn - added tools manpages * Fri Nov 01 2002 Willem Jan Palenstijn - updated .spec to work with RH80 - removed studio and gimp plugin packages for 1.0 branch * Fri Jun 07 2002 Willem Jan Palenstijn - updated ucxt data files * Wed Dec 05 2001 Tristan Tarrant - subpackages are here !!! * Thu Nov 29 2001 Tristan Tarrant - allow setting of bindir and datadir - build exult only (will be fixed with the addition of subpackages) - added README.1ST - optimizer flags should be set for CXXFLAGS too * Mon Jun 25 2001 Willem Jan Palenstijn - added exult_bg.flx, exult_si.flx - removed explicit SDL req. (proper SDL version is added automatically) * Tue Nov 7 2000 Tristan Tarrant - A few fixes * Sat Sep 9 2000 Tristan Tarrant - Install exult.flx in the right place * Tue Jul 11 2000 Tristan Tarrant - Created the .spec file * Fri Feb 9 2000 Tristan Tarrant - Disable GIMP plugin by default. - Include FAQ %prep %setup %build # Needed for snapshot releases. if [ ! -f configure ]; then ./autogen.sh fi %configure --disable-gimp-plugin --enable-exult-studio --enable-exult-studio-support if [ "$SMP" != "" ]; then (make "MAKE=make -k -j $SMP"; exit 0) make else make fi %install rm -rf $RPM_BUILD_ROOT %makeinstall %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc AUTHORS COPYING ChangeLog NEWS README FAQ README.1ST %{_bindir}/exult %{_datadir}/exult/exultmsg.txt %{_datadir}/exult/exult_bg.flx %{_datadir}/exult/exult_si.flx %{_datadir}/exult/exult.flx %{_datadir}/exult/midisfx.flx %{_datadir}/icons/exult.png %{_mandir}/man6/exult.6.gz %{_datadir}/applications/exult.desktop %files tools %defattr(-, root, root) %doc tools/expack.txt %{_mandir}/man1/expack.1.gz %{_mandir}/man1/ipack.1.gz %{_mandir}/man1/shp2pcx.1.gz %{_mandir}/man1/splitshp.1.gz %{_mandir}/man1/textpack.1.gz %{_bindir}/expack %{_bindir}/ipack %{_bindir}/textpack %{_bindir}/ucxt %{_bindir}/ucc %{_bindir}/splitshp %{_bindir}/shp2pcx %{_datadir}/exult/u7bgintrinsics.data %{_datadir}/exult/u7siintrinsics.data %{_datadir}/exult/u7misc.data %{_datadir}/exult/u7opcodes.data %files studio %defattr(-, root, root) %{_bindir}/exult_studio %{_datadir}/exult/exult_studio.glade %{_datadir}/exult/estudio/new/combos.flx %{_datadir}/exult/estudio/new/faces.vga %{_datadir}/exult/estudio/new/gumps.vga %{_datadir}/exult/estudio/new/palettes.flx %{_datadir}/exult/estudio/new/shapes.vga %{_datadir}/exult/estudio/new/sprites.vga %{_datadir}/exult/estudio/new/text.flx %{_datadir}/exult/estudio/new/fonts.vga %{_datadir}/exult/estudio/new/pointers.shp exult-1.2/config.guess0000755000175000001440000011576310013577154010532 #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-10-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # This shell variable is my proudest work .. or something. --bje set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; (old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; dummy=$tmpdir/dummy ; files="$dummy.c $dummy.o $dummy.rel $dummy" ; trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $files ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; unset files' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. eval $set_cc_for_build cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null if test "$?" = 0 ; then case `$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; 3-1307) UNAME_MACHINE="alphaev7" ;; esac fi rm -f $dummy.s $dummy && rmdir $tmpdir echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy && rmdir $tmpdir fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c && rmdir $tmpdir test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: exult-1.2/install-sh0000755000175000001440000001273610013577156010214 #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 exult-1.2/party.cc0000644000175000001440000003501510040665374007651 /** ** Party.cc - Manage the party. ** ** Written: 4/8/02 - JSF **/ /* Copyright (C) 2000-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "party.h" #include "actors.h" #include "gamewin.h" #include "frameseq.h" #include "dir.h" using std::cout; using std::endl; /* * Create. */ Party_manager::Party_manager ( ) : party_count(0), dead_party_count(0), validcnt(0) { // Clear party list. std::memset((char *) &party[0], 0, sizeof(party)); std::memset((char *) &dead_party[0], 0, sizeof(dead_party)); } /* * Add NPC to party. * * Output: false if no room or already a member. */ bool Party_manager::add_to_party ( Actor *npc // (Should not be the Avatar.) ) { const int maxparty = sizeof(party)/sizeof(party[0]); if (!npc || party_count == maxparty || npc->is_in_party()) return false; remove_from_dead_party(npc); // Just to be sure. npc->set_party_id(party_count); npc->set_flag (Obj_flags::in_party); // We can take items. npc->set_flag_recursively(Obj_flags::okay_to_take); party[party_count++] = npc->get_npc_num(); return true; } /* * Remove party member. * * Output: false if not found. */ bool Party_manager::remove_from_party ( Actor *npc ) { if (!npc) return false; int id = npc->get_party_id(); if (id == -1) // Not in party? return false; int npc_num = npc->get_npc_num(); if (party[id] != npc_num) { cout << "Party mismatch!!" << endl; return false; } // Shift the rest down. for (int i = id + 1; i < party_count; i++) { Actor *npc2 = gwin->get_npc(party[i]); if (npc2) npc2->set_party_id(i - 1); party[i - 1] = party[i]; } npc->clear_flag (Obj_flags::in_party); party_count--; party[party_count] = 0; npc->set_party_id(-1); return true; } /* * Find index of NPC in dead party list. * * Output: Index, or -1 if not found. */ int Party_manager::in_dead_party ( Actor *npc ) { int num = npc->get_npc_num(); for (int i = 0; i < dead_party_count; i++) if (dead_party[i] == num) return i; return -1; } /* * Add NPC to dead party list. * * Output: false if no room or already a member. */ bool Party_manager::add_to_dead_party ( Actor *npc // (Should not be the Avatar.) ) { const int maxparty = sizeof(dead_party)/sizeof(dead_party[0]); if (!npc || dead_party_count == maxparty || in_dead_party(npc) >= 0) return false; dead_party[dead_party_count++] = npc->get_npc_num(); return true; } /* * Remove NPC from dead party list. * * Output: false if not found. */ bool Party_manager::remove_from_dead_party ( Actor *npc ) { if (!npc) return false; int id = in_dead_party(npc); // Get index. if (id == -1) // Not in list? return false; int npc_num = npc->get_npc_num(); // Shift the rest down. for (int i = id + 1; i < dead_party_count; i++) dead_party[i - 1] = dead_party[i]; dead_party_count--; dead_party[dead_party_count] = 0; return true; } /* * Update party status of an NPC that has died or been resurrected. */ void Party_manager::update_party_status ( Actor *npc ) { if (npc->is_dead()) // Dead? { // Move party members to dead list. if (remove_from_party(npc)) add_to_dead_party(npc); } else // Alive. { if (remove_from_dead_party(npc)) add_to_party(npc); } } /* * In case NPC's were read after usecode, set party members' id's, and * move dead members into separate list. */ void Party_manager::link_party ( ) { // avatar is a party member too gwin->get_main_actor()->set_flag(Obj_flags::in_party); // You own your own stuff. gwin->get_main_actor()->set_flag_recursively(Obj_flags::okay_to_take); const int maxparty = sizeof(party)/sizeof(party[0]); int tmp_party[maxparty]; int tmp_party_count = party_count; int i; for (i = 0; i < maxparty; i++) tmp_party[i] = party[i]; party_count = dead_party_count = 0; // Now process them. for (i = 0; i < tmp_party_count; i++) { if (party[i] <= 0) // Fix corruption. continue; Actor *npc = gwin->get_npc(party[i]); int oldid; if (!npc || // Shouldn't happen! // But this has happened: ((oldid = npc->get_party_id()) >= 0 && oldid < party_count)) continue; // Skip bad entry. int npc_num = npc->get_npc_num(); if (npc->is_dead()) // Put dead in special list. { npc->set_party_id(-1); if (dead_party_count >= sizeof(dead_party)/sizeof(dead_party[0])) continue; dead_party[dead_party_count++] = npc_num; continue; } npc->set_party_id(party_count); party[party_count++] = npc_num; // ++++This messes up places where they should wait, and should be unnecessary. // npc->set_schedule_type(Schedule::follow_avatar); // We can use all his/her items. npc->set_flag_recursively(Obj_flags::okay_to_take); npc->set_flag (Obj_flags::in_party); } } /* * For each party member, this array has the party ID's (or -1) of the * two member's followers, arrayed as follows: * A * 0 1 * 2 3 4 * 7 5 6 8 */ static int followers[EXULT_PARTY_MAX + 1][2] = { {0, 1}, // These follow Avatar (ID = -1). {2, 3}, // Follow 0. {-1, 4}, // Follow 1. {7, -1}, // Follow 2. {5, 6}, // Follow 3. {-1, 8}, // Follow 4. {-1, -1}, {-1, -1}, {-1, -1}}; /* * Offsets for the follower, depending on direction (0-3, with * 0 = North, 1 = East, 2 = South, 3 = West). */ static int left_offsets[4][2] = { // Follower is behind and to left. {-2, 2}, // North. {-2, -2}, // East. {2, -2}, // South. {2, 2} }; // West. static int right_offsets[4][2] = { // Follower is behind and to right. {2, 2}, // North. {-2, 2}, // East. {-2, -2}, // South. {2, -2} }; // West. /* * This should be called each time the Avatar takes a step while under * control of the user. */ void Party_manager::get_followers ( int dir // Direction (0-7) Avatar just stepped. ) { validcnt = 0; // Get party members to control. for (int i = 0; i < party_count; i++) { Actor *npc = gwin->get_npc(party[i]); if (!npc || npc->get_flag(Obj_flags::asleep) || npc->get_flag(Obj_flags::paralyzed) || npc->is_dead()) continue; // Not available. if (npc->in_queue()) // Already walking? continue; // For now, let him continue... valid[validcnt++] = npc; } if (validcnt) move_followers(gwin->get_main_actor(), -1, dir); } /* * To walk in formation, each party member will have one or two other * party members who will follow him on each step. */ void Party_manager::move_followers ( Actor *npc, // Party member who just stepped. int vindex, // Index within 'valid'. int dir // Direction (0-7) he stepped in. ) { int id = npc->get_party_id(); // (-1 if Avatar). Tile_coord pos = npc->get_tile(); int lnum = followers[1 + id][0], rnum = followers[1 + id][1]; if (lnum == -1 && rnum == -1) return; // Nothing to do. int dir4 = dir/2; // 0-3 now. Actor *lnpc = (lnum == -1 || lnum >= validcnt) ? 0 : valid[lnum]; Actor *rnpc = (rnum == -1 || rnum >= validcnt) ? 0 : valid[rnum]; int ldir = -1, rdir = -1; // Have each take a step. if (lnpc) ldir = step(lnpc, npc, dir, pos + Tile_coord( left_offsets[dir4][0], left_offsets[dir4][1], 0)); if (rnpc) rdir = step(rnpc, npc, dir, pos + Tile_coord( right_offsets[dir4][0], right_offsets[dir4][1], 0)); if (ldir >= 0 && !lnpc->is_dead()) move_followers(lnpc, lnum, ldir); if (rdir >= 0 && !rnpc->is_dead()) move_followers(rnpc, rnum, rdir); } /* * Get tile to step to, given destination tile (possibly more than 1 * step away), and the party's direction. */ inline Tile_coord Get_step_tile ( Tile_coord pos, // Current pos. Tile_coord dest, // Desired dest. int dir // Dir. party is moving (0-7). ) { int dx = dest.tx - pos.tx, dy = dest.ty - pos.ty; if (dx < -1) dx = -1; // Limit to 1 tile. else if (dx > 1) dx = 1; if (dy < -1) dy = -1; else if (dy > 1) dy = 1; return pos + Tile_coord(dx, dy, 0); } /* * Find the party member occupying a given tile, starting with a given * party #. * Note: Maybe it should check a rectangle of tiles someday if we want * to have NPC's bigger than 1 tile. */ static Actor *Find_member_blocking ( Tile_coord pos, // Position to check. int first // Party ID to start with. ) { Game_window *gwin = Game_window::get_instance(); Party_manager *pman = gwin->get_party_man(); int count = pman->get_count(); for (int i = first; i < count; i++) { Actor *npc = gwin->get_npc(pman->get_member(i)); pos.tz = npc->get_lift();// Use NPC's, since it might be up/dn // by a step. if (npc->blocks(pos)) return npc; // Found. } return 0; } /* * Get the direction from a tile to NPC's position. */ inline int Get_dir_from ( Actor *npc, Tile_coord& from ) { Tile_coord pos = npc->get_tile(); return Get_direction(from.ty - pos.ty, pos.tx - from.tx); } /* * Is the straight path to the leader clear, and less than 5 tiles? */ inline bool Clear_to_leader ( Actor *npc, Actor *leader, Tile_coord from // Start from here. ) { Tile_coord dest = leader->get_tile(); int dist = dest.distance(from); if (dist > 4) return false; // Too far. while (--dist) // Check tiles up to there. { int dir = Get_dir_from(leader, from); Tile_coord next = from.get_neighbor(dir); if (npc->is_blocked(next, &from)) { Actor *bnpc = Find_member_blocking(next, 0); if (!bnpc) return false; // Blocked by non-party-member. next.tz = bnpc->get_lift(); } from = next; } int difftz = from.tz - dest.tz; // Check diff. in z-coords. return difftz*difftz <= 1; // Can't be more than 2. } /* * Get a notion of 'cost' for stepping to a particular tile. * * Output: Currently, 10000 if blocked, or (dist)**2. */ const int max_cost = 10000; static int Get_cost ( Actor *npc, // NPC to take the step. Actor *leader, // NPC he's following. Tile_coord to, // Tile to step to. Actor **find_blocking = 0 // Returns blocking party member. ) { int cost = 0; if (find_blocking) *find_blocking = 0; if (npc->is_blocked(to)) // (To.tz is updated.) { // Can't go there. if (find_blocking) { // Find member we can swap with. *find_blocking = Find_member_blocking(to, 1 + npc->get_party_id()); if (!*find_blocking) return max_cost; to.tz = (*find_blocking)->get_lift(); cost += 1; // Assess one point to swap. } else return max_cost; } Tile_coord lpos = leader->get_tile(); int difftz = to.tz - lpos.tz, // Measure closeness. diffty = Tile_coord::delta(to.ty, lpos.ty), difftx = Tile_coord::delta(to.tx, lpos.tx); // Get dist**2 in x-y plane. int xydist2 = diffty*diffty + difftx*difftx; cost += difftz*difftz + xydist2; if (xydist2 > 2) // More than 1 tile away? { // Check 1 more tile towards leader. if (!Clear_to_leader(npc, leader, to)) cost += 16; // If blocked, try to avoid. } return cost; } /* * Take best step to follow the leader. * * Output: True if a step taken. */ static bool Take_best_step ( Actor *npc, Actor *leader, Tile_coord& pos, // Current pos. int frame, // Frame to show. int dir // Direction we want to go. ) { static int deltadir[] = {0, 1, 7, 2, 6, 3, 5}; const int cnt = sizeof(deltadir)/sizeof(deltadir[0]); int best_cost = max_cost + 8; Tile_coord best(-1, -1, -1); Actor *best_in_way = 0; for (int i = 0; i < cnt; i++) { int diri = (dir + deltadir[i])%8; Tile_coord to = pos.get_neighbor(diri); Actor *in_way; // Fudge cost with diff. in dir. int cost = Get_cost(npc, leader, to, &in_way); if (cost < best_cost) { best_cost = cost; best_in_way = in_way; best = to; } } if (best_cost >= max_cost) return false; if (!best_in_way) // Nobody in way? return npc->step(best, frame)!=0; best = best_in_way->get_tile(); // Swap positions. npc->remove_this(true); best_in_way->remove_this(true); npc->set_frame(frame); // Appear to take a step. npc->move(best); best_in_way->move(pos); return true; } /* * See if a step is reasonable. This is the first test made. */ inline bool Is_step_okay ( Actor *npc, // NPC to take the step. Actor *leader, // NPC he's following. Tile_coord to // Tile to step to. ) { if (npc->is_blocked(to)) // (To.tz is updated.) return false; int difftz = to.tz - leader->get_lift(); difftz *= difftz; // Deltaz squared. if (difftz > 4) // More than 2? return false; // We'll want to find best dir. // How close in XY? int dist = to.distance(leader->get_tile()); if (dist == 1) return (difftz <= 1); // 1 tile away, so want dz <= 1. if (!Clear_to_leader(npc, leader, to)) return false; // Couldn't take a 2nd step. return true; } /* * Move one follower to its destination (if possible). * * Output: Direction (0-7) moved (or given 'dir' if we don't move). */ int Party_manager::step ( Actor *npc, Actor *leader, // Who NPC is following. int dir, // Direction we're walking (0-7). Tile_coord dest // Destination tile. ) { Tile_coord pos = npc->get_tile(); // Current position. Tile_coord to = Get_step_tile(pos, dest, dir); if (to.tx == pos.tx && to.ty == pos.ty) return dir; // Not moving. //TEST: if (npc->in_queue() || npc->is_moving()) cout << npc->get_name() << " shouldn't be stepping!" << endl; Frames_sequence *frames = npc->get_frames(dir); int& step_index = npc->get_step_index(); if (!step_index) // First time? Init. step_index = frames->find_unrotated(npc->get_framenum()); // Get next (updates step_index). int frame = frames->get_next(step_index); // Want dz<=1, dx<=2, dy<=2. if (Is_step_okay(npc, leader, to) && npc->step(to, frame)) ; // Could have died from stepping on // something. else if (npc->is_dead() || !Take_best_step(npc, leader, pos, frame, npc->get_direction(dest))) { // Failed to take a step. cout << npc->get_name() << " failed to take a step" << endl; frames->decrement(step_index); return dir; } return Get_dir_from(npc, pos); } exult-1.2/exult_types.h0000755000175000001440000000355207724430450010745 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EXULT_TYPES_H #define EXULT_TYPES_H #ifdef BEOS // BeOS headers already define these types #include typedef int8 sint8; typedef int16 sint16; typedef int32 sint32; #else #ifndef EX_TYPE_INT8 # define EX_TYPE_INT8 char /* guaranteed by ISO */ #endif #ifndef EX_TYPE_INT16 # if (SIZEOF_SHORT == 2) # define EX_TYPE_INT16 short # elif (SIZEOF_INT == 2) # define EX_TYPE_INT16 int # else # error "Please make sure a 16 bit type is provided by exult_types.h" # endif #endif /* !EX_TYPE_INT16 */ #ifndef EX_TYPE_INT32 # if (SIZEOF_INT == 4) # define EX_TYPE_INT32 int # elif (SIZEOF_LONG == 4) # define EX_TYPE_INT32 long # elif (SIZEOF_LONG_LONG == 4) # define EX_TYPE_INT32 long long # else # error "Please make sure a 32 bit type is provided by exult_types.h" # endif #endif /* !EX_TYPE_INT32 */ typedef unsigned EX_TYPE_INT8 uint8; typedef unsigned EX_TYPE_INT16 uint16; typedef unsigned EX_TYPE_INT32 uint32; typedef signed EX_TYPE_INT8 sint8; typedef signed EX_TYPE_INT16 sint16; typedef signed EX_TYPE_INT32 sint32; #endif //BeOS #endif exult-1.2/paths.cc0000644000175000001440000003246410040665440007630 /* * Paths.cc - Various pathfinding clients. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "paths.h" #include "Astar.h" #include "Zombie.h" #include "gamewin.h" #include "gamemap.h" #include "actors.h" /* * Create for given NPC. */ Actor_pathfinder_client::Actor_pathfinder_client ( Actor *n, int d ) : dist(d), npc(n) { // +++++Shouldn't need this anymore? set_move_flags(npc->get_type_flags()); } /* * Figure when to give up. */ int Actor_pathfinder_client::get_max_cost ( int cost_to_goal // From estimate_cost(). ) { int max_cost = 3*cost_to_goal; Game_window *gwin = Game_window::get_instance(); // Do at least 3 screens width. int min_max_cost = (gwin->get_width()/c_tilesize)*2*3; return max_cost > min_max_cost ? max_cost : min_max_cost; } /* * Figure cost going from one tile to an adjacent tile (for pathfinding). * * Output: Cost, or -1 if blocked. * The 'tz' field in tile may be modified. */ int Actor_pathfinder_client::get_step_cost ( Tile_coord from, Tile_coord& to // The tile we're going to. The 'tz' // field may be modified. ) { Game_window *gwin = Game_window::get_instance(); int cx = to.tx/c_tiles_per_chunk, cy = to.ty/c_tiles_per_chunk; Map_chunk *olist = gwin->get_map()->get_chunk(cx, cy); int tx = to.tx%c_tiles_per_chunk; // Get tile within chunk. int ty = to.ty%c_tiles_per_chunk; int cost = 1; olist->setup_cache(); // Make sure cache is valid. int water, poison; // Get tile info. Actor::get_tile_info(0, gwin, olist, tx, ty, water, poison); int old_lift = to.tz; // Might climb/descend. if (npc->is_blocked(to, &from)) { // Blocked, but check for a door. Game_object *block = Game_object::find_door(to); if (!block) return -1; if (!block->is_closed_door() || // Can't get past locked doors. block->get_framenum()%4 >= 2) return -1; // Can't be either end of door. Rectangle foot = block->get_footprint(); if (foot.h == 1 && (to.tx == foot.x || to.tx == foot.x + foot.w - 1)) return -1; else if (foot.w == 1 && (to.ty == foot.y || to.ty == foot.y + foot.h - 1)) return -1; if (foot.has_point(from.tx, from.ty)) return -1; // Don't walk within doorway. cost++; // But try to avoid them. } if (old_lift != to.tz) cost++; // On the diagonal? if (from.tx != to.tx || from.ty != to.ty) cost *= 3; // Make it 50% more expensive. else cost *= 2; if (poison && to.tz == 0) cost *= 2; // And avoid poison if possible. // Get 'flat' shapenum. ShapeID flat = olist->get_flat(tx, ty); int shapenum = flat.get_shapenum(); if (shapenum == 24) // Cobblestone path in BlackGate? { int framenum = flat.get_framenum(); if (framenum <= 1) cost--; } return (cost); } /* * Estimate cost from one point to another. */ int Actor_pathfinder_client::estimate_cost ( Tile_coord& from, Tile_coord& to ) { int dx = to.tx - from.tx; if (dx < -c_num_tiles/2) // Wrap around the world. dx += c_num_tiles; else if (dx < 0) dx = -dx; int dy = to.ty - from.ty; if (dy < -c_num_tiles/2) dy += c_num_tiles; else if (dy < 0) dy = -dy; int larger, smaller; // Start with larger. if (dy <= dx) { larger = dx; smaller = dy; } else { larger = dy; smaller = dx; } return (2*larger + smaller); // Straight = 2, diag = 3. } /* * Is tile at goal? */ int Actor_pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { return tile.distance(goal) <= dist && (goal.tz == -1 || tile.tz == goal.tz); } /* * Estimate cost from one point to another. */ int Onecoord_pathfinder_client::estimate_cost ( Tile_coord& from, Tile_coord& to // Should be the goal. ) { if (to.tx == -1) // Just care about Y? { // Cost = 2/tile. int dy = to.ty - from.ty; if (dy < -c_num_tiles/2) dy += c_num_tiles; else if (dy < 0) dy = -dy; return (2*dy); } else if (to.ty == -1) { int dx = to.tx - from.tx; if (dx < -c_num_tiles/2) dx += c_num_tiles; else if (dx < 0) dx = -dx; return (2*dx); } else // Shouldn't get here. return Actor_pathfinder_client::estimate_cost(from, to); } /* * Is tile at goal? */ int Onecoord_pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { return ((goal.tx == -1 || tile.tx == goal.tx) && (goal.ty == -1 || tile.ty == goal.ty) && (goal.tz == -1 || tile.tz == goal.tz)); } /* * Client to get offscreen. */ Offscreen_pathfinder_client::Offscreen_pathfinder_client ( Actor *n ) : Actor_pathfinder_client(n), screen( Game_window::get_instance()->get_win_tile_rect().enlarge(3)), best(-1, -1, -1) { } /* * Client to get offscreen. */ Offscreen_pathfinder_client::Offscreen_pathfinder_client ( Actor *n, Tile_coord b // Best offscreen pt. to aim for. ) : Actor_pathfinder_client(n), screen( Game_window::get_instance()->get_win_tile_rect().enlarge(3)), best(b) { if (best.tx != -1) // Scale (roughly) to edge of screen. { Rectangle scr = Game_window::get_instance()->get_win_tile_rect(); // Get center. int cx = scr.x + scr.w/2, cy = scr.y + scr.h/2; // More than 4 screens away? if (best.distance(Tile_coord(cx, cy, 0)) > 4*scr.w) { best.tx = best.ty = -1; return; } if (best.tx > cx + scr.w) // Too far to right of screen. best.tx = scr.x + scr.w + 1; else if (best.tx < cx - scr.w) best.tx = scr.x - 1; if (best.ty > cy + scr.h) best.ty = scr.y + scr.h + 1; else if (best.ty < cy - scr.h) best.ty = scr.y - 1; // Give up if it doesn't look right. if (best.distance(Tile_coord(cx, cy, 0)) > scr.w) best.tx = best.ty = -1; } } /* * Figure cost going from one tile to an adjacent tile (for pathfinding). * * Output: Cost, or -1 if blocked. * The 'tz' field in tile may be modified. */ int Offscreen_pathfinder_client::get_step_cost ( Tile_coord from, Tile_coord& to // The tile we're going to. The 'tz' // field may be modified. ) { int cost = Actor_pathfinder_client::get_step_cost(from, to); if (cost == -1) return cost; if (best.tx != -1) // Penalize for moving away from best. { if ((to.tx - from.tx)*(best.tx - from.tx) < 0) cost++; if ((to.ty - from.ty)*(best.ty - from.ty) < 0) cost++; } return cost; } /* * Estimate cost from one point to another. */ int Offscreen_pathfinder_client::estimate_cost ( Tile_coord& from, Tile_coord& to // Should be the goal. ) { if (best.tx != -1) // Off-screen goal? return Actor_pathfinder_client::estimate_cost(from, best); //++++++World-wrapping here???? int dx = from.tx - screen.x; // Figure shortest dist. int dx1 = screen.x + screen.w - from.tx; if (dx1 < dx) dx = dx1; int dy = from.ty - screen.y; int dy1 = screen.y + screen.h - from.ty; if (dy1 < dy) dy = dy1; int cost = dx < dy ? dx : dy; if (cost < 0) cost = 0; if (to.tz != -1 && from.tz != to.tz) cost++; return 2*cost; } /* * Is tile at goal? */ int Offscreen_pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { return !screen.has_point(tile.tx - tile.tz/2, tile.ty - tile.tz/2);//&& // Z-coord shouldn't matter. // (goal.tz == -1 || tile.tz == goal.tz); } /* * Figure when to give up. */ int Fast_pathfinder_client::get_max_cost ( int cost_to_goal // From estimate_cost(). ) { int max_cost = 2*cost_to_goal; // Don't try too hard. if (max_cost < 8) max_cost = 8; else if (max_cost > 64) max_cost = 64; return max_cost; } /* * Figure cost going from one tile to an adjacent tile (for pathfinding). * * Output: Cost, or -1 if blocked. * The 'tz' field in tile may be modified. */ int Fast_pathfinder_client::get_step_cost ( Tile_coord from, Tile_coord& to // The tile we're going to. The 'tz' // field may be modified. ) { Game_window *gwin = Game_window::get_instance(); int cx = to.tx/c_tiles_per_chunk, cy = to.ty/c_tiles_per_chunk; Map_chunk *olist = gwin->get_map()->get_chunk(cx, cy); int tx = to.tx%c_tiles_per_chunk; // Get tile within chunk. int ty = to.ty%c_tiles_per_chunk; olist->setup_cache(); // Make sure cache is valid. int new_lift; // Might climb/descend. // For now, look at 1 tile's height, // and step up/down 2 (needed for SI // Crystal Ball). if (olist->is_blocked(1, to.tz, tx, ty, new_lift, get_move_flags(), 2, 2)) return -1; to.tz = new_lift; // (I don't think we should do this // above...) return 1; } /* * Estimate cost from one point to another. */ int Fast_pathfinder_client::estimate_cost ( Tile_coord& from, Tile_coord& to ) { return from.distance(to); // Distance() does world-wrapping. } /* * Is tile at goal? */ int Fast_pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { if (tile.distance(goal) > dist) return 0; // Not close enough. int dz = tile.tz - goal.tz; // Want to be within 1 story. return dz <= 5 && dz >= -5; } /* * Just test to see if an object can be grabbed. */ int Fast_pathfinder_client::is_grabable ( Tile_coord from, // From this spot. Tile_coord to // To this spot. ) { //No. from.tz = to.tz; // Just look along dest's lift. if (from.distance(to) <= 1) return 1; // Already okay. Fast_pathfinder_client client(1, Game_window::get_instance()->get_main_actor()->get_type_flags()); Astar path; return path.NewPath(from, to, &client); } /* * Check for an unblocked straight path. * NOTE1: This really has nothing to do with Fast_pathfinder_client. * NOTE2: This version doesn't check the z-coord at all. */ int Fast_pathfinder_client::is_straight_path ( Tile_coord from, // From this spot. Tile_coord to // To this spot. ) { to.tz = from.tz; // ++++++For now. Zombie path; if (!path.NewPath(from, to, 0)) // Should always succeed. return 0; Tile_coord t; // Check each tile. bool done; while (path.GetNextStep(t, done)) if (t != from && t != to && Map_chunk::is_blocked(t)) return 0; // Blocked. return 1; // Looks okay. } /* * Create client for getting within a desired distance of a * destination. */ Monster_pathfinder_client::Monster_pathfinder_client ( Actor *npc, // 'Monster'. Tile_coord dest, int dist ) : Fast_pathfinder_client(dist), destbox(dest.tx, dest.ty, 0, 0) { intelligence = npc->get_property(Actor::intelligence); Shape_info& info1 = npc->get_info(); axtiles = info1.get_3d_xtiles(); aytiles = info1.get_3d_ytiles(); aztiles = info1.get_3d_height(); set_move_flags(npc->get_type_flags()); destbox.enlarge(dist); // How close we need to get. } /* * Create client for combat pathfinding. */ Monster_pathfinder_client::Monster_pathfinder_client ( Actor *attacker, int reach, // Weapon reach in tiles. Game_object *opponent ) : Fast_pathfinder_client(reach), destbox(0, 0, 0, 0) { intelligence = attacker->get_property(Actor::intelligence); Shape_info& info1 = attacker->get_info(); axtiles = info1.get_3d_xtiles(); aytiles = info1.get_3d_ytiles(); aztiles = info1.get_3d_height(); if (!opponent) return; // Means this isn't usable. set_move_flags(attacker->get_type_flags()); Shape_info& info2 = opponent->get_info(); Tile_coord opos = opponent->get_tile(); int oxtiles = info2.get_3d_xtiles(), oytiles = info2.get_3d_ytiles(); destbox = Rectangle(opos.tx - oxtiles + 1, opos.ty - oytiles + 1, oxtiles, oytiles); destbox.enlarge(reach); // This is how close we need to get. } /* * Figure when to give up. */ int Monster_pathfinder_client::get_max_cost ( int cost_to_goal // From estimate_cost(). ) { int max_cost = 2*cost_to_goal; // Don't try to hard. int icost = 2 + 2*intelligence; // Limit by intelligence. if (max_cost > icost) // Note: intel. ranges from 0 to 30. max_cost = icost; Game_window *gwin = Game_window::get_instance(); // Limit to 3/4 screen width. int scost = ((3*gwin->get_width())/4)/c_tilesize; if (max_cost > scost) max_cost = scost; if (max_cost < 15) // But not too small. max_cost = 15; return max_cost; } /* * Is tile at goal? */ int Monster_pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { int dz = tile.tz - goal.tz; // Got to be on same floor. if (dz/5 != 0) return 0; Rectangle abox(tile.tx - axtiles + 1, tile.ty - aytiles + 1, axtiles, aytiles); return abox.intersects(destbox); } /* * Figure cost going from one tile to an adjacent tile (for pathfinding). * * Output: Cost, or -1 if blocked. * The 'tz' field in tile may be modified. */ int Monster_pathfinder_client::get_step_cost ( Tile_coord from, Tile_coord& to // The tile we're going to. The 'tz' // field may be modified. ) { if (Map_chunk::is_blocked(axtiles, aytiles, aztiles, from, to, get_move_flags())) return -1; else return 1; } exult-1.2/autogen.sh0000755000175000001440000000455507744254420010214 #!/bin/sh DIE=0 # Check for availability (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo "**Error**: You must have 'autoconf' installed to compile Exult." echo "Download the appropriate package for your distribution," echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" DIE=1 } (automake --version) < /dev/null > /dev/null 2>&1 || { echo "**Error**: You must have 'automake' installed to compile Exult." echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.4.tar.gz" echo "(or a newer version if it is available)" DIE=1 NO_AUTOMAKE=yes } # if no automake, don't bother testing for aclocal test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { echo "**Error**: Missing 'aclocal'. The version of 'automake'" echo "installed doesn't appear recent enough." echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.4.tar.gz" echo "(or a newer version if it is available)" DIE=1 } if test "$DIE" -eq 1; then exit 1 fi aclocalincludes="" if test -d "/usr/local/share/aclocal"; then if test "/usr/local/share/aclocal" != `aclocal --print-ac-dir`; then aclocalincludes="$aclocalincludes -I /usr/local/share/aclocal" fi fi #if test -d "$HOME/share/aclocal"; then # if test "$HOME/share/aclocal" != `aclocal --print-ac-dir`; then # aclocalincludes="$aclocalincludes -I $HOME/share/aclocal" # fi #fi # Clean up the generated crud rm -f configure config.log config.guess config.sub config.cache rm -f libtool ltmain.sh missing mkinstalldirs install-sh rm -f autoconfig.h.in rm -f config.status aclocal.m4 rm -f `find . -name 'Makefile.in'` rm -f audio/midi_drivers/Makefile audio/Makefile conf/Makefile data/Makefile \ debian/Makefile desktop/Makefile docs/Makefile files/zip/Makefile \ files/Makefile flic/Makefile gumps/Makefile imagewin/Makefile \ mapedit/Makefile objs/Makefile pathfinder/Makefile server/Makefile \ shapes/Makefile tools/Makefile usecode/compiler/Makefile \ usecode/ucxt/Docs/Makefile usecode/ucxt/data/Makefile \ usecode/ucxt/include/Makefile usecode/ucxt/src/Makefile \ usecode/ucxt/Makefile usecode/Makefile Makefile # touch the configure.ac file to force rebuilding configure touch configure.ac # Regenerate everything aclocal $aclocalincludes libtoolize --force --copy autoheader automake --add-missing --copy --gnu autoconf echo "You are now ready to run ./configure" exult-1.2/config.sub0000755000175000001440000007167410013577154010177 #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-09-05' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39 | mipstx39el \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic4x | c4x*) basic_machine=tic4x-unknown os=-coff ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: exult-1.2/segfile.h0000644000175000001440000000252307724430450007770 /* * segfile.h - Handle access to to a data file consisting of segments. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SEGFILE_H_ #define _SEGFILE_H_ #include #include #include "exult_types.h" /* * A class for accessing any 'segmented' file: */ class Segment_file { std::string filename; std::ifstream file; // For reading. uint32 num_segments; public: Segment_file(std::string nm); int get_num_segments() { return num_segments; } int is_good() { return (num_segments != 0); } // Return allocated buffer with data. char* retrieve(uint32 index, std::size_t& len); }; #endif exult-1.2/missing0000755000175000001440000002123110013577156007575 #! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.3 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar ${1+"$@"} && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar ${1+"$@"} && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 exult-1.2/args.h0000755000175000001440000000330307724430447007314 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ARGS_H_ #define _ARGS_H_ // Handy argument processor. I'm certain the implementation could be better // but it suffices quite well at the moment. #include "exult_types.h" #ifdef __DECCXX # undef declare #endif #ifndef ALPHA_LINUX_CXX # include #endif #include class Args { struct Opts { std::string option; bool *bval; std::string *sval; int *ival; uint32 *uval; bool dbval; std::string dsval; int dival; uint32 duval; enum { no_type=0,type_bool,type_string,type_int,type_unsigned } valuetype; Opts() :option(""),valuetype(no_type) {}; ~Opts() {}; }; std::vector options; public: Args() {}; ~Args() {}; void declare(const char *s,bool *b,bool defval=true); void declare(const char *s,std::string *b,const char *defval=0); void declare(const char *s,int *b,int defval=0); void declare(const char *s,uint32 *b,uint32 defval=0); void process(int argc,char **argv); }; #endif exult-1.2/game.cc0000644000175000001440000002575410054030531007416 /* * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include #endif #include "menulist.h" #include "Audio.h" #include "Configuration.h" #include "databuf.h" #include "exult.h" #include "exult_flx.h" #include "files/U7file.h" #include "files/utils.h" #include "flic/playfli.h" #include "font.h" #include "game.h" #include "bggame.h" #include "sigame.h" #include "devgame.h" #include "gamewin.h" #include "keys.h" #include "mouse.h" #include "palette.h" #include "shapeid.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::ifstream; using std::strcmp; using std::strcpy; using std::strncmp; using std::string; #endif bool Game::new_game_flag = false; bool Game::editing_flag = false; Game *game = 0; Exult_Game Game::game_type = BLACK_GATE; bool Game::expansion = false; static char av_name[17] = ""; static int av_sex = -1; static int av_skin = -1; std::string Game::gametitle; unsigned int Game::ticks = 0; Game::Game() : menushapes() { try { // Okay to fail if development game. menushapes.load(MAINSHP_FLX); } catch (const exult_exception &e) { if (!is_editing()) throw e; } jive = false; gwin = Game_window::get_instance(); win = gwin->get_win(); ibuf = win->get_ib8(); topx = (gwin->get_width()-320)/2; topy = (gwin->get_height()-200)/2; centerx = gwin->get_width()/2; centery = gwin->get_height()/2; } Game::~Game() { } Game *Game::create_game(Exult_Game mygame, const char *title) { switch(mygame) { case EXULT_DEVEL_GAME: assert(title != 0); gametitle = title; game_type = mygame; break; case SERPENT_ISLE: gametitle = "serpentisle"; break; case BLACK_GATE: default: gametitle = "blackgate"; break; } // See if map-editing. string d("config/disk/game/" + gametitle + "/editing"); config->value(d.c_str(), editing_flag, false); // Make aliases to the current game's paths. string system_path_tag(gametitle); to_uppercase(system_path_tag); clone_system_path("", "<" + system_path_tag + "_STATIC>"); clone_system_path("", "<" + system_path_tag + "_GAMEDAT>"); clone_system_path("", "<" + system_path_tag + "_SAVEGAME>"); if (is_system_path_defined("<" + system_path_tag + "_PATCH>")) clone_system_path("", "<" + system_path_tag + "_PATCH>"); else clear_system_path(""); U7mkdir("", 0755); // make sure savegame directory exists // Discover the game we are running (BG, SI, ...) // We do this, because we don't really trust config :-) if (game_type != EXULT_DEVEL_GAME) { char *static_identity = Game_window::get_game_identity( INITGAME); if (!strcmp(static_identity," ULTIMA7")) { game_type = BLACK_GATE; expansion = false; } else if (!strcmp(static_identity, "FORGE")) { game_type = BLACK_GATE; expansion = true; } else if (!strcmp(static_identity, "SERPENT ISLE")) { game_type = SERPENT_ISLE; expansion = false; } else if (!strcmp(static_identity, "SILVER SEED")) { game_type = SERPENT_ISLE; expansion = true; } delete[] static_identity; } switch(game_type) { case BLACK_GATE: cout << "Starting a BLACK GATE game" << endl; game = new BG_Game(); break; case SERPENT_ISLE: cout << "Starting a SERPENT ISLE game" << endl; game = new SI_Game(); break; case EXULT_DEVEL_GAME: cout << "Starting '" << gametitle << "' game" << endl; game = new DEV_Game(); break; default: game = 0; } std::cout << "Game path settings:" << std::endl; std::cout << "Static : " << get_system_path("") << std::endl; std::cout << "Gamedat : " << get_system_path("") << std::endl; std::cout << "Savegame: " << get_system_path("") << std::endl; if (is_system_path_defined("")) std::cout << "Patch : " << get_system_path("") << std::endl; else std::cout << "Patch : none" << std::endl; std::cout << std::endl; // This should probably go elsewhere Audio *audio = Audio::get_ptr(); if (audio) { MyMidiPlayer *midi = audio->get_midi(); if (midi) midi->load_patches(); } return game; } void Game::play_flic(const char *archive, int index) { char *fli_buf; size_t len; U7object flic(archive, index); fli_buf = flic.retrieve(len); playfli fli(fli_buf); fli.play(win); delete [] fli_buf; } void Game::play_audio(const char *archive, int index) { U7object speech(archive, index); // FIXME: should use a DataBuffer speech.retrieve("speech.voc"); Audio::get_ptr()->playfile("speech.voc", false); } void Game::play_midi(int track,bool repeat) { if (game_type == BLACK_GATE) Audio::get_ptr()->start_music(track,repeat,1); else if (game_type == SERPENT_ISLE) Audio::get_ptr()->start_music(track,repeat,2); } void Game::add_shape(const char *name, int shapenum) { shapes[name] = shapenum; } int Game::get_shape(const char *name) { return shapes[name]; } void Game::add_resource(const char *name, const char *str, int num) { resources[name].str = str; resources[name].num = num; } str_int_pair Game::get_resource(const char *name) { return resources[name]; } bool Game::show_menu(bool skip) { int menuy = topy+120; // Brand-new game in development? if (skip || (is_editing() && !U7exists(MAINSHP_FLX))) { bool first = !U7exists(IDENTITY); if (first) set_avname("Newbie"); if (!gwin->init_gamedat(first)) return false; return true; } ExultDataSource mouse_data(MAINSHP_FLX, 19); menu_mouse = new Mouse(gwin, mouse_data); top_menu(); MenuList *menu = 0; int menuchoices[] = { 0x04, 0x05, 0x08, 0x06, 0x11, 0x12, 0x07 }; int num_choices = sizeof(menuchoices)/sizeof(int); int *menuentries = new int[num_choices]; Vga_file exult_flx("/exult.flx"); char npc_name[16]; snprintf(npc_name, 16, "Exult"); bool play = false; bool fadeout = true; bool exitmenu = false; do { int entries = 0; if(!menu) { entries = 0; menu = new MenuList(); int offset = 0; for(int i=0; i/quotes.flg")) || (i==5 && U7exists("/endgame.flg"))) { menu->add_entry(new MenuEntry(menushapes.get_shape(menuchoices[i],1), menushapes.get_shape(menuchoices[i],0), centerx, menuy+offset)); offset += menushapes.get_shape(menuchoices[i],1)->get_ybelow() + 3; menuentries[entries++]=i; } } menu->set_selection(2); } bool created = false; int choice = menu->handle_events(gwin, menu_mouse); switch(choice<0?choice:menuentries[choice]) { case -1: // Exit pal->fade_out(c_fade_out_time); Audio::get_ptr()->stop_music(); throw quit_exception(); case 0: // Intro pal->fade_out(c_fade_out_time); play_intro(); gwin->clear_screen(true); top_menu(); break; case 2: // Journey Onwards created = gwin->init_gamedat(false); if(!created) { show_journey_failed(); top_menu(); menu->set_selection(1); break; } exitmenu = true; fadeout = true; play = true; break; case 1: // New Game if(!created) { if(new_game(menushapes)) exitmenu = true; else break; } else exitmenu = true; fadeout = false; play = true; break; case 3: // Credits pal->fade_out(c_fade_out_time); show_credits(); delete menu; menu = 0; top_menu(); break; case 4: // Quotes pal->fade_out(c_fade_out_time); show_quotes(); top_menu(); break; case 5: // End Game pal->fade_out(c_fade_out_time); end_game(true); top_menu(); break; case 6: // Return to Menu play = false; exitmenu = true; fadeout = true; break; default: break; } } while(!exitmenu); if (fadeout) { pal->fade_out(c_fade_out_time); gwin->clear_screen(true); } delete menu; delete[] menuentries; Audio::get_ptr()->stop_music(); delete menu_mouse; return play; } void Game::journey_failed_text() { Font *font = fontManager.get_font("MENU_FONT"); font->center_text(ibuf, centerx, centery+30, "You must start a new game first."); pal->fade_in(50); while (!wait_delay(10)) ; pal->fade_out(50); } const char *Game::get_avname () { if (av_name[0]) return av_name; else return NULL; } int Game::get_avsex () { return av_sex; } int Game::get_avskin () { return av_skin; } // Assume safe void Game::set_avname (char *name) { strcpy (av_name, name); } void Game::set_avsex (int sex) { av_sex = sex; } void Game::set_avskin (int skin) { av_skin = skin; } void Game::clear_avname () { av_name[0] = 0; new_game_flag = false; } void Game::clear_avsex () { av_sex = -1; } void Game::clear_avskin () { av_skin = -1; } // wait ms milliseconds, while cycling colours startcol to startcol+ncol-1 // return 0 if time passed completly, 1 if user pressed any key or mouse button, // and 2 if user pressed Return/Enter int wait_delay(int ms, int startcol, int ncol) { SDL_Event event; int delay; int loops; bool mouse_down = false; int loopinterval = (ncol == 0) ? 50 : 10; if (!ms) ms = 1; if(ms <= 2*loopinterval) { delay = ms; loops = 1; } else { delay = loopinterval; loops = ms/delay; } for(int i=0; i 0) { Game_window::get_instance()->get_win() ->rotate_colors(startcol, ncol, 1); if (ms > 250) Game_window::get_instance()->get_win()->show(); } unsigned long ticks2 = SDL_GetTicks(); if (ticks2 - ticks1 > delay) i+= (ticks2 - ticks1) / delay - 1; else SDL_Delay(delay - (ticks2 - ticks1)); } return 0; } exult-1.2/tiles.h0000644000175000001440000000466407724430450007502 /* * tiles.h - Tile coords. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_TILES #define INCL_TILES 1 #include "exult_constants.h" /* * A 3D tile coordinate: */ class Tile_coord { static short neighbors[16]; // Neighboring tiles in each dir. public: short tx, ty, tz; // Coords. within world. tz=lift. Tile_coord(int x, int y, int z) : tx(x), ty(y), tz(z) { } Tile_coord(): tx(0),ty(0),tz(0) { } int operator==(Tile_coord t2) { return t2.tx == tx && t2.ty == ty && t2.tz == tz; } int operator!=(Tile_coord t2) { return !(*this == t2); } int distance(Tile_coord t2) // Distance to another tile? { // Handle wrapping round the world. int dy = (t2.ty - ty + c_num_tiles)%c_num_tiles; int dx = (t2.tx - tx + c_num_tiles)%c_num_tiles; if (dy >= c_num_tiles/2)// World-wrapping. dy = c_num_tiles - dy; if (dx >= c_num_tiles/2) dx = c_num_tiles - dx; // Take larger abs. value. return (dy > dx ? dy : dx); } // Get neighbor in given dir (0-7). inline Tile_coord get_neighbor(int dir) { return Tile_coord( (tx + neighbors[2*dir] + c_num_tiles)%c_num_tiles, (ty + neighbors[2*dir + 1] + c_num_tiles)%c_num_tiles, tz); } static bool gte(int t1, int t2) // Ret. t1 >= t2 with wrapping. { int diff = t1 - t2; return diff >= 0 ? (diff < c_num_tiles/2) : diff < -c_num_tiles/2; } // Ret. (to - from) with wrapping. static int delta(int from, int to) { int diff = to - from; return diff >= c_num_tiles/2 ? (diff - c_num_tiles) : (diff <= -c_num_tiles/2 ? (diff + c_num_tiles) : diff); } }; // Add two coords. inline Tile_coord operator+(Tile_coord a, Tile_coord b) { return Tile_coord(a.tx + b.tx, a.ty + b.ty, a.tz + b.tz); } #endif exult-1.2/combat.h0000644000175000001440000000711407755325113007623 /* * combat.h - Combat scheduling. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef COMBAT_H #define COMBAT_H 1 #include "schedule.h" #include "lists.h" class Actor; class Spellbook_object; /* * Combat schedule: */ class Combat_schedule : public Schedule { protected: static unsigned long battle_time;// Time when battle started. static unsigned long battle_end_time; // And when it ended. enum Phase // We'll be a finite-state-machine. { initial = 0, // Just constructed. approach = 1, // Approaching a foe to attack. retreat = 2, // Avoiding a foe. flee = 3, // Run away! strike = 4, // In the process of striking. fire = 5, // In process of firing range weapon. parry = 6, // In the process of parrying a blow. stunned = 7, // Just been hit. wait_return = 8 // Wait for boomerang. } state; Schedule_types prev_schedule; // Before going into combat. Actor_queue opponents; // Possible opponents. Game_object *practice_target; // Only for duel schedule. int weapon_shape; // Weapon's shape in shapes.vga. int ammo_shape; // If required, else 0. int projectile_shape; // For shooting, else 0. Spellbook_object *spellbook; // If readied. // Ranges in tiles. // 0 means not applicable. unsigned char strike_range, projectile_range, max_range; bool is_thrown; // Daggers, etc. bool returns; // Boomerang, magic axe. bool no_blocking; // Weapon/ammo goes through walls. unsigned char yelled; // Yell when first opponent targeted. bool started_battle; // 1st opponent targeted. unsigned char fleed; // Incremented when fleeing. bool can_yell; int failures; // # failures to find opponent. unsigned int teleport_time; // Next time we can teleport. void start_battle(); // Play music at start of battle. bool teleport(); // For monsters that can. virtual void find_opponents(); Actor *find_protected_attacker();// Find attacker of protected member. Game_object *find_foe(int mode);// Find a new opponent. Game_object *find_foe(); void approach_foe(); // Approach foe. void start_strike(); void run_away(); Spellbook_object *readied_spellbook(); public: Combat_schedule(Actor *n, Schedule_types prev_sched); static void monster_died(); // Checks for victory. virtual void now_what(); // Npc calls this when it's done virtual void im_dormant(); // Npc calls this when it goes dormant. virtual void ending(int newtype);// Switching to another schedule. virtual void set_weapon(); // Set weapon info. bool has_started_battle() const { return started_battle; } }; /* * Dueling is like combat, but nobody gets hurt. */ class Duel_schedule : public Combat_schedule { Tile_coord start; // Starting position. int attacks; // Count strikes. virtual void find_opponents(); public: Duel_schedule(Actor *n); virtual void now_what(); }; bool In_ammo_family(int shnum, int family);// Yow, a global function. #endif exult-1.2/debian/0000777000175000001440000000000010062225335007476 5exult-1.2/debian/exult-tools.docs0000644000175000001440000000010207443662363012573 tools/expack.txt tools/ipack.txt docs/u7eggs.txt docs/newgame.txt exult-1.2/debian/dirs0000644000175000001440000000003407402744567010314 /usr/games /usr/share/games exult-1.2/debian/control0000644000175000001440000000313307405655616011035 Source: exult Section: contrib/games Priority: extra Maintainer: Michael Zinn Build-Depends: debhelper (>> 3.0.0) Standards-Version: 3.5.2 Package: exult Architecture: any Depends: ${shlibs:Depends} Recommends: timidity Description: An engine for Ultima VII (BG, FOV, SI, SS) Exult is an open source engine for playing Ultima VII on a variety of modern operating systems and environments. . Visit the Exult homepage at http://exult.sourceforge.net/ . You must own Ultima VII in order to use this package. Package: exult-tools Architecture: any Depends: exult, ${shlibs:Depends} Description: Tools for editting & viewing exult games; includes exult-studio Includes: . expack - Command line tool for creating and extracting Flex (.flx) files. Flex files are used by Ultima 7 to store most of its data. splitshp - Command line tool to take a multi-frame shp file and split it into its individual frames. shp2pcx - Command line tool to convert shp files to pcx format; the shp files can be extracted using expack. ucxt - Tool to translate usecode back into `human readable', roughly assembly like code. The output can be presented in a variety of different format, including one which will, later, have a suitable compiler back into usecode. ucc - A usecode compiler. exult_studio - An editor for games using the Exult engine. . These are all works in progress. . For more information, visit the Exult homepage at http://exult.sourceforge.net/. exult-1.2/debian/exult-tools.files0000644000175000001440000000037507443662363012761 usr/games/expack usr/games/ipack usr/games/textpack usr/games/splitshp usr/games/shp2pcx usr/games/ucxt usr/games/ucc usr/games/exult_studio usr/share/games/exult/u7opcodes.data usr/share/games/exult/u7misc.data usr/share/games/exult/exult_studio.glade exult-1.2/debian/cvs_build0000755000175000001440000000415507405655616011337 #!/bin/sh -e # Script to make a package from your current source tree, with appropriate # version number (and changelog etc) for a CVS build. # # Arguments: These get passed straight through to debuild; you probably want # something like # # debian/cvs_build -rfakeroot -us -uc # # (it builds an `experimental' package; I suppose you can sign it and upload # the source if you really want to). if [ ! -f ChangeLog -o ! -d debian ]; then echo "This should be run from the root of your exult source tree," echo "like so:" echo echo "debian/cvs_build" exit 1 fi # Generate the sub version string, which will be the date of the last (top) # change recorded in the ChangeLog, followed by two digits for the total # number of ChangeLog entries for this date (so that, hopefully, the exact # source could be retrieved, if desired... of course this relies on the # ChangeLog being appropriately updated all the time :P). If there are more # than 99 ChangeLog entries for the current day (!!), 99 is used. count_date=`grep '^[0-9]' ChangeLog | awk '{ print $1 }' | uniq -c | head -1 | tr -d '-'` count=`echo $count_date | awk '{ print $1 }'` date=`echo $count_date | awk '{ print $2 }'` if [ $count -ge 100 ]; then echo "WARNING more than 100 different log entries on this day, sub-day version number set to 99." $count=99 fi sub_ver=`printf "%d%02d" $date $count` # TODO Obtain the current upstream version "automatically" exult_ver="0.97cvs" full_ver="1:$exult_ver-$sub_ver" # Put an entry in the debian/changelog # TODO Should probably note the person who built this, rather than # `the exult team'; possibly control should be update as well... mv debian/changelog debian/changelog.tmp echo "\ exult ($full_ver) experimental; urgency=low * automatically generated entry for cvs build -- The Exult Team `date -R` " > debian/changelog cat debian/changelog.tmp >> debian/changelog debuild $* # Replace the old changelog (to keep CVS happy and also so they don't # accumulate; only real releases get the privilege of accumulating :P) mv debian/changelog.tmp debian/changelog exult-1.2/debian/files0000644000175000001440000000014007443662363010451 exult_0.98rc1-1_i386.deb contrib/games extra exult-tools_0.98rc1-1_i386.deb contrib/games extra exult-1.2/debian/rules0000755000175000001440000000565207405655616010522 #!/usr/bin/make -f # # Debug builds: # If the environment variable DEB_BUILD_OPTIONS contains the substring # debug , then the package is built with debugging info included. # # To go with this, you'll probably want to leave the binaries unstripped; # having the substring nostrip in DEB_BUILD_OPTIONS will achieve this. # # Alternatively, just uncomment the line below #export DEB_BUILD_OPTIONS=debug:nostrip:$DEB_BUILD_OPTIONS # For normal, everyday builds, you can leave DEB_BUILD_OPTIONS blank # or unset or whatever. # # NOTE, as of now (2001-12-12), the gimp plugin is not included in exult-tools, # as it requires a more recent version of gimp than is available in debian. # # Based on: # Sample debian rules that uses debhelper # GNU copyright 1997 by Joey Hess. # # Modified for exult and exult-tools by # Michael `Wumpus' Zinn # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This is the debhelper compatability version to use. export DH_COMPAT=3 ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) CONFIGURE_DEBUG = --enable-debug endif configure: configure-stamp configure-stamp: dh_testdir # Generate configure and various other things sh autogen.sh # Run configure; at time of writing, libdir, sbindir, etc, are not used ./configure $(CONFIGURE_DEBUG) --prefix=/usr --bindir=/usr/games --datadir=/usr/share/games --enable-exult-studio # Back to template land... touch configure-stamp build: configure-stamp build-stamp build-stamp: dh_testdir # Do the making :-) $(MAKE) # Back to template land... touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp # Clean up after ourselves -$(MAKE) clean # Back to template land... dh_clean install: DH_OPTIONS= install: build dh_testdir dh_testroot dh_clean -k dh_installdirs # Install the package into debian/tmp; dh_movefiles then puts # the files into debian/exult or debian/exult-tools as # required. $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp # Back to template land... dh_movefiles # Build architecture-independent files here. # Pass -i to all debhelper commands in this target to reduce clutter. binary-indep: # Nothing to do here (NB if there was, prerequisites of # `build' and `install' should be included) # Build architecture-dependent files here. binary-arch: build install dh_testdir -a dh_testroot -a # dh_installdebconf -a dh_installdocs -a dh_installexamples -a dh_installmenu -a # dh_installlogrotate -a # dh_installemacsen -a # dh_installpam -a # dh_installmime -a # dh_installinit -a dh_installcron -a # dh_installman -a dh_installinfo -a # dh_undocumented -a dh_installchangelogs ChangeLog -a dh_strip -a dh_link -a dh_compress -a dh_fixperms -a # dh_makeshlibs -a dh_installdeb -a # dh_perl -a dh_shlibdeps -a dh_gencontrol -a dh_md5sums -a dh_builddeb -a binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure exult-1.2/debian/changelog0000644000175000001440000000513307443662362011304 exult (1:0.98rc1-1) unstable; urgency=low * Release candidate 1 -- Tristan Tarrant Wed, 13 Mar 2002 10:32:11 +0100 exult (1:0.97cvs-1) unstable; urgency=low * exult-tools updated for new tools, and included some extra documentation, with corresponding update to README.Debian * added stuff for building a debug package (the nostrip stuff comes "for free" since dh_strip knows about it) -- Michael Zinn Wed, 12 Dec 2001 20:02:21 +1100 exult (1:0.96beta1-1) unstable; urgency=low * New upstream release * Corrected version numbering of Debian package * Overhaul of debian/* (incidentally closes a bug filed against exult) * Split into multiple packages - exult and exult-tools * Moved to contrib/games (until such time as there are `free' games built on this engine, which isn't likely to be anytime soon ;-p) -- Michael Zinn Sat, 1 Dec 2001 15:53:46 +1100 exult (0.99-cvs-1) unstable; urgency=low * Irregular synchronisation with source-tree -- Dancer Fri, 23 Feb 2001 12:01:25 +1100 exult (0.90-alpha1-8) unstable; urgency=low * Incorporate the gnome desktop files * Irregular synchronisation with source-tree -- Dancer Fri, 23 Feb 2001 12:01:25 +1100 exult (0.90-alpha1-7) unstable; urgency=low * Irregular synchronisation with source-tree -- Dancer Vesperman Tue, 21 Nov 2000 08:39:28 +1100 exult (0.90-alpha1-6) unstable; urgency=low * Irregular synchronisation with source-tree -- Dancer Vesperman Fri, 17 Nov 2000 18:35:44 +1100 exult (0.90-alpha1-5) unstable; urgency=low * Irregular CVS snapshot -- Dancer Vesperman Tue, 14 Nov 2000 14:14:56 +1100 exult (0.90-alpha1-4) unstable; urgency=low * Irregular CVS snapshot. Some egg bugs fixed. -- Dancer Vesperman Mon, 13 Nov 2000 10:27:03 +1100 exult (0.90-alpha1-3) unstable; urgency=low * Added some documentation to the package. * Daily snapshot of code-tree -- Dancer Vesperman Sat, 11 Nov 2000 11:29:59 +1100 exult (0.90-alpha1-2) unstable; urgency=low * Changed Suggests: timidity to Recommends: timidity -- Dancer Vesperman Fri, 10 Nov 2000 13:42:37 +1100 exult (0.90-alpha1-1) unstable; urgency=low * Initial Alpha Release. -- Dancer Vesperman Fri, 03 Nov 2000 18:11:55 +1000 Local variables: mode: debian-changelog End: exult-1.2/debian/exult-tools.README.Debian0000644000175000001440000000121007405655616013763 exult-tools meta-documentation Updated 2001-12-12 by Michael Zinn First, you'll want to checkout the docs that came with exult itself, in /usr/doc/exult; a lot of stuff for the tools is in amongst the main documentation. In this directory are some further documents relevant to particular tools: expack.txt - documentation for expack. Go figure :) Potentially useful for playing with exult_studio: u7eggs.txt - rough description of what the various egg types do. serpentsfx.txt - listing of the sound effect numbers in SI. (again, for egg editting or whatever) exult-1.2/debian/exult.docs0000644000175000001440000000005007405655616011440 FAQ MidiInfo.txt NEWS README README.1ST exult-1.2/debian/Makefile.am0000644000175000001440000000027307406075062011460 EXTRA_DIST= \ changelog \ control \ copyright \ cvs_build \ dirs \ exult.docs \ exult.files \ exult-tools.docs \ exult-tools.files \ exult-tools.README.Debian \ files \ rules exult-1.2/debian/Makefile.in0000644000175000001440000001373010061527071011464 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ EXTRA_DIST = \ changelog \ control \ copyright \ cvs_build \ dirs \ exult.docs \ exult.files \ exult-tools.docs \ exult-tools.files \ exult-tools.README.Debian \ files \ rules subdir = debian mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DIST_COMMON = Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu debian/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/debian/copyright0000644000175000001440000000047707402744567011376 This package was debianized by Michael Zinn on Sat, 1 Dec 2001 15:53:46 +1100. It was downloaded from http://exult.sourceforge.net/ Upstream Author(s): The Exult Team Copyright: GNU General Public License, version 2.0: see /usr/share/common-licenses/GPL-2 exult-1.2/debian/exult.files0000644000175000001440000000010107405655616011607 usr/share/games/exult/*.flx usr/man/man6/exult.6 usr/games/exult exult-1.2/menulist.h0000644000175000001440000000511607724430450010213 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MENULIST_H #define MENULIST_H #include #include #include "SDL_events.h" class Game_window; class Shape_frame; class Font; class Mouse; class MenuObject { public: Shape_frame *frame_on, *frame_off; int x, y, x1, y1, x2, y2; bool selected; bool dirty; MenuObject() { }; virtual ~MenuObject() { } void set_selected(bool sel) { dirty |= (selected != sel); selected = sel; } bool is_selected() { return selected; } bool is_mouse_over(int mx, int my) { return ((mx>=x1)&&(mx<=x2)&&(my>=y1)&&(my<=y2)); }; virtual void paint(Game_window *gwin) =0; virtual bool handle_event(SDL_Event& event) =0; }; class MenuEntry: public MenuObject { public: MenuEntry(Shape_frame *on, Shape_frame *off, int xpos, int ypos); virtual ~MenuEntry() { } virtual void paint(Game_window *gwin); virtual bool handle_event(SDL_Event& event); }; class MenuChoice: public MenuObject { private: std::vector *choices; int choice; Font *font; int max_choice_width; public: MenuChoice(Shape_frame *on, Shape_frame *off, int xpos, int ypos, Font *fnt); virtual ~MenuChoice() { delete choices; } void add_choice(const char *s); int get_choice() { return choice; } void set_choice(int c) { choice = c; } virtual void paint(Game_window *gwin); virtual bool handle_event(SDL_Event& event); }; class MenuList { private: std::vector *entries; bool selected; int selection; public: MenuList(): selected(false), selection(0) { entries = new std::vector(); } ~MenuList(); int add_entry(MenuObject *entry) { entries->push_back(entry); return (entries->size()-1);} void paint(Game_window *gwin); int handle_events(Game_window *gwin, Mouse *mouse); int get_selection() { return selection; } void set_selection(int sel); void set_selection(int x, int y); }; #endif exult-1.2/exult.h0000755000175000001440000000416407724430450007521 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EXULT_H #define EXULT_H #include "mouse.h" class Actor; class Cheat; class Configuration; class Game_window; class KeyBinder; class Tile_coord; class Paintable; /* * Get a click, or, optionally, a keyboard char. * * Output: 0 if user hit ESC. * Chr gets keyboard char., or 0 if it's was a mouse click. */ extern int Get_click ( int& x, int& y, // Location returned (if not ESC). Mouse::Mouse_shapes shape, // Mouse shape to use. char *chr = 0, // Char. returned if not null. bool drag_ok = false, // Can drag while here. Paintable *paint = 0 // Paint over everything else. ); /* * Make a screenshot of the current screen display */ extern void make_screenshot ( bool silent = false // If false, will display a success/failure message ); /* * Wait for someone to stop walking. If a timeout is given, at least * one animation cycle will still always occur. */ extern void Wait_for_arrival ( Actor *actor, // Whom to wait for. Tile_coord dest, // Where he's going. long maxticks = 0 // Max. # msecs. to wait, or 0. ); extern void change_gamma (bool down); extern void increase_resolution(); extern void decrease_resolution(); typedef enum { QUIT_TIME_NO = 0, QUIT_TIME_YES = 1, QUIT_TIME_RESTART = 2 } quitting_time_enum; extern KeyBinder *keybinder; extern Configuration *config; extern quitting_time_enum quitting_time; #endif exult-1.2/mkinstalldirs0000755000175000001440000000132210013577156011003 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here exult-1.2/dir.cc0000644000175000001440000000555107724430447007300 /* * dir.cc - Directions. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "dir.h" /* * Return the direction for a given slope (0-7). * NOTE: Assumes cartesian coords, NOT screen coords. (which have y * growing downwards). */ Direction Get_direction ( int deltay, int deltax ) { if (deltax == 0) return deltay > 0 ? north : south; int dydx = (1024*deltay)/deltax;// Figure 1024*tan. if (dydx >= 0) if (deltax >= 0) // Top-right quadrant? return dydx <= 424 ? east : dydx <= 2472 ? northeast : north; else // Lower-left. return dydx <= 424 ? west : dydx <= 2472 ? southwest : south; else if (deltax >= 0) // Lower-right. return dydx >= -424 ? east : dydx >= -2472 ? southeast : south; else // Top-left? return dydx >= -424 ? west : dydx >= -2472 ? northwest : north; } /* * Return the direction for a given slope (0-7), rounded to NSEW. * NOTE: Assumes cartesian coords, NOT screen coords. (which have y * growing downwards). */ Direction Get_direction4 ( int deltay, int deltax ) { if (deltax >= 0) // Right side? return (deltay > deltax ? north : deltay < -deltax ? south : east); else // Left side. return (deltay > -deltax ? north : deltay < deltax ? south : west); } /* * Return the direction for a given slope (0-15). * NOTE: Assumes cartesian coords, NOT screen coords. (which have y * growing downwards). */ int Get_direction16 ( int deltay, int deltax ) { if (deltax == 0) return deltay > 0 ? 0 : 8; int dydx = (1024*deltay)/deltax;// Figure 1024*tan. int adydx = dydx < 0 ? -dydx : dydx; int angle = 0; if (adydx < 1533) // 1024*tan(5*11.25) { if (adydx < 204) // 1024*tan(11.25). angle = 4; else if (adydx < 684) // 1024*tan(3*11.25). angle = 3; else angle = 2; } else { if (adydx < 5148) // 1024*tan(7*11.25). angle = 1; else angle = 0; } if (deltay < 0) // Check quadrants. if (deltax > 0) angle = 8 - angle; else angle += 8; else if (deltax < 0) angle = 16 - angle; return angle % 16; } exult-1.2/shapeid.h0000644000175000001440000001640510026506273007767 /* * Copyright (C) 2000-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SHAPEID_H #define SHAPEID_H 1 #include "exult_constants.h" #include "shapevga.h" #include "singles.h" class Shape_frame; class Shape_info; class Fonts_vga_file; class Font; class Image_buffer8; enum ShapeFile { SF_SHAPES_VGA = 0, // /shapes.vga. MUST be first. SF_GUMPS_VGA, // /gumps.vga SF_PAPERDOL_VGA, // /paperdol.vga SF_SPRITES_VGA, // /sprites.vga SF_FACES_VGA, // /faces.vga SF_EXULT_FLX, // /exult.flx SF_GAME_FLX, // /bg_data.flx or /si_data.flx SF_BG_SIGUMP_FLX, // BG only for Paperdolls SF_BG_SISHAPES_VGA, // BG only for Multiracial // Not yet //SF_FONTS_VGA, // /fonts.vga SF_OTHER, // Other unknown FLX SF_COUNT // # of preceding entries. }; // Special pixels. enum Pixel_colors {POISON_PIXEL = 0, PROTECT_PIXEL, CURSED_PIXEL, HIT_PIXEL, NPIXCOLORS}; /* * Manage the set of shape files. */ class Shape_manager : public Game_singletons { static Shape_manager *instance; // There shall be only one. Shapes_vga_file shapes; // Main 'shapes.vga' file. Vga_file files[(int) SF_COUNT]; // The files we manage. Fonts_vga_file *fonts; // "fonts.vga" file. Xform_palette xforms[11]; // Transforms translucent colors // 0xf4 through 0xfe. Xform_palette *invis_xform; // For showing invisible NPC's. unsigned char special_pixels[NPIXCOLORS]; // Special colors. bool bg_paperdolls_allowed; // Set true if the SI paperdoll file // is found when playing BG bool bg_paperdolls; // True if paperdolls are wanted in BG bool bg_multiracial_allowed; // Set true if the SI shapes file // is found when playing BG public: friend class ShapeID; Shape_manager(); ~Shape_manager(); static Shape_manager *get_instance() { return instance; } void load(); // Read in files. void reload_shapes(int dragtype); // Reload a shape file. Vga_file& get_file(enum ShapeFile f) { return files[(int) f]; }; Shapes_vga_file& get_shapes() { return shapes; } inline Xform_palette& get_xform(int i) { return xforms[i]; } // BG Only inline bool can_use_paperdolls() const { return bg_paperdolls_allowed; } inline bool get_bg_paperdolls() const { return bg_paperdolls; } inline void set_bg_paperdolls(bool p) { bg_paperdolls = p; } inline bool can_use_multiracial() const { return bg_multiracial_allowed; } // Paint shape in window. void paint_shape(int xoff, int yoff, Shape_frame *shape, int translucent = 0) { if (!shape || !shape->data) CERR("NULL SHAPE!!!"); else if (!shape->rle) shape->paint(xoff, yoff); else if (!translucent) shape->paint_rle(xoff, yoff); else shape->paint_rle_translucent(xoff, yoff, xforms, sizeof(xforms)/sizeof(xforms[0])); } inline void paint_invisible(int xoff, int yoff, Shape_frame *shape) { if (shape) shape->paint_rle_transformed( xoff, yoff, *invis_xform); } // Paint outline around a shape. inline void paint_outline(int xoff, int yoff, Shape_frame *shape, Pixel_colors pix) { if (shape) shape->paint_rle_outline( xoff, yoff, special_pixels[(int) pix]); } unsigned char get_special_pixel(Pixel_colors pix) { return special_pixels[(int) pix]; } // Paint text using "fonts.vga". int paint_text_box(int fontnum, const char *text, int x, int y, int w, int h, int vert_lead = 0, int pbreak = 0, int shading = -1); int paint_text(int fontnum, const char *text, int xoff, int yoff); int paint_text(int fontnum, const char *text, int textlen, int xoff, int yoff); // Get text width. int get_text_width(int fontnum, const char *text); int get_text_width(int fontnum, const char *text, int textlen); // Get text height, baseline. int get_text_height(int fontnum); int get_text_baseline(int fontnum); Font *get_font(int fontnum); }; /* * A shape ID contains a shape # and a frame # within the shape encoded * as a 2-byte quantity. */ class ShapeID : public Game_singletons { short shapenum; // Shape #. signed char framenum; // Frame # within shape. char has_trans; ShapeFile shapefile; Shape_frame *shape; Shape_frame* cache_shape(); public: // Create from map data. ShapeID(unsigned char l, unsigned char h) : shapenum(l + 256*(h&0x3)), framenum(h >> 2), has_trans(0), shapefile(SF_SHAPES_VGA), shape(0) { } // Read from buffer & incr. ptr. ShapeID(unsigned char *& data) : has_trans(0), shapefile(SF_SHAPES_VGA), shape(0) { unsigned char l = *data++; unsigned char h = *data++; shapenum = l + 256*(h&0x3); framenum = h >> 2; } // Create "end-of-list"/invalid entry. ShapeID() : shapenum(-1), framenum(-1), has_trans(0), shapefile(SF_SHAPES_VGA), shape(0) { } virtual ~ShapeID() { } // End-of-list or invalid? int is_invalid() const { return shapenum == -1; } int is_eol() const { return is_invalid(); } inline int get_shapenum() const { return shapenum; } inline int get_framenum() const { return framenum; } inline ShapeFile get_shapefile() const { return shapefile; } inline Shape_frame *get_shape() { return (shape!=0)?shape:cache_shape(); } inline void set_translucent(int trans) { has_trans=trans; } inline bool is_translucent() { if (shape==0) cache_shape(); return has_trans!=0; } // Set to given shape. void set_shape(int shnum, int frnum) { shapenum = shnum; framenum = frnum; shape = 0; } ShapeID(int shnum, int frnum, ShapeFile shfile = SF_SHAPES_VGA) : shapenum(shnum), framenum(frnum), shapefile(shfile), shape(0), has_trans(0) { } void set_shape(int shnum) // Set shape, but keep old frame #. { shapenum = shnum; shape = 0; } void set_frame(int frnum) // Set to new frame. { framenum = frnum; shape = 0; } void set_file(ShapeFile shfile) // Set to new flex { shapefile = shfile; shape = 0; } void paint_shape(int xoff, int yoff, bool force_trans = false) { sman->paint_shape(xoff, yoff, get_shape(), has_trans || force_trans); } void paint_invisible(int xoff, int yoff) { sman->paint_invisible(xoff, yoff, get_shape()); } // Paint outline around a shape. inline void paint_outline(int xoff, int yoff, Pixel_colors pix) { sman->paint_outline(xoff, yoff, get_shape(), pix); } int get_num_frames() const; Shape_info& get_info() const // Get info. about shape. { return Shape_manager::instance->shapes.get_info(shapenum); } static Shape_info& get_info(int shnum) // Get info. about shape. { return Shape_manager::instance->shapes.get_info(shnum); } }; /* * An interface used in Get_click(): */ class Paintable { public: virtual void paint() = 0; }; #endif exult-1.2/drag.h0000644000175000001440000000441607724430447007300 /* * drag.cc - Dragging objects in Game_window. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_DRAG_H #define INCL_DRAG_H #include "singles.h" /* * Data needed when dragging an object. */ class Dragging_info : public Game_singletons { Game_object *obj; // What's being dragged. bool is_new; // Object was newly created. Gump *gump; Gump_button *button; Tile_coord old_pos; // Original pos. of object if it wasn't // in a container. Rectangle old_foot; // Original footprint. int old_lift; // Lift of obj OR its owner. int quantity; // Amount of object being moved. int readied_index; // If it was a 'readied' item. // Last mouse, paint positions: int mousex, mousey, paintx, painty; Rectangle rect; // Rectangle to repaint. Image_buffer *save; // Image below dragged object. bool okay; // True if drag constructed okay. bool possible_theft; // Moved enough to be 'theft'. bool start(int x, int y); // First motion. void put_back(); // Put back object. bool drop_on_gump(int x, int y, Game_object *to_drop, Gump *gump); bool drop_on_map(int x, int y, Game_object *to_drop); bool drop(int x, int y); // Drop obj. at given position. public: friend class Game_window; // Create for dropping new object. Dragging_info(Game_object *newobj); Dragging_info(int x, int y); // Create for given mouse position. ~Dragging_info(); bool moved(int x, int y); // Mouse moved. void paint(); // Paint object being dragged. // Mouse button released. bool drop(int x, int y, bool moved); }; #endif /* INCL_DRAG_H */ exult-1.2/monsters.cc0000644000175000001440000003600210054030531010343 /* * monsters.cc - Monsters. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "monsters.h" #include "monstinf.h" #include "gamewin.h" #include "animate.h" #include "schedule.h" #include "chunks.h" #include "Audio.h" #include "gamemap.h" #include "game.h" #include "effects.h" #ifndef UNDER_CE using std::rand; #endif /* * Slimes move differently. */ class Slime_actor : public Monster_actor { void update_frames(Tile_coord src, Tile_coord dest); public: Slime_actor(const std::string &nm, int shapenum, int num = -1, int uc = -1) : Monster_actor(nm, shapenum, num, uc) { } // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame); // Remove/delete this object. virtual void remove_this(int nodel = 0); // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); }; /* * Monsters (like cyclops) that cause quakes when they walk: */ class Quaking_actor : public Monster_actor { int qsteps; // # steps between quakes. int steps; // # steps taken. public: Quaking_actor(const std::string &nm, int shapenum, int qs = 5, int num = -1, int uc = -1) : Monster_actor(nm, shapenum, num, uc), qsteps(qs), steps(0) { } // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame); }; Monster_actor *Monster_actor::in_world = 0; /* * Add to global list (if not already there). */ void Monster_actor::link_in ( ) { if (prev_monster || in_world == this) return; // Already in list. if (in_world) // Add to head. in_world->prev_monster = this; next_monster = in_world; in_world = this; } /* * Remove from global list (if in list). */ void Monster_actor::link_out ( ) { if (next_monster) next_monster->prev_monster = prev_monster; if (prev_monster) prev_monster->next_monster = next_monster; else // We're at start of list. if (in_world == this) in_world = next_monster; next_monster = prev_monster = 0; } /* * Create monster. */ Monster_actor::Monster_actor ( const std::string &nm, int shapenum, int num, // Generally -1. int uc ) : Npc_actor(nm, shapenum, num, uc), prev_monster(0), next_monster(0), animator(0) { // Check for animated shape. Shape_info& info = get_info(); if (info.is_animated()) animator = Animator::create(this); } /* * Delete. */ Monster_actor::~Monster_actor ( ) { delete animator; link_out(); // Remove from chain. } /* * Another set of constants that should be in a data file (or that's * probably already in one of the U7 data files), this one correlating * a 'monster' shape with the food frame you get when you kill it. */ static int Monster_food[] = { 498, 10, // Chicken. 500, 9, // Cow - beef steaks. 502, 14, // Deer - meat. 509, 12, // Fish. 811, 9, // Rabbit - same as cow? 970, 8, // Sheep - mutton. 727, 23, // Horse - ribs. 329, 11 // Boar - ham. }; /* * Find food frame for given monster shape. * * Output: Frame if found, else a random frame (0-31). */ static int Find_monster_food ( int shnum // Monster shape. ) { const int cnt = sizeof(Monster_food)/(2*sizeof(Monster_food[0])); for (int i = 0; i < cnt; i++) if (Monster_food[2*i] == shnum) return Monster_food[2*i + 1]; return rand()%32; } /* * Create an instance of a monster. */ Monster_actor *Monster_actor::create ( int shnum // Shape to use. ) { if (shnum == 529) // Slime? // Usecode = shape. return new Slime_actor("", shnum, -1, shnum); else if (shnum == 501 || (shnum == 380 && GAME_BG)) return new Quaking_actor("", shnum, 5, -1, shnum); else return new Monster_actor("", shnum, -1, shnum); } /* * Create an instance of a monster and initialize from monstinf.dat. */ Monster_actor *Monster_actor::create ( int shnum, // Shape to use. Tile_coord pos, // Where to place it. If pos.tx < 0, // it's not placed in the world. int sched, // Schedule type. int align, // Alignment. bool temporary, bool equipment ) { // Get 'monsters.dat' info. const Monster_info *inf = ShapeID::get_info(shnum).get_monster_info(); if (!inf) inf = Monster_info::get_default(); Monster_actor *monster = create(shnum); monster->set_alignment(align == static_cast(Actor::neutral) ? inf->alignment : align); // Movement flags if ((inf->flags >> Monster_info::fly)&1) { monster->set_type_flag(Actor::tf_fly); } if ((inf->flags >> Monster_info::swim)&1) { monster->set_type_flag(Actor::tf_swim); } if ((inf->flags >> Monster_info::walk)&1) { monster->set_type_flag(Actor::tf_walk); } if ((inf->flags >> Monster_info::ethereal)&1) { monster->set_type_flag(Actor::tf_ethereal); } monster->set_property(Actor::strength, inf->strength); // Max. health = strength. monster->set_property(Actor::health, inf->strength); monster->set_property(Actor::dexterity, inf->dexterity); monster->set_property(Actor::intelligence, inf->intelligence); monster->set_property(Actor::combat, inf->combat); // Set temporary if (temporary) monster->set_flag (Obj_flags::is_temporary); monster->set_invalid(); // Place in world. if (pos.tx >= 0) monster->move(pos.tx, pos.ty, pos.tz); if (equipment) { // Get equipment. int equip_offset = inf->equip_offset; Equip_record *equip = inf->equip; if (equip_offset && equip_offset - 1 < inf->equip_cnt) { Equip_record& rec = equip[equip_offset - 1]; for (size_t i = 0; i < sizeof(equip->elements)/sizeof( equip->elements[0]); i++) { // Give equipment. Equip_element& elem = rec.elements[i]; if (!elem.shapenum || 1 + rand()%100 > elem.probability) continue;// You lose. int frnum = (elem.shapenum == 377) ? Find_monster_food(shnum) : 0; monster->create_quantity(elem.quantity, elem.shapenum, c_any_qual, frnum, temporary); } } } if (sched < 0) // Set sched. AFTER equipping. sched = static_cast(Schedule::loiter); monster->set_schedule_type(sched); return (monster); } /* * Delete all monsters. (Should only be called after deleting chunks.) */ void Monster_actor::delete_all ( ) { while (in_world) delete in_world; } /* * Render. */ void Monster_actor::paint ( ) { // Animate first if (animator) // Be sure animation is on. animator->want_animation(); Npc_actor::paint(); // Draw on screen. } /* * Step onto an adjacent tile. * * Output: 0 if blocked. * Dormant is set if off screen. */ int Monster_actor::step ( Tile_coord t, // Tile to step onto. int frame // New frame #. ) { // If move not allowed do I remove or change destination? // I'll do nothing for now if (!gwin->emulate_is_move_allowed(t.tx, t.ty)) return (0); if (get_flag(Obj_flags::paralyzed)) return 0; // Store old chunk. int old_cx = get_cx(), old_cy = get_cy(); // Get chunk. int cx = t.tx/c_tiles_per_chunk, cy = t.ty/c_tiles_per_chunk; // Get ->new chunk. Map_chunk *nlist = gmap->get_chunk(cx, cy); nlist->setup_cache(); // Setup cache if necessary. // Blocked? if (is_blocked(t)) { if (schedule) // Tell scheduler. schedule->set_blocked(t); stop(); if (!gwin->add_dirty(this)) dormant = true; // Off-screen. return (0); // Done. } // Check for scrolling. gwin->scroll_if_needed(this, t); add_dirty(); // Set to repaint old area. // Get old chunk. Map_chunk *olist = gmap->get_chunk(old_cx, old_cy); // Move it. // Get rel. tile coords. int tx = t.tx%c_tiles_per_chunk, ty = t.ty%c_tiles_per_chunk; movef(olist, nlist, tx, ty, frame, t.tz); if (!add_dirty(1) && // And > a screenful away? distance(gwin->get_camera_actor()) > 1 + 320/c_tilesize) { // No longer on screen. stop(); dormant = true; return (0); } return (1); // Add back to queue for next time. } /* * Remove an object from its container, or from the world. * The object is deleted. */ void Monster_actor::remove_this ( int nodel // 1 to not delete. ) { link_out(); // Remove from list. Npc_actor::remove_this(nodel); } /* * Move (teleport) to a new spot. */ void Monster_actor::move ( int newtx, int newty, int newlift ) { Npc_actor::move(newtx, newty, newlift); link_in(); // Insure it's in global list. } /* * Add an object. * * Output: 1, meaning object is completely contained in this, * 0 if not enough space. */ bool Monster_actor::add ( Game_object *obj, bool dont_check, // 1 to skip volume check. bool combine // True to try to combine obj. MAY // cause obj to be deleted. ) { // Try to add to 'readied' spot. if (Npc_actor::add(obj, true, combine)) return (true); // Successful. // Just add anything. return Container_game_object::add(obj, true, combine); } /* * Get total value of armor being worn. */ int Monster_actor::get_armor_points ( ) { Monster_info *inf = get_info().get_monster_info(); // Kind of guessing here. return Actor::get_armor_points() + (inf ? inf->armor : 0); } /* * Get weapon value. */ Weapon_info *Monster_actor::get_weapon ( int& points, int& shape ) { Monster_info *inf = get_info().get_monster_info(); // Kind of guessing here. Weapon_info *winf = Actor::get_weapon(points, shape); if (!winf) // No readied weapon? { // Look up monster itself. shape = 0; winf = get_info().get_weapon_info(); if (winf) { shape = get_shapenum(); points = winf->get_damage(); } else if (inf) // Builtin (claws?): points = inf->weapon; } return winf; } /* * We're dead. We're removed from the world, but not deleted. */ void Monster_actor::die ( Actor *attacker ) { Actor::die(attacker); // Got to delete this somewhere, but // doing it here crashes. } /* * Get the tiles where slimes adjacent to one in a given position should * be found. */ static void Get_slime_neighbors ( Tile_coord pos, // Position to look around. Tile_coord *neighbors // N,E,S,W tiles returned. ) { // Offsets to neighbors 2 tiles away. static int offsets[8] = {0,-2, 2,0, 0,2, -2,0}; for (int dir = 0; dir < 4; dir++) neighbors[dir] = pos +Tile_coord(offsets[2*dir], offsets[2*dir + 1], 0); } /* * Find whether a slime is a neighbor of a given spot. * * Output: Direction (0-3 for N,E,S,W), or -1 if not found. */ int Find_neighbor ( Game_object *slime, Tile_coord *neighbors // Neighboring spots to check. ) { Tile_coord pos = slime->get_tile(); for (int dir = 0; dir < 4; dir++) if (pos == neighbors[dir]) return dir; return -1; // Not found. } /* * Update the frame of a slime and its neighbors after it has been moved. * The assumption is that slimes are 2x2 tiles, and that framenum/2 is * based on whether there are adjoining slimes to the N, W, S, or E, with * bit 0 being random. */ void Slime_actor::update_frames ( Tile_coord src, // May be invalid (tx = -1). Tile_coord dest // May be invalid. If src & dest are // both valid, we assume they're at // most 2 tiles apart. ) { Tile_coord neighbors[4]; // Gets surrounding spots for slimes. int dir; // Get direction of neighbor. Game_object_vector nearby; // Get nearby slimes. if (src.tx != -1) if (dest.tx != -1) // Assume within 2 tiles. Game_object::find_nearby(nearby, dest, 529, 4, 8); else Game_object::find_nearby(nearby, src, 529, 2, 8); else // Assume they're both not invalid. Game_object::find_nearby(nearby, dest, 529, 2, 8); if (src.tx != -1) // Update neighbors we moved from. { Get_slime_neighbors(src, neighbors); for (Game_object_vector::const_iterator it = nearby.begin(); it != nearby.end(); ++it) { Game_object *slime = *it; if (slime != this && (dir = Find_neighbor(slime, neighbors)) >= 0) { int ndir = (dir+2)%4; // Turn off bit (1<change_frame((slime->get_framenum()& ~(((1<= 0) { // In a neighboring spot? frnum |= (1<change_frame((slime->get_framenum()&~1)| ((1<create_ireg_object(912, 4 + rand()%8); b->set_flag(Obj_flags::is_temporary); b->move(oldpos); } return ret; } /* * Remove an object from its container, or from the world. * The object is deleted. */ void Slime_actor::remove_this ( int nodel // 1 to not delete. ) { Tile_coord pos = get_tile(); Monster_actor::remove_this(nodel); // Update surrounding slimes. update_frames(pos, Tile_coord(-1, -1, -1)); } /* * Move (teleport) to a new spot. I assume slimes only use this when * being added to the world. */ void Slime_actor::move ( int newtx, int newty, int newlift ) { // Save old pos. Tile_coord pos = get_tile(); if (get_cx() == 255) // Invalid? pos = Tile_coord(-1, -1, -1); Monster_actor::move(newtx, newty, newlift); // Update surrounding frames (& this). update_frames(pos, get_tile()); } /* * Step onto an adjacent tile. * * Output: 0 if blocked. * Dormant is set if off screen. */ int Quaking_actor::step ( Tile_coord t, // Tile to step onto. int frame // New frame #. ) { int ret = Monster_actor::step(t, frame); if (ret) { steps = (steps + 1)%qsteps; if (!steps) // Time to roll? gwin->get_tqueue()->add(Game::get_ticks() + 10, new Earthquake(2), 0L); } return ret; } exult-1.2/game.h0000644000175000001440000000752310002523154007253 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GAME_H #define GAME_H #include #include #include "hash_utils.h" #include "exult_constants.h" #include "palette.h" #include "vgafile.h" #include "singles.h" class Game_window; class Image_window8; class Image_buffer8; class Mouse; struct str_int_pair { const char *str; int num; }; enum Exult_Game { NONE, BLACK_GATE, SERPENT_ISLE, EXULT_DEVEL_GAME // One that we develop. }; #define GAME_BG (Game::get_game_type() == BLACK_GATE) #define GAME_SI (Game::get_game_type() == SERPENT_ISLE) #define GAME_FOV (Game::get_game_type()==BLACK_GATE && Game::has_expansion()) #define GAME_SS (Game::get_game_type()==SERPENT_ISLE && Game::has_expansion()) class Game : public Game_singletons { private: static bool new_game_flag; static Exult_Game game_type; static bool expansion; #ifndef DONT_HAVE_HASH_MAP hash_map shapes; hash_map resources; #else /* !HAVE_HASH_MAP */ std::map shapes; std::map resources; #endif Mouse *menu_mouse; static std::string gametitle; static unsigned int ticks; protected: static bool editing_flag; int topx, topy, centerx, centery; Vga_file menushapes; bool jive; public: Game_window *gwin; Image_window8 *win; Image_buffer8 *ibuf; // Palette pal; Game(); virtual ~Game(); static void set_new_game() { new_game_flag = true; } static bool is_new_game() { return new_game_flag; } static bool is_editing() { return editing_flag; } static Game *create_game(Exult_Game mygame, const char *title = 0); static Exult_Game get_game_type() { return game_type; } static bool has_expansion() { return expansion; } static const char *get_avname (); static int get_avsex (); static int get_avskin (); static void set_avname (char *name); static void set_avsex (int sex); static void set_avskin (int skin); static void clear_avname (); static void clear_avsex (); static void clear_avskin (); static std::string get_gametitle() { return gametitle; } virtual void play_intro() =0; virtual void end_game(bool success) =0; virtual void top_menu() =0; virtual void show_quotes() =0; virtual void show_credits() =0; virtual bool new_game(Vga_file &shapes) =0; virtual int get_start_tile_x() =0; virtual int get_start_tile_y() =0; virtual void show_journey_failed() = 0; void play_flic(const char *archive, int index); void play_audio(const char *archive, int index); void play_midi(int track, bool repeat = false); void add_shape(const char *name, int shapenum); int get_shape(const char *name); void add_resource(const char *name, const char *str, int num); str_int_pair get_resource(const char *name); bool show_menu(bool skip = false); void journey_failed_text(); void set_jive () {jive = true;} void clear_jive () {jive = false;} inline static unsigned int get_ticks() { return ticks; } inline static void set_ticks(unsigned int t) { ticks = t; } }; extern Game *game; extern int wait_delay(int ms, int startcol = 0, int ncol = 0); extern Exult_Game exult_menu(Game_window *gwin); #endif exult-1.2/mouse.h0000644000175000001440000001167707724430450007514 /* * mouse.h - Mouse pointers. * * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MOUSE_H_ #define _MOUSE_H_ #include "rect.h" #include "dir.h" #include "iwin8.h" #include "vgafile.h" #include "glshape.h" /* * Handle custom mouse pointers. */ class Mouse { protected: Shape_file pointers; // Pointers from 'pointers.shp'. Game_window *gwin; // Where to draw. Image_window8 *iwin; // From gwin. Image_buffer *backup; // Stores image below mouse shape. Rectangle box; // Area backed up. Rectangle dirty; // Dirty area from mouse move. int mousex, mousey; // Last place where mouse was. int cur_framenum; // Frame # of current shape. Shape_frame *cur; // Current shape. unsigned char focus; // 1 if we have focus. unsigned char onscreen; // 1 if mouse is drawn on screen. static short short_arrows[8]; // Frame #'s of short arrows, indexed // by direction (0-7, 0=east). static short med_arrows[8]; // Medium arrows. static short long_arrows[8]; // Frame #'s of long arrows. static short short_combat_arrows[8]; // Short red arrows static short med_combat_arrows[8]; // Medium red arrows void set_shape0(int framenum); // Set shape without checking first. void Init(); public: enum Mouse_shapes // List of shapes' frame #'s. { dontchange = 1000, // Flag to not change. hand = 0, redx = 1, greenselect = 2, // For modal select. tooheavy = 3, outofrange = 4, outofammo = 5, wontfit = 6, hourglass = 7, greensquare = 23, blocked = 49 }; /* Avatar speed, relative to standard delay: * avatar_speed = standard_delay * 100 / avatar_speed_factor * * * Experimental results, Serpent Isle * * "short" arrow within central 0.4 of screen in each dimension * "middle" arrow within central 0.8 of screen in each dimension * "long" arrow (non-combat, non-threat only) outside * * relative speeds: * (movement type - time for a certain dist. - rel. speed) * non-combat short arrow - 8 - 1 * non-combat medium arrow - 4 - 2 * non-combat long arrow - 2 - 4 * combat short arrow - 8 - 1 * combat medium arrow - 6 - 4/3 */ enum Avatar_Speed_Factors { slow_speed_factor = 100, medium_combat_speed_factor = 133, medium_speed_factor = 200, fast_speed_factor = 400 }; int avatar_speed; static bool mouse_update; static Mouse* mouse; Mouse(Game_window *gw); Mouse(Game_window *gw, DataSource& shapes); ~Mouse(); void show(); // Paint it. void hide() // Restore area under mouse. { if (onscreen) { onscreen = 0; iwin->put(backup, box.x, box.y); dirty = box; // Init. dirty to box. } } void set_shape(int framenum) // Set to desired shape. { if (framenum != cur_framenum) set_shape0(framenum); } void set_shape(Mouse_shapes shape) { set_shape(static_cast(shape)); } Mouse_shapes get_shape() { return (Mouse_shapes) cur_framenum; } void move(int x, int y); // Move to new location (mouse motion). void blit_dirty() // Blit dirty area. { // But not in OpenGL. if (!GL_manager::get_instance()) iwin->show(dirty.x - 1, dirty.y - 1, dirty.w + 2, dirty.h + 2); } void set_location(int x, int y);// Set to given location. // Flash desired shape for 1/2 sec. void flash_shape(Mouse_shapes flash); // Set to short arrow. int get_short_arrow(Direction dir) { return (short_arrows[static_cast(dir)]); } // Set to medium arrow. int get_medium_arrow(Direction dir) { return (med_arrows[static_cast(dir)]); } // Set to long arrow. int get_long_arrow(Direction dir) { return (long_arrows[static_cast(dir)]); } // Set to short combat mode arrow. int get_short_combat_arrow(Direction dir) { return (short_combat_arrows[static_cast(dir)]); } // Set to medium combat mode arrow. int get_medium_combat_arrow(Direction dir) { return (med_combat_arrows[static_cast(dir)]); } unsigned char is_onscreen() { return onscreen; } //inline const int get_mousex() const { return mousex; } //inline const int get_mousey() const { return mousey; } // Sets hand or speed cursors void set_speed_cursor(); }; #endif exult-1.2/Makefile.am0000644000175000001440000001104410054030527010222 INCLUDES = -I$(srcdir) -I$(srcdir)/headers -I$(srcdir)/imagewin -I$(srcdir)/shapes \ -I$(srcdir)/server -I$(srcdir)/data \ -I$(srcdir)/objs -I$(srcdir)/conf -I$(srcdir)/files -I$(srcdir)/gumps \ -I$(srcdir)/audio -I$(srcdir)/pathfinder -I$(srcdir)/usecode \ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(EXE_TARGET) SUBDIRS = files conf shapes imagewin tools data flic audio pathfinder gumps \ usecode objs server mapedit debian desktop docs bin_PROGRAMS = exult exult_SOURCES = \ actions.cc \ actions.h \ actorio.cc \ actors.cc \ actors.h \ alloc.cc \ alpha_kludges.h \ args.cc \ args.h \ autoarray.h \ bggame.cc \ bggame.h \ browser.cc \ browser.h \ cheat.cc \ cheat.h \ cheat_screen.cc \ cheat_screen.h \ combat.cc \ combat.h \ combat_opts.h \ delobjs.cc \ delobjs.h \ devgame.cc \ devgame.h \ dir.cc \ dir.h \ drag.cc \ drag.h \ effects.cc \ effects.h \ exult.cc \ exult.h \ exulticon.h \ exultmenu.cc \ exultmenu.h \ exult_types.h \ exult_constants.h \ fnames.h \ frameseq.h \ game.cc \ game.h \ gameclk.cc \ gameclk.h \ gamedat.cc \ gamemap.cc \ gamemap.h \ gamerend.cc \ gamerend.h \ gamewin.cc \ gamewin.h \ hash_utils.h \ keys.cc \ keys.h \ keyactions.cc \ keyactions.h \ lists.h \ menulist.cc \ menulist.h \ monsters.cc \ monsters.h \ mouse.cc \ mouse.h \ npcnear.cc \ npcnear.h \ npctime.cc \ npctime.h \ palette.cc \ palette.h \ party.cc \ party.h \ paths.cc \ paths.h \ readnpcs.cc \ ready.h \ rect.h \ schedule.cc \ schedule.h \ segfile.cc \ segfile.h \ shapeid.cc \ shapeid.h \ sigame.cc \ sigame.h \ singles.h \ tiles.h \ tqueue.cc \ tqueue.h \ txtscroll.cc \ txtscroll.h \ vec.h \ version.cc \ version.h \ xdrag.cc \ xdrag.h EXULTLIBS = \ pathfinder/libpathfinder.la \ audio/libaudio.la \ audio/midi_drivers/libmididrv.la \ flic/libflic.la \ conf/libconf.la \ imagewin/libimagewin.la \ server/libserver.la \ usecode/libusecode.la \ shapes/libshapes.la \ objs/libobjs.la \ gumps/libgumps.la \ files/libu7file.la \ files/zip/libminizip.la exult_LDADD = \ $(EXULTLIBS) \ $(SDL_LIBS) $(KMID_LIBS) $(SYSLIBS) $(x_libraries) $(ICON_FILE) \ $(ZLIB_LIBS) $(OPENGL_LIBS) exult_DEPENDENCIES = $(ICON_FILE) $(EXULTLIBS) noinst_HEADERS = \ alpha_kludges.h EXTRA_DIST = \ autogen.sh \ README.1ST \ README \ FAQ \ README.win32 \ README.axp \ README.BeOS \ README.MacOS \ README.MacOSX \ README.AmigaOS \ README.MorphOS \ README.Qtopia \ Makefile.be \ Makefile.common \ Makefile.mingw \ Makefile.studio.mingw \ Makefile.MorphOS \ Info.plist.in \ exult.spec \ windrag.cc \ windrag.h \ win32/exult.ico \ win32/exultico.rc \ win32/exultstudio.ico \ win32/exultstudioico.rc \ beos/exult.rsrc \ mac/exult_icon.rsrc.bin \ mac/ExultMac.mcp.xml.sit \ mac/exult_version.rsrc.bin \ mac/mac_autoconfig.h \ mac/mac_prefix.h \ macosx/exult.icns \ msvcstuff/expack.vcproj \ msvcstuff/Exult.vcproj \ msvcstuff/Exult.sln \ msvcstuff/Exult_bg_flx.vcproj \ msvcstuff/Exult_flx.vcproj \ msvcstuff/Exult_si_flx.vcproj \ msvcstuff/mklink.vcproj \ msvcstuff/msvc_kludges.cc \ msvcstuff/msvc_kludges.h \ msvcstuff/rip.vcproj \ msvcstuff/shp2pcx.vcproj \ msvcstuff/splitshp.vcproj \ msvcstuff/ucdump.vcproj \ msvcstuff/unistd.h \ msvcstuff/wuc.vcproj \ msvcstuff/wud.vcproj \ msvcstuff/Zip.vcproj \ msvcstuff/exconfig/exconfig.cpp \ msvcstuff/exconfig/exconfig.def \ msvcstuff/exconfig/exconfig.vcproj \ msvcstuff/exconfig/exconfig.h \ msvcstuff/exconfig/exconfig.rc \ msvcstuff/exconfig/resource.h \ msvcstuff/exconfig/StdAfx.cpp \ msvcstuff/exconfig/StdAfx.h \ headers/common_types.h \ headers/exceptions.h \ headers/gamma.h \ server/servewin32.cc \ server/servewin32.h win32/exultico.o: $(srcdir)/win32/exultico.rc $(srcdir)/win32/exult.ico -mkdir win32 cp $(srcdir)/win32/exult.ico win32 windres $(srcdir)/win32/exultico.rc win32/exultico.o CLEANFILES = *~ if MACOSX bundle_name = Exult.app Exult_app: ${EXE_TARGET} mkdir -p $(bundle_name)/Contents/MacOS mkdir -p $(bundle_name)/Contents/Resources echo "APPL????" > $(bundle_name)/Contents/PkgInfo $(INSTALL_DATA) Info.plist $(bundle_name)/Contents/ $(INSTALL_PROGRAM) $< $(bundle_name)/Contents/MacOS/ $(INSTALL_DATA) macosx/exult.icns $(bundle_name)/Contents/Resources/ install-exec-local: Exult_app mkdir -p $(DESTDIR)/Applications/ cp -r $(bundle_name) $(DESTDIR)/Applications/ else install-exec-local: endif exult-1.2/Makefile.be0000644000175000001440000000273310012400054010206 # Exult makefile for use in BeOS # It may require a little tweaking. (paths) # Base of the exult source SRC=. ### Modify these paths SDL_CFLAGS=-I/boot/develop/tools/gnupro/include/SDL SDL_LIBS=-L/boot/develop/tools/gnupro/lib -lSDLmain -lSDL -lSDL_mixer CPPFLAGS=-DVERSION=\"$(VERSION)\" -DBEOS -DDEBUG -DEXULT_DATADIR=\"data\" \ -DHAVE_ZIP_SUPPORT -I$(SRC)/files/zip \ -I$(SRC)/imagewin -I$(SRC)/shapes -I$(SRC)/data -I$(SRC)/tools \ -I$(SRC)/files -I$(SRC) -I$(SRC)/audio -I$(SRC)/conf \ -I$(SRC)/gumps -I$(SRC)/objs -I$(SRC)/pathfinder -I$(SRC)/usecode -I$(SRC)/headers -DHAVE_SNPRINTF $(SDL_CFLAGS) CXXFLAGS=-O2 -Wall LFLAGS= LIBS=$(SDL_LIBS) -lmidi -lbe -lz EXEC=exult MIDI_DRV_OBJS=be_midi.o # unused: KMIDI.o Timidity_binary.o forked_player.o win_MCI.o include Makefile.common beos/exult.rsrc : beos/exult.rsrc xres -o $(EXEC) beos/exult.rsrc finishedbinary: $(EXEC) strip $(EXEC) xres -o $(EXEC) beos/exult.rsrc run: $(EXEC) ./$(EXEC) bindist: finishedbinary rm -rf exult-$(VERSION) mkdir exult-$(VERSION) mkdir exult-$(VERSION)/data mkdir exult-$(VERSION)/doc mkdir exult-$(VERSION)/lib cp $(EXEC) exult-$(VERSION) cp README FAQ README.BeOS COPYING NEWS AUTHORS ChangeLog exult-$(VERSION)/doc cp data/exult.flx data/exult_bg.flx data/exult_si.flx exult-$(VERSION)/data cp $(HOME)/lib/libSDL.so $(HOME)/lib/README-SDL.txt exult-$(VERSION)/lib rm -f exult-$(VERSION).x86.beos.zip zip -r exult-$(VERSION).x86.beos.zip exult-$(VERSION) rm -rf exult-$(VERSION) exult-1.2/Makefile.in0000644000175000001440000006527410061527024010252 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir) -I$(srcdir)/headers -I$(srcdir)/imagewin -I$(srcdir)/shapes \ -I$(srcdir)/server -I$(srcdir)/data \ -I$(srcdir)/objs -I$(srcdir)/conf -I$(srcdir)/files -I$(srcdir)/gumps \ -I$(srcdir)/audio -I$(srcdir)/pathfinder -I$(srcdir)/usecode \ $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(EXE_TARGET) SUBDIRS = files conf shapes imagewin tools data flic audio pathfinder gumps \ usecode objs server mapedit debian desktop docs bin_PROGRAMS = exult exult_SOURCES = \ actions.cc \ actions.h \ actorio.cc \ actors.cc \ actors.h \ alloc.cc \ alpha_kludges.h \ args.cc \ args.h \ autoarray.h \ bggame.cc \ bggame.h \ browser.cc \ browser.h \ cheat.cc \ cheat.h \ cheat_screen.cc \ cheat_screen.h \ combat.cc \ combat.h \ combat_opts.h \ delobjs.cc \ delobjs.h \ devgame.cc \ devgame.h \ dir.cc \ dir.h \ drag.cc \ drag.h \ effects.cc \ effects.h \ exult.cc \ exult.h \ exulticon.h \ exultmenu.cc \ exultmenu.h \ exult_types.h \ exult_constants.h \ fnames.h \ frameseq.h \ game.cc \ game.h \ gameclk.cc \ gameclk.h \ gamedat.cc \ gamemap.cc \ gamemap.h \ gamerend.cc \ gamerend.h \ gamewin.cc \ gamewin.h \ hash_utils.h \ keys.cc \ keys.h \ keyactions.cc \ keyactions.h \ lists.h \ menulist.cc \ menulist.h \ monsters.cc \ monsters.h \ mouse.cc \ mouse.h \ npcnear.cc \ npcnear.h \ npctime.cc \ npctime.h \ palette.cc \ palette.h \ party.cc \ party.h \ paths.cc \ paths.h \ readnpcs.cc \ ready.h \ rect.h \ schedule.cc \ schedule.h \ segfile.cc \ segfile.h \ shapeid.cc \ shapeid.h \ sigame.cc \ sigame.h \ singles.h \ tiles.h \ tqueue.cc \ tqueue.h \ txtscroll.cc \ txtscroll.h \ vec.h \ version.cc \ version.h \ xdrag.cc \ xdrag.h EXULTLIBS = \ pathfinder/libpathfinder.la \ audio/libaudio.la \ audio/midi_drivers/libmididrv.la \ flic/libflic.la \ conf/libconf.la \ imagewin/libimagewin.la \ server/libserver.la \ usecode/libusecode.la \ shapes/libshapes.la \ objs/libobjs.la \ gumps/libgumps.la \ files/libu7file.la \ files/zip/libminizip.la exult_LDADD = \ $(EXULTLIBS) \ $(SDL_LIBS) $(KMID_LIBS) $(SYSLIBS) $(x_libraries) $(ICON_FILE) \ $(ZLIB_LIBS) $(OPENGL_LIBS) exult_DEPENDENCIES = $(ICON_FILE) $(EXULTLIBS) noinst_HEADERS = \ alpha_kludges.h EXTRA_DIST = \ autogen.sh \ README.1ST \ README \ FAQ \ README.win32 \ README.axp \ README.BeOS \ README.MacOS \ README.MacOSX \ README.AmigaOS \ README.MorphOS \ README.Qtopia \ Makefile.be \ Makefile.common \ Makefile.mingw \ Makefile.studio.mingw \ Makefile.MorphOS \ Info.plist.in \ exult.spec \ windrag.cc \ windrag.h \ win32/exult.ico \ win32/exultico.rc \ win32/exultstudio.ico \ win32/exultstudioico.rc \ beos/exult.rsrc \ mac/exult_icon.rsrc.bin \ mac/ExultMac.mcp.xml.sit \ mac/exult_version.rsrc.bin \ mac/mac_autoconfig.h \ mac/mac_prefix.h \ macosx/exult.icns \ msvcstuff/expack.vcproj \ msvcstuff/Exult.vcproj \ msvcstuff/Exult.sln \ msvcstuff/Exult_bg_flx.vcproj \ msvcstuff/Exult_flx.vcproj \ msvcstuff/Exult_si_flx.vcproj \ msvcstuff/mklink.vcproj \ msvcstuff/msvc_kludges.cc \ msvcstuff/msvc_kludges.h \ msvcstuff/rip.vcproj \ msvcstuff/shp2pcx.vcproj \ msvcstuff/splitshp.vcproj \ msvcstuff/ucdump.vcproj \ msvcstuff/unistd.h \ msvcstuff/wuc.vcproj \ msvcstuff/wud.vcproj \ msvcstuff/Zip.vcproj \ msvcstuff/exconfig/exconfig.cpp \ msvcstuff/exconfig/exconfig.def \ msvcstuff/exconfig/exconfig.vcproj \ msvcstuff/exconfig/exconfig.h \ msvcstuff/exconfig/exconfig.rc \ msvcstuff/exconfig/resource.h \ msvcstuff/exconfig/StdAfx.cpp \ msvcstuff/exconfig/StdAfx.h \ headers/common_types.h \ headers/exceptions.h \ headers/gamma.h \ server/servewin32.cc \ server/servewin32.h CLEANFILES = *~ @MACOSX_TRUE@bundle_name = Exult.app subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = exult.spec Info.plist bin_PROGRAMS = exult$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) am_exult_OBJECTS = actions.$(OBJEXT) actorio.$(OBJEXT) actors.$(OBJEXT) \ alloc.$(OBJEXT) args.$(OBJEXT) bggame.$(OBJEXT) \ browser.$(OBJEXT) cheat.$(OBJEXT) cheat_screen.$(OBJEXT) \ combat.$(OBJEXT) delobjs.$(OBJEXT) devgame.$(OBJEXT) \ dir.$(OBJEXT) drag.$(OBJEXT) effects.$(OBJEXT) exult.$(OBJEXT) \ exultmenu.$(OBJEXT) game.$(OBJEXT) gameclk.$(OBJEXT) \ gamedat.$(OBJEXT) gamemap.$(OBJEXT) gamerend.$(OBJEXT) \ gamewin.$(OBJEXT) keys.$(OBJEXT) keyactions.$(OBJEXT) \ menulist.$(OBJEXT) monsters.$(OBJEXT) mouse.$(OBJEXT) \ npcnear.$(OBJEXT) npctime.$(OBJEXT) palette.$(OBJEXT) \ party.$(OBJEXT) paths.$(OBJEXT) readnpcs.$(OBJEXT) \ schedule.$(OBJEXT) segfile.$(OBJEXT) shapeid.$(OBJEXT) \ sigame.$(OBJEXT) tqueue.$(OBJEXT) txtscroll.$(OBJEXT) \ version.$(OBJEXT) xdrag.$(OBJEXT) exult_OBJECTS = $(am_exult_OBJECTS) exult_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/actions.Po $(DEPDIR)/actorio.Po \ @AMDEP_TRUE@ $(DEPDIR)/actors.Po $(DEPDIR)/alloc.Po \ @AMDEP_TRUE@ $(DEPDIR)/args.Po $(DEPDIR)/bggame.Po \ @AMDEP_TRUE@ $(DEPDIR)/browser.Po $(DEPDIR)/cheat.Po \ @AMDEP_TRUE@ $(DEPDIR)/cheat_screen.Po $(DEPDIR)/combat.Po \ @AMDEP_TRUE@ $(DEPDIR)/delobjs.Po $(DEPDIR)/devgame.Po \ @AMDEP_TRUE@ $(DEPDIR)/dir.Po $(DEPDIR)/drag.Po \ @AMDEP_TRUE@ $(DEPDIR)/effects.Po $(DEPDIR)/exult.Po \ @AMDEP_TRUE@ $(DEPDIR)/exultmenu.Po $(DEPDIR)/game.Po \ @AMDEP_TRUE@ $(DEPDIR)/gameclk.Po $(DEPDIR)/gamedat.Po \ @AMDEP_TRUE@ $(DEPDIR)/gamemap.Po $(DEPDIR)/gamerend.Po \ @AMDEP_TRUE@ $(DEPDIR)/gamewin.Po $(DEPDIR)/keyactions.Po \ @AMDEP_TRUE@ $(DEPDIR)/keys.Po $(DEPDIR)/menulist.Po \ @AMDEP_TRUE@ $(DEPDIR)/monsters.Po $(DEPDIR)/mouse.Po \ @AMDEP_TRUE@ $(DEPDIR)/npcnear.Po $(DEPDIR)/npctime.Po \ @AMDEP_TRUE@ $(DEPDIR)/palette.Po $(DEPDIR)/party.Po \ @AMDEP_TRUE@ $(DEPDIR)/paths.Po $(DEPDIR)/readnpcs.Po \ @AMDEP_TRUE@ $(DEPDIR)/schedule.Po $(DEPDIR)/segfile.Po \ @AMDEP_TRUE@ $(DEPDIR)/shapeid.Po $(DEPDIR)/sigame.Po \ @AMDEP_TRUE@ $(DEPDIR)/tqueue.Po $(DEPDIR)/txtscroll.Po \ @AMDEP_TRUE@ $(DEPDIR)/version.Po $(DEPDIR)/xdrag.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(exult_SOURCES) HEADERS = $(noinst_HEADERS) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = README $(noinst_HEADERS) ./stamp-h.in AUTHORS COPYING \ ChangeLog INSTALL Info.plist.in Makefile.am Makefile.in NEWS \ aclocal.m4 config.guess config.h.in config.sub configure \ configure.ac depcomp exult.spec.in install-sh ltmain.sh missing \ mkinstalldirs DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(exult_SOURCES) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$@ $(SHELL) ./config.status $(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): configure.ac cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h @if test ! -f $@; then \ rm -f stamp-h; \ $(MAKE) stamp-h; \ else :; fi stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h stamp-hT @echo timestamp > stamp-hT 2> /dev/null cd $(top_builddir) \ && CONFIG_FILES= CONFIG_HEADERS=config.h \ $(SHELL) ./config.status @mv stamp-hT stamp-h $(srcdir)/config.h.in: $(srcdir)/./stamp-h.in @if test ! -f $@; then \ rm -f $(srcdir)/./stamp-h.in; \ $(MAKE) $(srcdir)/./stamp-h.in; \ else :; fi $(srcdir)/./stamp-h.in: $(top_srcdir)/configure.ac $(ACLOCAL_M4) @rm -f $(srcdir)/./stamp-h.in $(srcdir)/./stamp-h.inT @echo timestamp > $(srcdir)/./stamp-h.inT 2> /dev/null cd $(top_srcdir) && $(AUTOHEADER) @mv $(srcdir)/./stamp-h.inT $(srcdir)/./stamp-h.in distclean-hdr: -rm -f config.h exult.spec: $(top_builddir)/config.status exult.spec.in cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status Info.plist: $(top_builddir)/config.status Info.plist.in cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) exult$(EXEEXT): $(exult_OBJECTS) $(exult_DEPENDENCIES) @rm -f exult$(EXEEXT) $(CXXLINK) $(exult_LDFLAGS) $(exult_OBJECTS) $(exult_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/actions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/actorio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/actors.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/args.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bggame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/browser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/cheat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/cheat_screen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/combat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/delobjs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/devgame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/drag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/effects.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/exult.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/exultmenu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/game.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gameclk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gamedat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gamemap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gamerend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gamewin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/keyactions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/keys.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/menulist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/monsters.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mouse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/npcnear.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/npctime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/palette.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/party.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/paths.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/readnpcs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/schedule.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/segfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapeid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/sigame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/tqueue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/txtscroll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/xdrag.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = . # Avoid unsightly `./'. distdir = $(PACKAGE)-$(VERSION) GZIP_ENV = --best distdir: $(DISTFILES) -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) mkdir $(distdir) $(mkinstalldirs) $(distdir)/. $(distdir)/beos $(distdir)/headers $(distdir)/mac $(distdir)/macosx $(distdir)/msvcstuff $(distdir)/msvcstuff/exconfig $(distdir)/server $(distdir)/win32 @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/=build mkdir $(distdir)/=inst chmod a-w $(distdir) dc_install_base=`CDPATH=: && cd $(distdir)/=inst && pwd` \ && cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix=$$dc_install_base \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ || (echo "Error: files left after uninstall" 1>&2; \ exit 1) ) \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && $(MAKE) $(AM_MAKEFLAGS) distclean \ && rm -f $(distdir).tar.gz \ && (test `find . -type f -print | wc -l` -eq 0 \ || (echo "Error: files left after distclean" 1>&2; \ exit 1) ) -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) @echo "$(distdir).tar.gz is ready for distribution" | \ sed 'h;s/./=/g;p;x;p;x' check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(HEADERS) config.h installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(bindir) install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am dist-all: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) distclean: distclean-recursive -rm -f config.status config.cache config.log distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-binPROGRAMS install-exec-local install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool clean-recursive \ dist dist-all distcheck distclean distclean-compile \ distclean-depend distclean-generic distclean-hdr \ distclean-libtool distclean-recursive distclean-tags distdir \ dvi dvi-am dvi-recursive info info-am info-recursive install \ install-am install-binPROGRAMS install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-local install-exec-recursive install-info \ install-info-am install-info-recursive install-man \ install-recursive install-strip installcheck installcheck-am \ installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am \ uninstall-info-recursive uninstall-recursive win32/exultico.o: $(srcdir)/win32/exultico.rc $(srcdir)/win32/exult.ico -mkdir win32 cp $(srcdir)/win32/exult.ico win32 windres $(srcdir)/win32/exultico.rc win32/exultico.o @MACOSX_TRUE@Exult_app: ${EXE_TARGET} @MACOSX_TRUE@ mkdir -p $(bundle_name)/Contents/MacOS @MACOSX_TRUE@ mkdir -p $(bundle_name)/Contents/Resources @MACOSX_TRUE@ echo "APPL????" > $(bundle_name)/Contents/PkgInfo @MACOSX_TRUE@ $(INSTALL_DATA) Info.plist $(bundle_name)/Contents/ @MACOSX_TRUE@ $(INSTALL_PROGRAM) $< $(bundle_name)/Contents/MacOS/ @MACOSX_TRUE@ $(INSTALL_DATA) macosx/exult.icns $(bundle_name)/Contents/Resources/ @MACOSX_TRUE@install-exec-local: Exult_app @MACOSX_TRUE@ mkdir -p $(DESTDIR)/Applications/ @MACOSX_TRUE@ cp -r $(bundle_name) $(DESTDIR)/Applications/ @MACOSX_FALSE@install-exec-local: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/README.MacOS0000755000175000001440000000154207341767430010033 Exult instructions for MacOS ---------------------------- To play ------- First you need to get Ultima 7. Either you own it already, or you buy it somewhere. Then you must install it on a DOS/Windows machine in order to get the data file. A good way is to use a PC emulator for this, e.g. Virtual PC, Real PC or SoftWindows. From the Ultima7 folder on your PC, copy the STATIC sub folder to the folder that contains the ExultMac application. Now run ExultMac, and have fun! Notes ------ * Exult generates the files 'stdout.txt' and 'stderr.txt'. These may give you some idea of what is going on under the hood. When Exult suddenly quits, sometimes these files can help. * You can build exult from the source yourself if you want, provided you own a copy of CodeWarrior for MacOS. If you need help with that, feel free to contact me at exult-1.2/msvcstuff/0000777000175000001440000000000010062225324010272 5exult-1.2/msvcstuff/wud.vcproj0000644000175000001440000002063310017126522012236 exult-1.2/msvcstuff/Exult_si_flx.vcproj0000644000175000001440000000554010017126522014104 exult-1.2/msvcstuff/Exult.vcproj0000644000175000001440000012074610062225264012551 exult-1.2/msvcstuff/rip.vcproj0000644000175000001440000002044410017126522012231 exult-1.2/msvcstuff/unistd.h0000644000175000001440000000014007321075263011671 // unistd.h so Exult will compile under MSVC #ifndef UNISTD_H #define UNISTD_H #endif UNISTD_Hexult-1.2/msvcstuff/expack.vcproj0000644000175000001440000003004610017126522012711 exult-1.2/msvcstuff/msvc_kludges.h0000644000175000001440000002037310061526217013056 // // MSVC Kludges... and precompiled header for Exult // // DO NOT INCLUDE // // This files allows Exult, and it's tools, to compile under the very non // standards compilent MSVC. It also serves as a precompiled header to greatly // improve compile times in MSVC. // #ifndef MSVC_KLUDGES_H #define MSVC_KLUDGES_H #define HAVE_SSTREAM 1 // Firstly some things that need to be defined #define VERSION "1.2" #define EXULT_DATADIR "data/" #define SIZEOF_SHORT 2 #define SIZEOF_INT 4 #define SIZEOF_LONG 4 #define DONT_HAVE_HASH_SET #define DONT_HAVE_HASH_MAP //#define HAVE_OPENGL //#define FUDGE_SAMPLE_RATES #define USE_FMOPL_MIDI #ifndef WIN32 #error WTF! #endif // No GDI #define NOGDI // Settings for debug builds #ifndef NDEBUG #define USE_EXULTSTUDIO #define ENABLE_MIDISFX #define COLOURLESS_REALLY_HATES_THE_BG_SFX #define FORCE_44KHZ #ifndef DEBUG //#define DEBUG 1 #endif #endif // Yeah, lets do unicode compiles //#define UNICODE // Don't need everything in the windows headers #define WIN32_LEAN_AND_MEAN // Disable some warnings #pragma warning (disable: 4786) // Debug Len > 255 #pragma warning (disable: 4355) // 'this' : used in base member initializer list #ifndef ENABLE_EXTRA_WARNINGS //#pragma warning (disable: 4101) // unreferenced local variable //#pragma warning (disable: 4309) // truncation of constant value #pragma warning (disable: 4305) // truncation from 'const int' to 'char' #pragma warning (disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) #endif // // Hacks for MSVC 6 // #if (_MSC_VER == 1200) // Define size_t, but don't define tm, we'll define that later #define _TM_DEFINED #include #undef _TM_DEFINED #define _SIZE_T_DEFINED // we can't put cstdio into std because MSVC MUST have it in the global namespace #include // Now put the headers that should be in std into the std namespace namespace std { extern "C" { #include #include //#include #include #include #include #include #include #include #include #include #include }; // Kludge to make Exult think that size_t has been put into the // std namespace typedef ::size_t size_t2; #define size_t size_t2 // These are declared/defined in and the need to be in // the std namespace using ::FILE; using ::fread; using ::va_list; using ::fopen; using ::fclose; using ::fwrite; using ::remove; using ::printf; } // These get put in std when they otherwise should be, or are required by other headers using std::memcmp; using std::memset; using std::mbstate_t; using std::size_t; using std::time_t; using std::_fsize_t; using std::tm; using std::_dev_t; using std::_ino_t; using std::_off_t; using std::isspace; using std::_alloca; using std::wcslen; using std::strtol; // Nope, stat isn't defined #ifdef _STAT_DEFINED #undef _STAT_DEFINED #endif #include // // Hacks for MSVC 7 // #elif (_MSC_VER == 1300) #include #define HAVE_SYS_STAT_H #define inline __forceinline #else #error Unknown Version of MSVC being used. Edit "msvc_include.h" and add your version #endif // We've got snprintf #define HAVE_SNPRINTF #define snprintf _snprintf // When doing a DEBUG compile we will output to the console // However, SDL doesn't want us to do that #ifdef DEBUG //#define SDL_main main #endif // Some often used headers that could be included in out precompiled header #include #include #include #include #include #include #include #include #include #include #include #include #include #include using std::getline; // Why oh why! // MSVC thinks near and far are actually supposed to be used with pointers // but because they are no longer used, it consequently causes an error #undef near #define near ex_near #undef far #define far ex_far #undef FAR #define FAR #undef NEAR #define NEAR // We need this defined #define __STRING(x) #x #ifdef DEBUG #define STRICTUNZIP #define STRICTZIP #endif // Only include these headers if we are actually compiling Exult #ifdef EXULT #ifndef HAVE_ZIP_SUPPORT #define HAVE_ZIP_SUPPORT #endif #ifdef USING_PRECOMPILED_HEADER #include #include "../actions.h" #include "../actors.h" #include "../args.h" #include "../bggame.h" #include "../browser.h" #include "../cheat.h" #include "../cheat_screen.h" #include "../combat.h" #include "../delobjs.h" #include "../dir.h" #include "../effects.h" #include "../headers/exceptions.h" #include "../headers/common_types.h" #include "../exult.h" #include "../exult_constants.h" #include "../exult_types.h" #include "../exultmenu.h" #include "../fnames.h" #include "../frameseq.h" #include "../game.h" #include "../gameclk.h" #include "../gamewin.h" #include "../headers/gamma.h" #include "../hash_utils.h" #include "../keyactions.h" #include "../keys.h" #include "../lists.h" #include "../menulist.h" #include "../mouse.h" #include "../npcnear.h" #include "../npctime.h" #include "../palette.h" #include "../paths.h" #include "../ready.h" #include "../rect.h" #include "../schedule.h" #include "../segfile.h" #include "../shapeid.h" #include "../sigame.h" #include "../tiles.h" #include "../tqueue.h" #include "../txtscroll.h" #include "../vec.h" #include "../flic/playfli.h" #include "../pathfinder/Astar.h" #include "../pathfinder/PathFinder.h" #include "../pathfinder/Zombie.h" #include "../objs/animate.h" #include "../objs/barge.h" #include "../objs/chunks.h" #include "../objs/chunkter.h" #include "../objs/citerate.h" #include "../objs/contain.h" #include "../objs/egg.h" #include "../objs/flags.h" #include "../objs/iregobjs.h" #include "../objs/jawbone.h" #include "../objs/objiter.h" #include "../objs/objlist.h" #include "../objs/objs.h" #include "../objs/ordinfo.h" #include "../objs/spellbook.h" #include "../objs/virstone.h" #include "../conf/Configuration.h" #include "../conf/XMLEntity.h" #include "../usecode/conversation.h" #include "../usecode/keyring.h" #include "../usecode/ucinternal.h" #include "../usecode/ucmachine.h" #include "../usecode/ucsched.h" #include "../usecode/ucscriptop.h" #include "../usecode/useval.h" #include "../audio/Audio.h" #include "../audio/conv.h" #include "../audio/Midi.h" #include "../audio/soundtest.h" #include "../audio/xmidi.h" #include "../gumps/Actor_gump.h" #include "../gumps/AudioOptions_gump.h" #include "../gumps/Book_gump.h" #include "../gumps/CombatStats_gump.h" #include "../gumps/Face_button.h" #include "../gumps/Face_stats.h" #include "../gumps/File_gump.h" #include "../gumps/Gamemenu_gump.h" #include "../gumps/Gump.h" #include "../gumps/Gump_button.h" #include "../gumps/Gump_manager.h" #include "../gumps/Gump_ToggleButton.h" #include "../gumps/gump_types.h" #include "../gumps/gump_utils.h" #include "../gumps/Gump_widget.h" #include "../gumps/Jawbone_gump.h" #include "../gumps/misc_buttons.h" #include "../gumps/Modal_gump.h" #include "../gumps/Newfile_gump.h" #include "../gumps/Paperdoll_gump.h" #include "../gumps/Scroll_gump.h" #include "../gumps/Sign_gump.h" #include "../gumps/Slider_gump.h" #include "../gumps/Spellbook_gump.h" #include "../gumps/Stats_gump.h" #include "../gumps/Text_button.h" #include "../gumps/Text_gump.h" #include "../gumps/VideoOptions_gump.h" #include "../gumps/Yesno_gump.h" #include "../imagewin/ibuf8.h" #include "../imagewin/imagebuf.h" #include "../imagewin/imagewin.h" #include "../imagewin/iwin8.h" #include "../shapes/bodies.h" #include "../shapes/font.h" #include "../shapes/fontvga.h" #include "../shapes/items.h" #include "../shapes/monstinf.h" #include "../shapes/shapeinf.h" #include "../shapes/shapevga.h" #include "../shapes/u7drag.h" #include "../shapes/vgafile.h" #endif //USING_PRECOMPILED_HEADER //#include "../files/zip/zip_u7file.h" #endif // We will probably always want these #ifdef USING_PRECOMPILED_HEADER #include "../files/databuf.h" #include "../files/Flat.h" #include "../files/Flex.h" #include "../files/IFF.h" #include "../files/listfiles.h" #include "../files/Table.h" #include "../files/U7file.h" #include "../files/utils.h" #include "../files/crc.h" #endif //USING_PRECOMPILED_HEADER // Don't want SDL Parachute #define NO_SDL_PARACHUTE #define CHUNK_OBJ_DUMP #endif /* !MSVC_KLUDGES_H */ exult-1.2/msvcstuff/ucdump.vcproj0000644000175000001440000002051610017126522012734 exult-1.2/msvcstuff/wuc.vcproj0000644000175000001440000002074310017126522012237 exult-1.2/msvcstuff/shp2pcx.vcproj0000644000175000001440000002120710017126522013024 exult-1.2/msvcstuff/msvc_kludges.cc0000644000175000001440000000006007524010427013204 // Precompiled header #include "msvc_kludges.h" exult-1.2/msvcstuff/splitshp.vcproj0000644000175000001440000002125510017126522013306 exult-1.2/msvcstuff/Exult.sln0000644000175000001440000002721110017126522012030 Microsoft Visual Studio Solution File, Format Version 7.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exult", "Exult.vcproj", "{0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exult_bg_flx", "Exult_bg_flx.vcproj", "{0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exult_flx", "Exult_flx.vcproj", "{C8853EC2-3A90-4020-976E-D5FBE12B9265}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exult_si_flx", "Exult_si_flx.vcproj", "{39A7A7D1-834B-4A01-B321-3D14A359BC88}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Zip.vcproj", "{3BA72F61-852F-47A5-8E50-2B433FE77638}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exconfig", "exconfig\exconfig.vcproj", "{852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expack", "expack.vcproj", "{C9D55119-2372-43A8-A3B2-1BFB6997AE4D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mklink", "mklink.vcproj", "{5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rip", "rip.vcproj", "{2B89F9A9-3794-4665-9723-5D18868A36AD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shp2pcx", "shp2pcx.vcproj", "{33C9A31A-78A6-48DF-A948-8054B65EC121}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splitshp", "splitshp.vcproj", "{44FA98BB-5816-43F8-BFCD-3B6270D64BE2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ucdump", "ucdump.vcproj", "{328A75CE-F668-42C8-A68C-037ED7682990}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wuc", "wuc.vcproj", "{85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wud", "wud.vcproj", "{499B31BD-2481-4E51-BBDC-418479F34642}" EndProject Global GlobalSection(SolutionConfiguration) = preSolution ConfigName.0 = Debug ConfigName.1 = Debug Install ConfigName.2 = Release ConfigName.3 = Release Install EndGlobalSection GlobalSection(ProjectDependencies) = postSolution {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.0 = {3BA72F61-852F-47A5-8E50-2B433FE77638} {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.1 = {39A7A7D1-834B-4A01-B321-3D14A359BC88} {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.2 = {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB} {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.3 = {C8853EC2-3A90-4020-976E-D5FBE12B9265} {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.0 = {C9D55119-2372-43A8-A3B2-1BFB6997AE4D} {C8853EC2-3A90-4020-976E-D5FBE12B9265}.0 = {C9D55119-2372-43A8-A3B2-1BFB6997AE4D} {39A7A7D1-834B-4A01-B321-3D14A359BC88}.0 = {C9D55119-2372-43A8-A3B2-1BFB6997AE4D} EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Debug.ActiveCfg = Debug|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Debug.Build.0 = Debug|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Debug Install.ActiveCfg = Debug Install|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Debug Install.Build.0 = Debug Install|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Release.ActiveCfg = Release|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Release.Build.0 = Release|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Release Install.ActiveCfg = Release Install|Win32 {0451A879-8AB7-4AD0-A559-CC3EC4DA9A50}.Release Install.Build.0 = Release Install|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Debug.ActiveCfg = Debug|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Debug.Build.0 = Debug|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Debug Install.ActiveCfg = Debug Install|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Debug Install.Build.0 = Debug Install|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Release.ActiveCfg = Release|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Release.Build.0 = Release|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Release Install.ActiveCfg = Release Install|Win32 {0E58490B-9F02-4FB6-8D39-18C9DAD87CCB}.Release Install.Build.0 = Release Install|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Debug.ActiveCfg = Debug|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Debug.Build.0 = Debug|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Debug Install.ActiveCfg = Debug Install|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Debug Install.Build.0 = Debug Install|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Release.ActiveCfg = Release|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Release.Build.0 = Release|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Release Install.ActiveCfg = Release Install|Win32 {C8853EC2-3A90-4020-976E-D5FBE12B9265}.Release Install.Build.0 = Release Install|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Debug.ActiveCfg = Debug|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Debug.Build.0 = Debug|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Debug Install.ActiveCfg = Debug Install|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Debug Install.Build.0 = Debug Install|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Release.ActiveCfg = Release|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Release.Build.0 = Release|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Release Install.ActiveCfg = Release Install|Win32 {39A7A7D1-834B-4A01-B321-3D14A359BC88}.Release Install.Build.0 = Release Install|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Debug.ActiveCfg = Debug|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Debug.Build.0 = Debug|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Debug Install.ActiveCfg = Debug Install|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Debug Install.Build.0 = Debug Install|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Release.ActiveCfg = Release|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Release.Build.0 = Release|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Release Install.ActiveCfg = Release Install|Win32 {3BA72F61-852F-47A5-8E50-2B433FE77638}.Release Install.Build.0 = Release Install|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Debug.ActiveCfg = Release|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Debug.Build.0 = Release|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Debug Install.ActiveCfg = Debug|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Debug Install.Build.0 = Debug|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Release.ActiveCfg = Release|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Release.Build.0 = Release|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Release Install.ActiveCfg = Release|Win32 {852E48BB-7F79-47B5-A0F6-7CDA87A8AFAD}.Release Install.Build.0 = Release|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Debug.ActiveCfg = Debug|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Debug.Build.0 = Debug|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Debug Install.ActiveCfg = Debug Install|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Debug Install.Build.0 = Debug Install|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Release.ActiveCfg = Release|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Release.Build.0 = Release|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Release Install.ActiveCfg = Release Install|Win32 {C9D55119-2372-43A8-A3B2-1BFB6997AE4D}.Release Install.Build.0 = Release Install|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Debug.ActiveCfg = Debug|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Debug.Build.0 = Debug|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Debug Install.ActiveCfg = Debug Install|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Debug Install.Build.0 = Debug Install|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Release.ActiveCfg = Release|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Release.Build.0 = Release|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Release Install.ActiveCfg = Release Install|Win32 {5B194FF1-6CD9-4111-B2A9-BD00EBA77A1E}.Release Install.Build.0 = Release Install|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Debug.ActiveCfg = Debug|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Debug.Build.0 = Debug|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Debug Install.ActiveCfg = Debug Install|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Debug Install.Build.0 = Debug Install|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Release.ActiveCfg = Release|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Release.Build.0 = Release|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Release Install.ActiveCfg = Release Install|Win32 {2B89F9A9-3794-4665-9723-5D18868A36AD}.Release Install.Build.0 = Release Install|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Debug.ActiveCfg = Debug|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Debug.Build.0 = Debug|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Debug Install.ActiveCfg = Debug Install|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Debug Install.Build.0 = Debug Install|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Release.ActiveCfg = Release|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Release.Build.0 = Release|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Release Install.ActiveCfg = Release Install|Win32 {33C9A31A-78A6-48DF-A948-8054B65EC121}.Release Install.Build.0 = Release Install|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Debug.ActiveCfg = Debug|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Debug.Build.0 = Debug|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Debug Install.ActiveCfg = Debug Install|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Debug Install.Build.0 = Debug Install|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Release.ActiveCfg = Release|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Release.Build.0 = Release|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Release Install.ActiveCfg = Release Install|Win32 {44FA98BB-5816-43F8-BFCD-3B6270D64BE2}.Release Install.Build.0 = Release Install|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Debug.ActiveCfg = Debug|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Debug.Build.0 = Debug|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Debug Install.ActiveCfg = Debug Install|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Debug Install.Build.0 = Debug Install|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Release.ActiveCfg = Release|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Release.Build.0 = Release|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Release Install.ActiveCfg = Release Install|Win32 {328A75CE-F668-42C8-A68C-037ED7682990}.Release Install.Build.0 = Release Install|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Debug.ActiveCfg = Debug|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Debug.Build.0 = Debug|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Debug Install.ActiveCfg = Debug Install|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Debug Install.Build.0 = Debug Install|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Release.ActiveCfg = Release|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Release.Build.0 = Release|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Release Install.ActiveCfg = Release Install|Win32 {85D7D98F-E12B-4AF9-9DFA-31D5F5D51ADE}.Release Install.Build.0 = Release Install|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Debug.ActiveCfg = Debug|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Debug.Build.0 = Debug|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Debug Install.ActiveCfg = Debug Install|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Debug Install.Build.0 = Debug Install|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Release.ActiveCfg = Release|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Release.Build.0 = Release|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Release Install.ActiveCfg = Release Install|Win32 {499B31BD-2481-4E51-BBDC-418479F34642}.Release Install.Build.0 = Release Install|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal exult-1.2/msvcstuff/mklink.vcproj0000644000175000001440000002051610017126522012724 exult-1.2/msvcstuff/Exult_bg_flx.vcproj0000644000175000001440000001064010017126522014056 exult-1.2/msvcstuff/Exult_flx.vcproj0000644000175000001440000001165010017126522013410 exult-1.2/msvcstuff/exconfig/0000777000175000001440000000000010062225324012074 5exult-1.2/msvcstuff/exconfig/exconfig.def0000644000175000001440000000005107352676401014304 EXPORTS GetPaths WriteConfig LaunchAppexult-1.2/msvcstuff/exconfig/exconfig.cpp0000644000175000001440000002057207724430452014337 /* * Copyright (C) 2000-2002 Ryan Nunn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * What is this? * * EXCONFIG is a dll that is used by the InstallShield Wizard to get and set the * Black Gate and Serpent Isle paths. * */ #include "stdafx.h" #include "exconfig.h" #include "Configuration.h" #include #define MAX_STRLEN 512 #ifdef _DEBUF #define MessageBoxDebug(a,b,c,d) MessageBox(a,b,c,d); #else #define MessageBoxDebug(a,b,c,d) #endif const std::string c_empty_string; char *config_defaults[] = { "config/disk/game/blackgate/keys", "(default)", "config/disk/game/blackgate/waves", "jmsfx.flx", "config/disk/game/serpentisle/keys", "(default)", "config/disk/game/serpentisle/waves", "jmsisfx.flx", "config/audio/enabled", "yes", "config/audio/effects/enabled", "yes", "config/audio/effects/convert", "gs", "config/audio/midi/enabled", "yes", "config/audio/midi/convert", "gm", "config/audio/midi/reverb/enabled", "no", "config/audio/midi/reverb/level", "0", "config/audio/midi/chorus/enabled", "no", "config/audio/midi/chorus/level", "0", "config/audio/midi/volume_curve", "1.000000", "config/audio/speech/enabled", "yes", "config/gameplay/cheat", "yes", "config/gameplay/skip_intro", "no", "config/gameplay/skip_splash", "no", "config/video/width", "320", "config/video/height", "200", "config/video/scale", "2", "config/video/scale_method", "2xSaI", "config/video/fullscreen", "no", "config/video/disable_fades", "no", "config/video/gamma/red", "1.00", "config/video/gamma/green", "1.00", "config/video/gamma/blue", "1.00", 0 }; class Path { struct Directory { char name[256]; Directory *next; Directory() : next(0) { name[0] = 0; } }; bool network;// Networked? char drive; // Drive letter (if set) Directory *dirs; // Directories void RemoveAll(); int Addit(const char* p); public: Path() : network(false), drive(0), dirs(0) { } Path(const char* p) : network(false), drive(0), dirs(0) { AddString(p); } ~Path(); void RemoveLast() { Addit(".."); } void AddString(const char* p); void GetString(char p[MAX_STRLEN]); }; // Destructor Path::~Path() { RemoveAll(); network = false; drive = 0; } void Path::RemoveAll() { Directory *d = dirs; while (d) { Directory *next = d->next; delete d; d = next; } dirs = 0; } int Path::Addit(const char* p) { Directory *d = dirs; Directory *prev = 0; Directory *prevprev = 0; // Check for . and .. // Create new if (!d) { dirs = d = new Directory; } else { while (d->next) { prevprev = d; d = d->next; } d->next = new Directory; prev = d; d = d->next; } for (int i = 0; p[i] != 0 && p[i] != '\\' && p[i] != '/'; i++) d->name[i] = p[i]; d->name[i] = 0; // Skip all 'slashes' while (p[i] && (p[i] == '\\' || p[i] == '/')) i++; // Check for . and .. if (!std::strcmp(d->name, ".")) { delete d; prev->next = 0; } else if (!std::strcmp(d->name, "..")) { delete d; delete prev; prevprev->next = 0; } return i; } // Add path void Path::AddString(const char *p) { int len = std::strlen (p); // Root dir of this drive if (*p == '\\' || *p == '/') { // Remove all the entires RemoveAll(); p++; // Could be network drive if (*p == '\\') { network = true; p++; } } else if (p[0] && p[1] == ':') // Drive { RemoveAll(); drive = *p; network = false; p+= 2; } // Skip all slashes while (*p && (*p == '\\' || *p == '/')) p++; while (*p) { p+= Addit(p); } } void Path::GetString(char p[MAX_STRLEN]) { p[0] = 0; if (network) std::strncat(p, "\\\\", MAX_STRLEN); else if (drive) _snprintf (p, MAX_STRLEN, "%c:\\", drive); else std::strncat(p, "\\", MAX_STRLEN); Directory *d = dirs; while (d) { std::strncat (p, d->name, MAX_STRLEN); d = d->next; if (d) std::strncat(p, "\\", MAX_STRLEN); } } // The exports #ifdef __cplusplus extern "C" { #endif EXCONFIG_API LONG APIENTRY GetPaths(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { Path path(lpszValue); char p[MAX_STRLEN]; path.AddString("exult.cfg"); path.GetString(p); char *si_pathdef = ""; char *bg_pathdef = ""; MessageBoxDebug (hwnd, lpszValue, p, MB_OK); try { //chdir (lpszValue); Configuration config; config.read_config_file(p); std::string data_directory; config.value("config/disk/game/serpentisle/path",data_directory,si_pathdef); if (data_directory != si_pathdef) { path.~Path(); path.AddString(lpszValue); path.AddString(data_directory.c_str()); path.GetString(p); } else { std::strncpy (p, si_pathdef, MAX_STRLEN); } config.value("config/disk/game/blackgate/path",data_directory,bg_pathdef); if (data_directory != bg_pathdef) { path.~Path(); path.AddString(lpszValue); path.AddString(data_directory.c_str()); path.GetString(lpszValue); } else { std::strncpy (lpszValue, bg_pathdef, MAX_STRLEN); } std::strncat(lpszValue, "\n", MAX_STRLEN); std::strncat(lpszValue, p, MAX_STRLEN); MessageBoxDebug (hwnd, lpszValue, data_directory.c_str(), MB_OK); } catch(...) { std::strncpy(lpszValue, bg_pathdef, MAX_STRLEN); std::strncat(lpszValue, "\n", MAX_STRLEN); std::strncat(lpszValue, si_pathdef, MAX_STRLEN); } return 0; } EXCONFIG_API LONG APIENTRY WriteConfig(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { MessageBoxDebug (hwnd, lpszValue, "WriteConfig", MB_OK); int len = std::strlen (lpszValue); char *p = new char [len+1]; int i, j, bgstart, sistart; for (i = 0; i < len && lpszValue[i] != '\n'; i++) p[i] = lpszValue[i]; p[i] = 0; bgstart = i+1; Path path(p); path.AddString("exult.cfg"); path.GetString(p); MessageBoxDebug (hwnd, p, "WriteConfig: p", MB_OK); try { //chdir (lpszValue); Configuration config; config.read_config_file(p); for (j = 0, i = bgstart; i < len && lpszValue[i] != '\n'; j++, i++) p[j] = lpszValue[i]; p[j] = 0; sistart = i+1; if (j > 1 && p[j-1] == '\\') p[j-1] = 0; MessageBoxDebug (hwnd, p, "WriteConfig: BG", MB_OK); config.set("config/disk/game/blackgate/path", p, true); for (j = 0, i = sistart ; i < len && lpszValue[i]; j++, i++) p[j] = lpszValue[i]; p[j] = 0; if (j > 1 && p[j-1] == '\\') p[j-1] = 0; MessageBoxDebug (hwnd, p, "WriteConfig: SI", MB_OK); config.set("config/disk/game/serpentisle/path", p, true); std::string s; for (i = 0; config_defaults[i]; i+=2) { config.value(config_defaults[i], s, ""); if (s.empty()) config.set(config_defaults[i], config_defaults[i+1], true); } // Fix broken SI SFX stuff config.value("config/disk/game/serpentisle/waves", s, ""); const char *si_sfx = s.c_str(); int slen = std::strlen(si_sfx); slen -= std::strlen ("jmsfxsi.flx"); if (slen >= 0 && !std::strcmp(si_sfx+slen, "jmsfxsi.flx")) { char *fixed = new char[slen+1]; std::strncpy (fixed, si_sfx, slen); fixed[slen] = 0; s = fixed; s += "jmsisfx.flx"; config.set("config/disk/game/serpentisle/waves", s, true); } config.write_back(); } catch(...) { } delete [] p; return 0; } EXCONFIG_API LONG APIENTRY LaunchApp(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { Path path(lpszValue); char p[MAX_STRLEN]; PROCESS_INFORMATION pi; STARTUPINFO si; path.RemoveLast(); path.GetString(p); std::memset (&si, 0, sizeof(si)); si.cb = sizeof(si); MessageBoxDebug(hwnd, lpszValue, "LaunchApp", MB_OK); CreateProcess (NULL, lpszValue, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, *lpIValue==1?p:NULL, &si, &pi); return 0; } #ifdef __cplusplus } #endif BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } exult-1.2/msvcstuff/exconfig/resource.h0000644000175000001440000000061507352677300014027 //{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by exconfig.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif exult-1.2/msvcstuff/exconfig/exconfig.rc0000644000175000001440000000466110062225264014152 //Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (Australia) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS #pragma code_page(1252) #endif //_WIN32 #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,2 PRODUCTVERSION 1,2,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "0c0904b0" BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "\0" VALUE "FileDescription", "Exult Config Helper DLL for InstallShield\0" VALUE "FileVersion", "1, 0, 0, 2\0" VALUE "InternalName", "exconfig\0" VALUE "LegalCopyright", "Copyright 2004\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "exconfig.dll\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Exult\0" VALUE "ProductVersion", "1.2\0" VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0xc09, 1200 END END #endif // !_MAC #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (Australia) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED exult-1.2/msvcstuff/exconfig/StdAfx.h0000644000175000001440000000147307352676401013375 // stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__07A411AF_2AA7_43BB_AF36_B5999C1DEE6B__INCLUDED_) #define AFX_STDAFX_H__07A411AF_2AA7_43BB_AF36_B5999C1DEE6B__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // This MUST BE FIRST! #include "msvc_kludges.h" // Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__07A411AF_2AA7_43BB_AF36_B5999C1DEE6B__INCLUDED_) exult-1.2/msvcstuff/exconfig/exconfig.vcproj0000644000175000001440000001444410017126522015046 exult-1.2/msvcstuff/exconfig/StdAfx.cpp0000644000175000001440000000043707352676401013727 // stdafx.cpp : source file that includes just the standard includes // exconfig.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file exult-1.2/msvcstuff/exconfig/exconfig.h0000644000175000001440000000146407352676401014006 // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the EXCONFIG_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // EXCONFIG_API functions as being imported from a DLL, wheras this DLL sees symbols // defined with this macro as being exported. #ifdef EXCONFIG_EXPORTS #define EXCONFIG_API __declspec(dllexport) #else #define EXCONFIG_API __declspec(dllimport) #endif // Insert your headers here #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #endif #include extern const std::string c_empty_string;exult-1.2/msvcstuff/Zip.vcproj0000644000175000001440000001571210017126522012203 exult-1.2/exult.spec.in0000644000175000001440000001025310026506273010616 # # Note that this is NOT a relocatable package # %define ver @VERSION@ %define rel 1 %define name @PACKAGE@ Summary: Ultima VII Engine Name: %name Version: %ver Release: %rel Copyright: GPL Group: Amusements/Games Source: http://download.sourceforge.net/projects/exult/exult-%{ver}.tar.gz BuildRoot: %{_tmppath}/%{name}-root Packager: Willem Jan Palenstijn URL: http://exult.sourceforge.net Prereq: /sbin/install-info %description Exult: an implementation of the Ultima VII engine for modern Operating Systems. %package tools Summary: Tools and utilities for playing with Exult/Ultima VII data files Group: Amusements/Games %description tools Exult Tools: a set of utilities for playing with Exult/Ultima VII data files. Included in the tools are: expack (archiver), ucxt (decompiler), ucc (compiler), splitshp (frame splitter), shp2pcx (shape converter), ipack (image archiver), textpack (text archiver) %package studio Summary: An editor for the Exult engine. Group: Amusements/Games %description studio Exult Studio: an editor for the Exult engine. # Also included is a plugin for the Gimp for the .shp image format. # (not yet...) %changelog * Tue Jul 22 2003 Willem Jan Palensitjn - updated for 1.1Beta1 - added a 'studio' package * Wed Nov 06 2002 Willem Jan Palensitjn - added tools manpages * Fri Nov 01 2002 Willem Jan Palenstijn - updated .spec to work with RH80 - removed studio and gimp plugin packages for 1.0 branch * Fri Jun 07 2002 Willem Jan Palenstijn - updated ucxt data files * Wed Dec 05 2001 Tristan Tarrant - subpackages are here !!! * Thu Nov 29 2001 Tristan Tarrant - allow setting of bindir and datadir - build exult only (will be fixed with the addition of subpackages) - added README.1ST - optimizer flags should be set for CXXFLAGS too * Mon Jun 25 2001 Willem Jan Palenstijn - added exult_bg.flx, exult_si.flx - removed explicit SDL req. (proper SDL version is added automatically) * Tue Nov 7 2000 Tristan Tarrant - A few fixes * Sat Sep 9 2000 Tristan Tarrant - Install exult.flx in the right place * Tue Jul 11 2000 Tristan Tarrant - Created the .spec file * Fri Feb 9 2000 Tristan Tarrant - Disable GIMP plugin by default. - Include FAQ %prep %setup %build # Needed for snapshot releases. if [ ! -f configure ]; then ./autogen.sh fi %configure --disable-gimp-plugin --enable-exult-studio --enable-exult-studio-support if [ "$SMP" != "" ]; then (make "MAKE=make -k -j $SMP"; exit 0) make else make fi %install rm -rf $RPM_BUILD_ROOT %makeinstall %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc AUTHORS COPYING ChangeLog NEWS README FAQ README.1ST %{_bindir}/exult %{_datadir}/exult/exultmsg.txt %{_datadir}/exult/exult_bg.flx %{_datadir}/exult/exult_si.flx %{_datadir}/exult/exult.flx %{_datadir}/exult/midisfx.flx %{_datadir}/icons/exult.png %{_mandir}/man6/exult.6.gz %{_datadir}/applications/exult.desktop %files tools %defattr(-, root, root) %doc tools/expack.txt %{_mandir}/man1/expack.1.gz %{_mandir}/man1/ipack.1.gz %{_mandir}/man1/shp2pcx.1.gz %{_mandir}/man1/splitshp.1.gz %{_mandir}/man1/textpack.1.gz %{_bindir}/expack %{_bindir}/ipack %{_bindir}/textpack %{_bindir}/ucxt %{_bindir}/ucc %{_bindir}/splitshp %{_bindir}/shp2pcx %{_datadir}/exult/u7bgintrinsics.data %{_datadir}/exult/u7siintrinsics.data %{_datadir}/exult/u7misc.data %{_datadir}/exult/u7opcodes.data %files studio %defattr(-, root, root) %{_bindir}/exult_studio %{_datadir}/exult/exult_studio.glade %{_datadir}/exult/estudio/new/combos.flx %{_datadir}/exult/estudio/new/faces.vga %{_datadir}/exult/estudio/new/gumps.vga %{_datadir}/exult/estudio/new/palettes.flx %{_datadir}/exult/estudio/new/shapes.vga %{_datadir}/exult/estudio/new/sprites.vga %{_datadir}/exult/estudio/new/text.flx %{_datadir}/exult/estudio/new/fonts.vga %{_datadir}/exult/estudio/new/pointers.shp exult-1.2/keys.h0000644000175000001440000000373007724430450007326 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KEYS_H #define KEYS_H #include "SDL_events.h" #include "game.h" #include #include #include const int c_maxparams = 4; struct Action; struct ActionType { const Action* action; int params[c_maxparams]; }; struct ltSDLkeysym { bool operator()(SDL_keysym k1, SDL_keysym k2) const { if (k1.sym == k2.sym) return k1.mod < k2.mod; else return k1.sym < k2.sym; } }; typedef std::map KeyMap; class KeyBinder { private: KeyMap bindings; std::vector keyhelp; std::vector cheathelp; public: KeyBinder(); ~KeyBinder(); /* Add keybinding */ void AddKeyBinding(SDLKey sym, int mod, const Action* action, int nparams, int* params); /* Delete keybinding */ void DelKeyBinding(SDLKey sym, int mod); /* Other methods */ void Flush() { bindings.clear(); keyhelp.clear(); cheathelp.clear(); } bool DoAction(ActionType action, bool press); bool HandleEvent(SDL_Event &ev); void LoadFromFile(const char* filename); void LoadDefaults(); void ShowHelp(); void ShowCheatHelp(); private: void ParseText(char *text, int len); void ParseLine(char *line); void FillParseMaps(); }; #endif /* KEYS_H */ exult-1.2/mouse.cc0000644000175000001440000002241310026506273007634 /* * mouse.cc - Mouse pointers. * * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_mouse.h" #include "SDL_timer.h" #include "mouse.h" #include "gamewin.h" #include "fnames.h" #include "Gump.h" #include "Gump_manager.h" #include "barge.h" #include "actors.h" #include "cheat.h" #include "combat_opts.h" #include "combat.h" #include "schedule.h" /* To get Schedule::combat */ #ifndef _MSC_VER using std::max; #endif short Mouse::short_arrows[8] = {8, 9, 10, 11, 12, 13, 14, 15}; short Mouse::med_arrows[8] = {16, 17, 18, 19, 20, 21, 22, 23}; short Mouse::long_arrows[8] = {24, 25, 26, 27, 28, 29, 30, 31}; short Mouse::short_combat_arrows[8] = {32, 33, 34, 35, 36, 37, 38, 39}; short Mouse::med_combat_arrows[8] = {40, 41, 42, 43, 44, 45, 46, 47}; Mouse* Mouse::mouse = 0; bool Mouse::mouse_update = false; /* * Create. */ Mouse::Mouse ( Game_window *gw // Where to draw. ) : gwin(gw), iwin(gwin->get_win()),backup(0),box(0,0,0,0),dirty(0,0,0,0), cur_framenum(0),cur(0),avatar_speed(100*gwin->get_std_delay()/slow_speed_factor) { SDL_GetMouseState(&mousex, &mousey); mousex /= gwin->get_fastmouse() ? 1 : iwin->get_scale(); mousey /= gwin->get_fastmouse() ? 1 : iwin->get_scale(); if (is_system_path_defined("") && U7exists(PATCH_POINTERS)) pointers.load(PATCH_POINTERS); else pointers.load(POINTERS); Init(); set_shape(get_short_arrow(east)); // +++++For now. } Mouse::Mouse ( Game_window *gw, // Where to draw. DataSource &shapes ) : gwin(gw), iwin(gwin->get_win()),backup(0),box(0,0,0,0),dirty(0,0,0,0),cur_framenum(0),cur(0),avatar_speed(100*gwin->get_std_delay()/slow_speed_factor) { SDL_GetMouseState(&mousex, &mousey); mousex /= gwin->get_fastmouse() ? 1 : iwin->get_scale(); mousey /= gwin->get_fastmouse() ? 1 : iwin->get_scale(); pointers.load(&shapes); Init(); set_shape0(0); } void Mouse::Init() { int cnt = pointers.get_num_frames(); int maxleft = 0, maxright = 0, maxabove = 0, maxbelow = 0; for (int i = 0; i < cnt; i++) { Shape_frame *frame = pointers.get_frame(i); int xleft = frame->get_xleft(), xright = frame->get_xright(); int yabove = frame->get_yabove(), ybelow = frame->get_ybelow(); if (xleft > maxleft) maxleft = xleft; if (xright > maxright) maxright = xright; if (yabove > maxabove) maxabove = yabove; if (ybelow > maxbelow) maxbelow = ybelow; } int maxw = maxleft + maxright, maxh = maxabove + maxbelow; // Create backup buffer. backup = iwin->create_buffer(maxw, maxh); box.w = maxw; box.h = maxh; onscreen = 0; // initially offscreen } /* * Delete. */ Mouse::~Mouse ( ) { delete backup; } /* * Show the mouse. */ void Mouse::show ( ) { if (!onscreen) { onscreen = 1; // Save background. iwin->get(backup, box.x, box.y); // Paint new location. // cur->paint_rle(iwin->get_ib8(), mousex, mousey); cur->paint_rle(mousex, mousey); } } /* * Move cursor */ void Mouse::move(int x, int y) { bool warp = false; if (x >= gwin->get_width()) { x = gwin->get_width() - 1; warp = true; } if (y >= gwin->get_height()) { y = gwin->get_height() - 1; warp = true; } if (warp) SDL_WarpMouse(x, y); #ifdef DEBUG if (onscreen) std::cerr << "Trying to move mouse while onscreen!" << std::endl; #endif // Shift to new position. box.shift(x - mousex, y - mousey); dirty = dirty.add(box); // Enlarge dirty area. mousex = x; mousey = y; } /* * Set to new shape. Should be called after checking that frame # * actually changed. */ void Mouse::set_shape0 ( int framenum ) { cur_framenum = framenum; cur = pointers.get_frame(framenum); while (!cur) // For newly-created games. cur = pointers.get_frame(--framenum); // Set backup box to cover mouse. box.x = mousex - cur->get_xleft(); box.y = mousey - cur->get_yabove(); dirty = dirty.add(box); // Update dirty area. } /* * Set to an arbitrary location. */ void Mouse::set_location ( int x, int y // Mouse position. ) { mousex = x; mousey = y; box.x = mousex - cur->get_xleft(); box.y = mousey - cur->get_yabove(); } /* * Flash a desired shape for about 1/2 second. */ void Mouse::flash_shape ( Mouse_shapes flash ) { Mouse_shapes saveshape = get_shape(); hide(); set_shape(flash); show(); gwin->show(1); SDL_Delay(600); hide(); gwin->paint(); set_shape(saveshape); gwin->set_painted(); } /* * Set default cursor */ void Mouse::set_speed_cursor() { Game_window *gwin = Game_window::get_instance(); Gump_manager *gump_man = gwin->get_gump_man(); int cursor = dontchange; int ax, ay; // Get Avatar/barge screen location. // Check if we are in dont_move mode, in this case display the hand cursor if (gwin->main_actor_dont_move()) cursor = hand; /* Can again, optionally move in gump mode. */ else if (gump_man->gump_mode()) { if (gump_man->gumps_dont_pause_game()) { Gump *gump = gump_man->find_gump(mousex, mousey); if (gump && !gump->no_handcursor()) cursor = hand; } else cursor = hand; } else if (gwin->get_dragging_gump()) cursor = hand; else if (cheat.in_map_editor()) { switch (cheat.get_edit_mode()) { case Cheat::move: cursor = hand; break; case Cheat::paint: cursor = short_combat_arrows[4]; break; // Short S red arrow. case Cheat::paint_chunks: cursor = med_combat_arrows[0]; break; // Med. N red arrow. #if 0 case Cheat::select: cursor = short_arrows[7]; break; // Short NW green. case Cheat::hide: cursor = redx; break; #endif case Cheat::combo_pick: cursor = greenselect; break; } } else if (Combat::is_paused()) cursor = short_combat_arrows[0]; // Short N red arrow. if (cursor == dontchange) { Barge_object *barge = gwin->get_moving_barge(); if (barge) { // Use center of barge. gwin->get_shape_location(barge, ax, ay); ax -= barge->get_xtiles()*(c_tilesize/2); ay -= barge->get_ytiles()*(c_tilesize/2); } else gwin->get_shape_location(gwin->get_main_actor(), ax, ay); int dy = ay - mousey, dx = mousex - ax; Direction dir = Get_direction(dy, dx); Rectangle gamewin_dims = gwin->get_win_rect(); float speed_section = max( max( -static_cast(dx)/ax, static_cast(dx)/(gamewin_dims.w-ax)), max(static_cast(dy)/ay, -static_cast(dy)/(gamewin_dims.h-ay)) ); /* If there is a hostile NPC nearby, the avatar isn't allowed to * move very fast * Note that the range at which this occurs in the original is * less than the "potential target" range- that is, if I go into * combat mode, even when I'm allowed to run at full speed, * I'll sometime charge off to kill someone "too far away" * to affect a speed limit. * I don't know whether this is taken into account by * get_nearby_npcs, but on the other hand, its a negligible point. */ Actor_queue nearby; if (!cheat.in_god_mode()) gwin->get_nearby_npcs( nearby ); bool nearby_hostile = false; for( Actor_queue::const_iterator it = nearby.begin(); it != nearby.end(); ++it ) { Actor *actor = *it; if( !actor->is_dead() && actor->get_schedule() && actor->get_alignment() >= Npc_actor::hostile && actor->get_schedule_type() == Schedule::combat && static_cast(actor->get_schedule())-> has_started_battle()) { /* TODO- I think invisibles still trigger the * slowdown, verify this. */ nearby_hostile = true; break; /* No need to bother checking the rest :P */ } } if( speed_section < 0.4 ) { if( gwin->in_combat() ) cursor = get_short_combat_arrow( dir ); else cursor = get_short_arrow( dir ); avatar_speed = 100*gwin->get_std_delay()/slow_speed_factor; } else if( speed_section < 0.8 || gwin->in_combat() || nearby_hostile ) { if( gwin->in_combat() ) cursor = get_medium_combat_arrow( dir ); else cursor = get_medium_arrow( dir ); if( gwin->in_combat() || nearby_hostile ) avatar_speed = 100*gwin->get_std_delay()/medium_combat_speed_factor; else avatar_speed = 100*gwin->get_std_delay()/medium_speed_factor; } else /* Fast - NB, we can't get here in combat mode; there is no * long combat arrow, nor is there a fast combat speed. */ { cursor = get_long_arrow( dir ); avatar_speed = 100*gwin->get_std_delay()/fast_speed_factor; } } if (cursor != dontchange) set_shape(cursor); } exult-1.2/xdrag.cc0000644000175000001440000002042410054030532007600 /* * Xdrag.cc - Drag-and-drop under X. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #if defined(USE_EXULTSTUDIO) && !defined(WIN32) #include /* Debugging messages */ #include #include #include #include "xdrag.h" #include "u7drag.h" using std::cout; using std::endl; /* * Get a window's screen coords. */ static void Get_window_coords ( Display *display, Window win, int &sx, int& sy // Coords. returned. ) { Window root, parent; // Get parent window. Window *children; unsigned int nchildren; XQueryTree(display, win, &root, &parent, &children, &nchildren); if (children) XFree(children); if (parent && parent != root) // Recurse on parent. Get_window_coords(display, parent, sx, sy); else sx = sy = 0; XWindowAttributes atts; // Get position within parent. XGetWindowAttributes(display, win, &atts); sx += atts.x; sy += atts.y; } /* * Initialize. */ Xdnd::Xdnd ( Display *d, Window xw, // Window-manager window. Window xgw, // Game's display window in xw. Move_shape_handler_fun movefun, Move_combo_handler_fun movecmbfun, Drop_shape_handler_fun shapefun, Drop_chunk_handler_fun cfun, Drop_combo_handler_fun cmbfun ) : display(d), xwmwin(xw), xgamewin(xgw), num_types(0), lastx(-1), lasty(-1), file(-1), shape(-1), frame(-1), chunknum(-1), combo_cnt(-1), combo(0), combo_xtiles(0), combo_ytiles(0), data_valid(false), move_shape_handler(movefun), move_combo_handler(movecmbfun), shape_handler(shapefun), chunk_handler(cfun), combo_handler(cmbfun) { shapeid_atom = XInternAtom(display, U7_TARGET_SHAPEID_NAME, 0); chunkid_atom = XInternAtom(display, U7_TARGET_CHUNKID_NAME, 0); comboid_atom = XInternAtom(display, U7_TARGET_COMBOID_NAME, 0); // Atom for Xdnd protocol: xdnd_aware = XInternAtom(display, "XdndAware", 0); xdnd_enter = XInternAtom(display, "XdndEnter", 0); xdnd_leave = XInternAtom(display, "XdndLeave", 0); xdnd_position = XInternAtom(display, "XdndPosition", 0); xdnd_drop = XInternAtom(display, "XdndDrop", 0); xdnd_status = XInternAtom(display, "XdndStatus", 0); xdnd_copy = XInternAtom(display, "XdndActionCopy", 0); xdnd_ask = XInternAtom(display, "XdndActionAsk", 0); xdnd_typelist = XInternAtom(display, "XdndTypeList", 0); xdnd_selection = XInternAtom(display, "XdndSelection", 0); xdnd_version = 3; // Create XdndAware property. if (xwmwin) XChangeProperty(display, xwmwin, xdnd_aware, XA_ATOM, 32, PropModeReplace, reinterpret_cast( &xdnd_version), 1); } /* * Cleanup. */ Xdnd::~Xdnd ( ) { delete combo; } /* * Handle drag-and-drop. */ void Xdnd::client_msg ( XClientMessageEvent& cev // Message received. ) { cout << "Xwin client msg. received." << endl; char *nm = XGetAtomName(display, cev.message_type); if (nm) cout << "Type = " << nm << endl; XEvent xev; // Return event. xev.xclient.type = ClientMessage; Window drag_win = cev.data.l[0];// Where drag comes from. xev.xclient.format = 32; xev.xclient.window = drag_win; xev.xclient.data.l[0] = xwmwin; if (cev.message_type == xdnd_enter) { data_valid = false; if (cev.data.l[1]&1) // More than 3 types? { Atom type; int format; unsigned long nitems, after; Atom *data; XGetWindowProperty(display, drag_win, xdnd_typelist, 0, 65536, false, XA_ATOM, &type, &format, &nitems, &after, reinterpret_cast( &data)); if (format != 32 || type != XA_ATOM) return; // No good. if (nitems > max_types) nitems = max_types; for (num_types = 0; num_types < nitems; num_types++) drag_types[num_types] = data[num_types]; } else { num_types = 0; for (int i = 0; i < 3; i++) if (cev.data.l[2+i]) drag_types[num_types++] = cev.data.l[2+i]; cout << "num_types = " << num_types << endl; } // Save current window coords. Get_window_coords(display, xgamewin, winx, winy); } else if (cev.message_type == xdnd_position) { int i; // For now, just do shapeid. for (i = 0; i < num_types; i++) if (drag_types[i] == shapeid_atom || drag_types[i] == chunkid_atom || drag_types[i] == comboid_atom) break; xev.xclient.message_type = xdnd_status; // Flags??: 3=good, 0=can't accept. xev.xclient.data.l[1] = i < num_types ? 3 : 0; // I think next 2 should be a rect.?? xev.xclient.data.l[2] = 0; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = xdnd_copy; XSendEvent(display, drag_win, false, 0, &xev); // Save mouse position. int x = ((cev.data.l[2]>>16)&0xffff) - winx; int y = (cev.data.l[2]&0xffff) - winy; // Get timestamp. unsigned long time = 0; //????++++++++++++++++ if (i == num_types) return; if (!data_valid) // Tell owner we want data. XConvertSelection(display, xdnd_selection, drag_types[i], xdnd_selection, xwmwin, time); else if (file == U7_SHAPE_SHAPES) (*move_shape_handler)(shape, frame, x,y, lastx, lasty, true); else if (combo_cnt > 0) (*move_combo_handler)(combo_xtiles, combo_ytiles, combo_tiles_right, combo_tiles_below, x, y, lastx, lasty, true); lastx = x; lasty = y; } else if (cev.message_type == xdnd_leave) { num_types = 0; // Clear list. // Force repaint to clear grid. (*move_shape_handler)(-1, -1, 0, 0, lastx, lasty, true); data_valid = false; } else if (cev.message_type == xdnd_drop) { int i; // For now, just do shapes, chunks. for (i = 0; i < num_types; i++) if (drag_types[i] == shapeid_atom || drag_types[i] == chunkid_atom || drag_types[i] == comboid_atom) break; bool okay = data_valid && i < num_types; num_types = 0; if (!okay) return; if (shape >= 0) // Dropping a shape? { if (file == U7_SHAPE_SHAPES) // For now, just allow "shapes.vga". (*shape_handler)(shape, frame, lastx,lasty, 0); } else if (chunknum >= 0) // A whole chunk. (*chunk_handler)(chunknum, lastx, lasty, 0); else if (combo_cnt >= 0 && combo) (*combo_handler)(combo_cnt, combo, lastx, lasty, 0); data_valid = false; } } /* * Get the selection data. */ void Xdnd::select_msg ( XSelectionEvent& sev ) { cout << "SelectionEvent received with target type: " << XGetAtomName(display, sev.target) << endl; if (sev.selection != xdnd_selection || (sev.target != shapeid_atom && sev.target != chunkid_atom && sev.target != comboid_atom) || sev.property == None) return; // Wrong type. cout << "HERE" << endl; file = shape = frame = -1; // Invalidate old data. chunknum = -1; combo_cnt = -1; combo_xtiles = combo_ytiles = 0; delete combo; combo = 0; Atom type = None; // Get data. int format; unsigned long nitems, after; unsigned char *data; if (XGetWindowProperty(display, sev.requestor, sev.property, 0, 65000, False, AnyPropertyType, &type, &format, &nitems, &after, &data) != Success) { cout << "Error in getting selection" << endl; return; } if (sev.target == shapeid_atom) // Dropping a shape? { // Get shape info. Get_u7_shapeid(data, file, shape, frame); data_valid = true; } else if (sev.target == chunkid_atom) { // A whole chunk. Get_u7_chunkid(data, chunknum); data_valid = true; } else if (sev.target == comboid_atom) { Get_u7_comboid(data, combo_xtiles, combo_ytiles, combo_tiles_right, combo_tiles_below, combo_cnt, combo); cout << "Combo: xtiles=" << combo_xtiles << ", ytiles=" << combo_ytiles << ", tiles_right=" << combo_tiles_right << ", tiles_below=" << combo_tiles_below << endl; data_valid = true; } XFree(data); } #endif /* USE_EXULTSTUDIO */ exult-1.2/README.win320000755000175000001440000001035607741460025010030 Exult instructions for Windows ------------------------------------ To play --------- Copy exult.exe into your Ultima 7 directory. If you are currently playing a game of Ultima 7, be sure to remove the gamedat directory. (don't forget to back it up first...) Run exult.exe Have fun! Notes ------ * Exult generates the files 'stdout.txt' and 'stderr.txt'. These may give you some idea of what is going on under the hood. When Exult suddenly quits, sometimes these files can help. * If you're interested in building Exult for windows yourself, there are two sections below describing how. To build in Windows using MinGW ----------------------------------- (Thanks to Travis Howell) Download and install MinGW from: http://prdownloads.sourceforge.net/mingw/MinGW-3.1.0-1.exe Download and install MSYS from: http://prdownloads.sourceforge.net/mingw/MSYS-1.0.9.exe Download the SDL binaries & headers from: http://exult.sourceforge.net/snapshots/exult_sdl_win32.zip Unzip this file into the main directory of Exult source code. (it should add a SDL subdirectory) Download the other required developer tools from: http://exult.sourceforge.net/snapshots/exult_dev_win32.zip Unzip this file into the MinGW directory. If you want to compile Exult Studio get the additional required developer tools from: http://exult.sourceforge.net/snapshots/exult_studio_dev_win32.zip Unzip this file into the MinGW directory. Start MSYS Change to the directory where you unpacked the Exult source code. (ie cd C:/exult ) Open makefile.mingw from the Exult directory in a text editor and change C:/Ultima7 to the directory you want Exult to be installed to. (ie C:/Games/Ultima7 ) If you are compiling Exult Studio, open makefile.studio.mingw from the Exult directory in a text editor and change C:/Ultima7 to the directory you want Exult Studio to be installed to. (It must be the same directory that Exult is installed into to!) (ie C:/Games/Ultima7 ) Type 'make -f makefile.mingw install' without quotes to compile and install Exult for Windows Type 'make -f makefile.mingw toolsinstall' without quotes to compile and install the Exult Tools for Windows Type 'make -f makefile.studio.mingw install' without quotes to compile and install Exult Studio for Windows Copy over the required library files (*.dll) from the bin directory of MinGW to the installation directory of Exult Studio Once compile has finished and been installed exit MSYS Run Exult.exe and enjoy the game :-) To build in Windows using MSVC 6.0 ---------------------------------- 1) Download SDL and ZLib for Win32/MSVC6. Add their Include and Library directories to MSVC's Search Directories (Tools->Options->Directories). SDL: http://www.libsdl.org/ ZLib: http://www.gzip.org/zlib/ 2) Set The environment variable EXULT_INSTALL_PATH to the directory where you want the Exult binaries to be copied to when doing an Install Build. This is optional and is only required for when doing an Install build. 3) Load the Exult Project Workspace "msvcstuff/Exult.dsw" in MSVC 6.0 (File->Load Workspace) 4) If required, enter the correct "Working Directory" in the "Debug tab" of the Exult project settings for all Configurations. 5) Select and Build Exult using one of the 4 Configuration (Win32 Debug, Win32 Release, Win32 Debug Install or Win32 Release Install). 6) Have Fun! To cross-build from Linux --------------------------- (Note: this hasn't been tested recently, and may or may not work) Exult is originally a Linux project, using a platform independent API called SDL. (Simple DirectMedia Layer) Because of this, the Windows version has been built in Linux, using the cross-compiler Mingw32. Please note it is not necessary to build Exult yourself, since the Windows executable is already included. 1) get and install Mingw32 and SDL. SDL: http://www.libsdl.org/index.php Mingw32: http://www.libsdl.org/extras/win32/cross/README.txt Installation instructions can be found on the same pages. (make sure to get the DirectX headers, and build SDL for the cross compiler) 2) build exult: configure --host=i386-linux --target=i386-mingw32 --enable-win32 make 3) copy exult.exe to your U7 directory, and run it from windows If you are currently playing a game of Ultima 7, be sure to make a backup of the gamedat directory. 4) Have fun :-) exult-1.2/macosx/0000777000175000001440000000000010062225324007544 5exult-1.2/macosx/exult.icns0000644000175000001440000007531407343211155011516 icnszit32:?* "3UU?8U/2Řȷ0Ż U þtǯ忿Ĵlɥ 쾿Ħc Iˤ| )漿:U1ͪ(U8ȷ ζ4 JؽǪp_u¦NcϽĠKAʹx$ɼ$U Ș ɰzwȯ-?1ŦP>?AGNUaQ 0ҭoFu ŮD UŲ&Ԭԛ}tVX?}ԃӁ҅ρ uUO8r߀4ڮxn=}܀;ԱՀրʨSUõv\T\k|$״ѱz 骀=1³u`WX^eksz}|ɴpfils}ٵ"Y̿}^4  *Ƚ2-:IoôKЦwD ,Ƽ4 $Ov nƩ]$ 1ż9$M_H ?7d 6Ż:Zrh?$m7ƻ:??U$3S^7ż<職U U9ž=UU̅:@Ɇ:ſ>U:ſ? ;@K߀ ܾCe߽P ᾳj$"㿫}3忟=Ŕ+bӑDޚi3'崘% dـ ͨUfۿŒFοC!҄?̀DՀ ˮ>˺xU yбR uw|w"X0D\YJߓE91fр ځ8:3 nۀ77+U]݉77# ^ޟ@5&? jھ]E3ɁςXJ 骀Bug"T-Zf5̪?D2??쪁?* "3UU?8U/2Řȷ0Ż U þtǯ忿Ĵlɥ 쾿Ħc Iˤ| )漿:U1ͪ(U8ȷ ζ4 JؽǪp_u¦NcϽĠKAʹx$ɼ$U Ș ɰzwȯ-?1ŦP>?AGNUaQ 0ҭoFu ŮD UŲ&Ԭԛ}tVX?}ԃӁ҅ρ uUO8r߀4ڮxn=}܀;ԱՀրʨSUõv\T\k|$״ѱz 骀=1³u`WX^eksz}|ɴpfils}ٵ"Y̿}^4  *Ƚ2-:IoôKЦwD ,Ƽ4 $Ov nƩ]$ 1ż9$M_H ?7d 6Ż:Zrh?$m7ƻ:??U$3S^7ż<職U U9ž=UU̅:@Ɇ:ſ>U:ſ? ;@K߀ ܾCe߽P ᾳj$"㿫}3忟=Ŕ+bӑDޚi3'崘% dـ ͨUfۿŒFοC!҄?̀DՀ ˮ>˺xU yбR uw|w"X0D\YJߓE91fр ځ8:3 nۀ77+U]݉77# ^ޟ@5&? jھ]E3ɁςXJ 骀Bug"T-Zf5̪?D2??쪁?* "3UU?8U/2Řȷ0Ż U þtǯ忿Ĵlɥ 쾿Ħc Iˤ| )漿:U1ͪ(U8ȷ ζ4 JؽǪp_u¦NcϽĠKAʹx$ɼ$U Ș ɰzwȯ-?1ŦP>?AGNUaQ 0ҭoFu ŮD UŲ&Ԭԛ}tVX?}ԃӁ҅ρ uUO8r߀4ڮxn=}܀;ԱՀրʨSUõv\T\k|$״ѱz 骀=1³u`WX^eksz}|ɴpfils}ٵ"Y̿}^4  *Ƚ2-:IoôKЦwD ,Ƽ4 $Ov nƩ]$ 1ż9$M_H ?7d 6Ż:Zrh?$m7ƻ:??U$3S^7ż<職U U9ž=UU̅:@Ɇ:ſ>U:ſ? ;@K߀ ܾCe߽P ᾳj$"㿫}3忟=Ŕ+bӑDޚi3'崘% dـ ͨUfۿŒFοC!҄?̀DՀ ˮ>˺xU yбR uw|w"X0D\YJߓE91fр ځ8:3 nۀ77+U]݉77# ^ޟ@5&? jھ]E3ɁςXJ 骀Bug"T-Zf5̪?D2??쪁t8mk@   &1;BFD?6,   %7K^p{gTA. &>ZzȗiK1 8YkG*'Gs]5 +Sl= -XwB *V{@  %Ps:Dg/5nV"  &WB@m-  +bOCʶy2  )aƬ_BAbR>ƨ}O)%Py/ "WȨyF ML2pϯ}FUm&DغM (i< !Vʜ\& =U ,gڵw6"bo$6{ϜSD5A7  2zG Hf#&eVNסQVcPϑ@Ko#Oȃ3Cv'Kx*>y*Eo#;x)^WdC֡PEiK̑A4q%T3 %f|,&_߲j%M6 0nҟS8D <ʼn>%gVLߵp+Kk"'_ҡV 3|37wÉ?[JMرm*=h# .h˘P%f:Fܹ{6 C\.fΠ[  'i;Kܼ>Cc' 8sΣa%$cJ,^ٺ@;}= &Qɞ^$ Wp:#*Lӳ|< &FtU]Ȟf7  *&  exult-1.2/Info.plist.in0000644000175000001440000000163510005245716010554 CFBundleDevelopmentRegion English CFBundleExecutable @EXE_TARGET@ CFBundleGetInfoString @VERSION@, Copyright 2000-2004 The Exult Team CFBundleIconFile exult.icns CFBundleInfoDictionaryVersion 6.0 CFBundleName @PACKAGE@ CFBundlePackageType APPL CFBundleShortVersionString @VERSION@ CFBundleVersion @VERSION@ NSPrincipalClass NSApplication NSHumanReadableCopyright Copyright 2000-2004 The Exult Team exult-1.2/config.h.in0000644000175000001440000001363010032174126010214 /* config.h.in. Generated from configure.ac by autoheader. */ /* Using Alpha Linux with cxx */ #undef ALPHA_LINUX_CXX /* Using Cygwin */ #undef CYGWIN /* Enable debug mode */ #undef DEBUG /* Define to 1 if you have the `atexit' function. */ #undef HAVE_ATEXIT /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 /* Define to 1 if you have the header file. */ #undef HAVE_EXT_HASH_MAP /* Define to 1 if you have the header file. */ #undef HAVE_EXT_HASH_SET /* Have freetype2 */ #undef HAVE_FREETYPE2 /* Have addrinfo/getaddrinfo */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Have GIMP */ #undef HAVE_GIMP /* Have GIMP 1.2.x */ #undef HAVE_GIMP_1_2 /* Have Glade support libraries */ #undef HAVE_GLADE /* Define to 1 if you have the header file. */ #undef HAVE_HASH_MAP /* Define to 1 if you have the header file. */ #undef HAVE_HASH_SET /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `isascii' function. */ #undef HAVE_ISASCII /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the `memchr' function. */ #undef HAVE_MEMCHR /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Have mkstemp */ #undef HAVE_MKSTEMP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Have OpenGL */ #undef HAVE_OPENGL /* Define to 1 if you have the header file. */ #undef HAVE_PNG_H /* Define to 1 if you have the `pow' function. */ #undef HAVE_POW /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Have snprintf */ #undef HAVE_SNPRINTF /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if you have the header file. */ #undef HAVE_SSTREAM /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H /* Have timidity binary */ #undef HAVE_TIMIDITY_BIN /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Have zip support */ #undef HAVE_ZIP_SUPPORT /* Initialize allocated blocks */ #undef INITIALISE_ALLOCATED_BLOCKS /* Using MacOSX */ #undef MACOSX /* Disable SDL parachute */ #undef NO_SDL_PARACHUTE /* Using OpenBSD */ #undef OPENBSD /* Package Name */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Poison allocated blocks */ #undef POISON_ALLOCATED_BLOCKS /* The size of a `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of a `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of a `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG /* The size of a `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Use ExultStudio */ #undef USE_EXULTSTUDIO /* Package Version */ #undef VERSION /* Version Number Extra */ #undef VER_EXTRA /* Version Number Major */ #undef VER_MAJOR /* Version Number Minor */ #undef VER_MINOR /* Use alternate allocator */ #undef WANT_ALTERNATE_ALLOCATOR /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define as `__inline' if that's what the C compiler calls it, or to nothing if it is not supported. */ #undef inline /* Define to `unsigned' if does not define. */ #undef size_t #ifdef ALPHA_LINUX_CXX #include "alpha_kludges.h" #endif #define USE_FMOPL_MIDI exult-1.2/exultmenu.cc0000644000175000001440000003020407753476057010552 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "menulist.h" #include "exultmenu.h" #include "exult.h" #include "mouse.h" #include "gamewin.h" #include "ibuf8.h" #include "game.h" #include "bggame.h" #include "sigame.h" #include "Audio.h" #include "font.h" #include "cheat.h" #include "Configuration.h" #include "txtscroll.h" #include "data/exult_flx.h" #include "palette.h" #include "shapeid.h" static bool get_play_intro(void); static void set_play_intro(bool); static bool get_play_1st_scene(void); static void set_play_1st_scene(bool); ExultMenu::ExultMenu(Game_window *gw) { gwin = gw; ibuf = gwin->get_win()->get_ib8(); calc_win(); fontManager.add_font("CREDITS_FONT", "/exult.flx", EXULT_FLX_FONT_SHP, 1); exult_flx.load("/exult.flx"); } ExultMenu::~ExultMenu() { } void ExultMenu::calc_win() { topx = (gwin->get_width()-320)/2; topy = (gwin->get_height()-200)/2; centerx = gwin->get_width()/2; centery = gwin->get_height()/2; menuy = topy+120; } void ExultMenu::setup() { Palette *gpal = gwin->get_pal(); Font *font = fontManager.get_font("CREDITS_FONT"); MenuList menu; int menuypos = menuy-44; MenuChoice *scalemethod = new MenuChoice(exult_flx.get_shape(EXULT_FLX_SCALING_METHOD_SHP,1), exult_flx.get_shape(EXULT_FLX_SCALING_METHOD_SHP,0), centerx, menuypos, font); for (int i = 0; i < Image_window::NumScalers; i++) scalemethod->add_choice(Image_window::get_name_for_scaler(i)); scalemethod->set_choice(gwin->get_win()->get_scaler()); menu.add_entry(scalemethod); menuypos+=11; MenuChoice *palfades = new MenuChoice(exult_flx.get_shape(EXULT_FLX_PALETTE_FADES_SHP,1), exult_flx.get_shape(EXULT_FLX_PALETTE_FADES_SHP,0), centerx, menuypos, font); palfades->add_choice("Off"); palfades->add_choice("On"); palfades->set_choice(gwin->get_pal()->get_fades_enabled()?1:0); menu.add_entry(palfades); menuypos+=11; MenuChoice *midiconv = 0; #ifdef ENABLE_MIDISFX MenuChoice *sfxconv = 0; #endif if (Audio::get_ptr()->get_midi()) { midiconv = new MenuChoice(exult_flx.get_shape(EXULT_FLX_MIDI_CONVERSION_SHP,1), exult_flx.get_shape(EXULT_FLX_MIDI_CONVERSION_SHP,0), centerx, menuypos, font); midiconv->add_choice("None"); midiconv->add_choice("GM"); midiconv->add_choice("GS"); midiconv->add_choice("GS127"); midiconv->set_choice(Audio::get_ptr()->get_midi()->get_music_conversion()); menu.add_entry(midiconv); menuypos+=11; #ifdef ENABLE_MIDISFX MenuChoice *sfxconv = new MenuChoice(exult_flx.get_shape(EXULT_FLX_SFX_CONVERSION_SHP,1), exult_flx.get_shape(EXULT_FLX_SFX_CONVERSION_SHP,0), centerx, menuypos, font); sfxconv->add_choice("None"); sfxconv->add_choice("GS"); sfxconv->set_choice(Audio::get_ptr()->get_midi()->get_effects_conversion()==XMIDI_CONVERT_GS127_TO_GS?1:0); menu.add_entry(sfxconv); menuypos+=11; #endif } MenuChoice *playintro = new MenuChoice(exult_flx.get_shape(EXULT_FLX_PLAY_INTRO_SHP,1), exult_flx.get_shape(EXULT_FLX_PLAY_INTRO_SHP,0), centerx, menuypos, font); playintro->add_choice("Off"); playintro->add_choice("On"); playintro->set_choice(get_play_intro()?1:0); menu.add_entry(playintro); menuypos+=11; MenuChoice *playscene = new MenuChoice(exult_flx.get_shape(EXULT_FLX_PLAY_1ST_SCENE_SHP,1), exult_flx.get_shape(EXULT_FLX_PLAY_1ST_SCENE_SHP,0), centerx, menuypos, font); playscene->add_choice("Off"); playscene->add_choice("On"); playscene->set_choice(get_play_1st_scene()?1:0); menu.add_entry(playscene); menuypos+=11; MenuChoice *fullscreen = new MenuChoice(exult_flx.get_shape(EXULT_FLX_FULL_SCREEN_SHP,1), exult_flx.get_shape(EXULT_FLX_FULL_SCREEN_SHP,0), centerx, menuypos, font); fullscreen->add_choice("Off"); fullscreen->add_choice("On"); fullscreen->set_choice(gwin->get_win()->is_fullscreen()?1:0); menu.add_entry(fullscreen); menuypos+=11; MenuChoice *cheating = new MenuChoice(exult_flx.get_shape(EXULT_FLX_CHEATING_SHP,1), exult_flx.get_shape(EXULT_FLX_CHEATING_SHP,0), centerx, menuypos, font); cheating->add_choice("Off"); cheating->add_choice("On"); cheating->set_choice(cheat()?1:0); menu.add_entry(cheating); menuypos+=11; MenuEntry *ok = new MenuEntry(exult_flx.get_shape(EXULT_FLX_OK_SHP,1), exult_flx.get_shape(EXULT_FLX_OK_SHP,0), centerx-64, menuy+55); int ok_button = menu.add_entry(ok); MenuEntry *cancel = new MenuEntry(exult_flx.get_shape(EXULT_FLX_CANCEL_SHP,1), exult_flx.get_shape(EXULT_FLX_CANCEL_SHP,0), centerx+64, menuy+55); int cancel_button = menu.add_entry(cancel); menu.set_selection(0); gwin->clear_screen(true); for(;;) { gpal->apply(); int entry = menu.handle_events(gwin,menu_mouse); if(entry==ok_button) { gpal->fade_out(c_fade_out_time); gwin->clear_screen(true); // Scaling Method int scaler = scalemethod->get_choice(); if(scaler!=gwin->get_win()->get_scaler()) { gwin->resized( gwin->get_win()->get_width(), gwin->get_win()->get_height(), gwin->get_win()->get_scale(), scalemethod->get_choice() ); if (scaler > Image_window::NoScaler && scaler < Image_window::NumScalers) config->set("config/video/scale_method",Image_window::get_name_for_scaler(scaler),true); } // Palette fades gpal->set_fades_enabled( palfades->get_choice()==1); config->set("config/video/disable_fades", gpal->get_fades_enabled()?"no":"yes",true); if (Audio::get_ptr()->get_midi()) { if (midiconv) { // Midi Conversion Audio::get_ptr()->get_midi()->set_music_conversion(midiconv->get_choice()); } #ifdef ENABLE_MIDISFX if (sfxconv) { // SFX Conversion Audio::get_ptr()->get_midi()->set_effects_conversion(sfxconv->get_choice()==1?XMIDI_CONVERT_GS127_TO_GS:XMIDI_CONVERT_NOCONVERSION); } #endif } // Play Intro set_play_intro(playintro->get_choice()==1); // Play 1st scene set_play_1st_scene(playscene->get_choice()==1); // Full screen if(((fullscreen->get_choice()==0)&&(gwin->get_win()->is_fullscreen()))|| ((fullscreen->get_choice()==1)&&(!gwin->get_win()->is_fullscreen()))) gwin->get_win()->toggle_fullscreen(); config->set("config/video/fullscreen",gwin->get_win()->is_fullscreen()?"yes":"no",true); // Cheating cheat.set_enabled(cheating->get_choice()==1); calc_win(); return; } else if (entry==cancel_button) { gpal->fade_out(c_fade_out_time); gwin->clear_screen(true); return; } } } Exult_Game ExultMenu::run() { Palette *gpal = gwin->get_pal(); Shape_manager *sman = Shape_manager::get_instance(); Font *font = fontManager.get_font("CREDITS_FONT"); // Check for the games in the designated directories. bool bg_installed = BG_Game::is_installed(); bool si_installed = SI_Game::is_installed(); if(!bg_installed && !si_installed) { gpal->load("/exult.flx",EXULT_FLX_EXULT0_PAL); font->center_text(gwin->get_win()->get_ib8(), centerx, topy+20, "WARNING"); font->center_text(gwin->get_win()->get_ib8(), centerx, topy+40, "Could not find the data files for either"); font->center_text(gwin->get_win()->get_ib8(), centerx, topy+50, "\"The Black Gate\" or \"Serpent Isle\"."); font->center_text(gwin->get_win()->get_ib8(), centerx, topy+60, "Please edit the configuration file"); font->center_text(gwin->get_win()->get_ib8(), centerx, topy+70, "and restart Exult"); gpal->apply(); while(!wait_delay(200)) ; throw quit_exception(1); } ExultDataSource *midi_data = new ExultDataSource("/exult.flx", EXULT_FLX_MEDITOWN_MID); XMIDI midfile(midi_data, XMIDI_CONVERT_NOCONVERSION); if(Audio::get_ptr()->audio_enabled) //Must check this or it will crash as midi //may not be initialised { if(Audio::get_ptr()->get_midi()->get_output_driver_type() == MIDI_DRIVER_OGG) Audio::get_ptr()->start_music(99,true); else Audio::get_ptr()->start_music(midfile.GetEventList(0), true); } ExultDataSource mouse_data("/exult.flx", EXULT_FLX_POINTERS_SHP); menu_mouse = new Mouse(gwin, mouse_data); sman->paint_shape(topx,topy,exult_flx.get_shape(EXULT_FLX_EXULT_LOGO_SHP, 0)); gpal->load("/exult.flx",EXULT_FLX_EXULT0_PAL); gpal->fade_in(c_fade_in_time); wait_delay(2000); MenuList *menu = new MenuList(); int menuchoices[] = { EXULT_FLX_BLACK_GATE_SHP, EXULT_FLX_SERPENT_ISLE_SHP, EXULT_FLX_SETUP_SHP, EXULT_FLX_EXULT_CREDITS_SHP, EXULT_FLX_EXULT_QUOTES_SHP, EXULT_FLX_EXIT_SHP }; int num_choices = sizeof(menuchoices)/sizeof(int); int *menuentries = new int[num_choices]; int entries = 0; int sfx_bg_ypos = -1, sfx_si_ypos = -1; int ypos = menuy-24; for(int i=0; i1) { menu->add_entry(new MenuEntry(exult_flx.get_shape(menuchoices[i],1), exult_flx.get_shape(menuchoices[i],0), centerx, ypos)); if(i==0) sfx_bg_ypos = ypos; if(i==1) sfx_si_ypos = ypos; ypos += exult_flx.get_shape(menuchoices[i],0)->get_height()+2; menuentries[entries++]=i; } if(i<2) ypos+=5; } menu->set_selection(0); Exult_Game sel_game = NONE; do { sman->paint_shape(topx,topy,exult_flx.get_shape(EXULT_FLX_EXULT_LOGO_SHP, 1)); font->draw_text(gwin->get_win()->get_ib8(), topx+320-font->get_text_width(VERSION), topy+190, VERSION); if (sfx_bg_ypos >= 0) sman->paint_shape(centerx-80,sfx_bg_ypos, exult_flx.get_shape(EXULT_FLX_SFX_ICON_SHP, Audio::get_ptr()->can_sfx("blackgate")?1:0)); if (sfx_si_ypos >= 0) sman->paint_shape(centerx-80,sfx_si_ypos,exult_flx.get_shape(EXULT_FLX_SFX_ICON_SHP, Audio::get_ptr()->can_sfx("serpentisle")?1:0)); int choice = menu->handle_events(gwin, menu_mouse); switch(choice<0?choice:menuentries[choice]) { case 5: case -1: // Exit gpal->fade_out(c_fade_out_time); Audio::get_ptr()->stop_music(); throw quit_exception(); case 0: // Black Gate gpal->fade_out(c_fade_out_time); sel_game = BLACK_GATE; break; case 1: // Serpent Isle gpal->fade_out(c_fade_out_time); sel_game = SERPENT_ISLE; break; case 2: // Setup gpal->fade_out(c_fade_out_time); setup(); gpal->apply(); break; case 3: // Exult Credits { gpal->fade_out(c_fade_out_time); TextScroller credits("/exult.flx", EXULT_FLX_CREDITS_TXT, fontManager.get_font("CREDITS_FONT"), exult_flx.extract_shape(EXULT_FLX_EXTRAS_SHP)); credits.run(gwin); gwin->clear_screen(true); gpal->apply(); } break; case 4: // Exult Quotes { gpal->fade_out(c_fade_out_time); TextScroller quotes("/exult.flx", EXULT_FLX_QUOTES_TXT, fontManager.get_font("CREDITS_FONT"), exult_flx.extract_shape(EXULT_FLX_EXTRAS_SHP)); quotes.run(gwin); gwin->clear_screen(true); gpal->apply(); } break; default: break; } } while(sel_game==NONE); delete[] menuentries; delete menu; gwin->clear_screen(true); Audio::get_ptr()->stop_music(); delete menu_mouse; delete midi_data; return sel_game; } bool get_play_intro (void) { std::string yn; config->value("config/gameplay/skip_splash", yn, "no"); return(yn=="no"); } void set_play_intro (bool play) { config->set("config/gameplay/skip_splash", play?"no":"yes", true); } bool get_play_1st_scene (void) { std::string yn; config->value("config/gameplay/skip_intro", yn, "no"); return(yn=="no"); } void set_play_1st_scene (bool play) { config->set("config/gameplay/skip_intro", play?"no":"yes", true); } exult-1.2/imagewin/0000777000175000001440000000000010062225326010054 5exult-1.2/imagewin/iwin8.h0000644000175000001440000000726507517355271011227 /** ** Iwin8.h - 8-bit image window. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_IWIN8 #define INCL_IWIN8 1 #include "imagewin.h" #include "ibuf8.h" template class GammaTable; /* * Here's an 8-bit color-depth window (faster than the generic). */ class Image_window8 : public Image_window { unsigned char colors[768]; // Palette. Image_buffer8 *ib8; // Cast to 8-bit buffer. static GammaTable GammaRed; static GammaTable GammaGreen; static GammaTable GammaBlue; public: Image_window8(unsigned int w, unsigned int h, int scl = 1, bool fs = false, int sclr = point); ~Image_window8(); Image_buffer8 *get_ib8() const { return ib8; } // Set palette. virtual void set_palette(unsigned char *rgbs, int maxval, int brightness = 100); // Rotate palette colors. virtual void rotate_colors(int first, int num, int upd); /* * 8-bit color methods: */ // Fill with given (8-bit) value. void fill8(unsigned char val) { ib8->Image_buffer8::fill8(val); } // Fill rect. wth pixel. void fill8(unsigned char val, int srcw, int srch, int destx, int desty) { IF_OPENGL(opengl_fill8(val, srcw, srch, destx, desty), ib8->Image_buffer8::fill8(val, srcw, srch, destx, desty)); } // Fill line with pixel. void fill_line8(unsigned char val, int srcw, int destx, int desty) { ib8->Image_buffer8::fill_line8(val, srcw, destx, desty); } // Copy rectangle into here. void copy8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { ib8->Image_buffer8::copy8(src_pixels, srcw, srch, destx, desty); } // Copy line to here. void copy_line8(unsigned char *src_pixels, int srcw, int destx, int desty) { ib8->Image_buffer8::copy_line8(src_pixels, srcw, destx, desty); } // Copy with translucency table. void copy_line_translucent8( unsigned char *src_pixels, int srcw, int destx, int desty, int first_translucent, int last_translucent, Xform_palette *xforms) { ib8->Image_buffer8::copy_line_translucent8(src_pixels, srcw, destx, desty, first_translucent, last_translucent, xforms); } // Apply translucency to a line. void fill_line_translucent8(unsigned char val, int srcw, int destx, int desty, Xform_palette& xform) { ib8->Image_buffer8::fill_line_translucent8(val, srcw, destx, desty, xform); } // Copy rect. with transp. color. void copy_transparent8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { ib8->Image_buffer8::copy_transparent8(src_pixels, srcw, srch, destx, desty); } // Get/put a single pixel. unsigned char get_pixel8(int x, int y) { return ib8->Image_buffer8::get_pixel8(x, y); } void put_pixel8(unsigned char pix, int x, int y) { ib8->Image_buffer8::put_pixel8(pix, x, y); } static void get_gamma (float &r, float &g, float &b); static void set_gamma (float r, float g, float b); unsigned char* mini_screenshot(); }; #endif exult-1.2/imagewin/imagebuf.h0000644000175000001440000001327207517355271011743 /** ** Imagebuf.h - A buffer for blitting. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_IMAGEBUF #define INCL_IMAGEBUF 1 // Table for translating palette vals.: //typedef unsigned char *Xform_palette; // Should be 256-bytes. /* * This class represents a single transparent color by providing a * palette for its effect on all the other colors. */ class Xform_palette { public: unsigned char colors[256]; // For transforming 8-bit colors. unsigned char r,g,b,a; // Actual colour and alpha. void set_color(int cr, int cg, int cb, int ca) { r = cr; g = cg; b = cb; a = ca; } unsigned char operator[](int i) const { return colors[i]; } }; /* * Here's a generic off-screen buffer. It's up to the derived classes * to set the data. */ class Image_buffer { protected: unsigned int width, height; // Dimensions (in pixels). int depth; // # bits/pixel. int pixel_size; // # bytes/pixel. unsigned char *bits; // Allocated image buffer. unsigned int line_width; // # words/scan-line. private: int clipx, clipy, clipw, cliph; // Clip rectangle. // Clip. Rets. 0 if nothing to draw. int clip_internal(int& srcx, int& srcw, int& destx, int clips, int clipl) { if (destx < clips) { if ((srcw += (destx - clips)) <= 0) return (0); srcx -= (destx - clips); destx = clips; } if (destx + srcw > (clips + clipl)) if ((srcw = ((clips + clipl) - destx)) <= 0) return (0); return (1); } protected: int clip_x(int& srcx, int& srcw, int& destx, int desty) { return desty < clipy || desty >= clipy + cliph ? 0 : clip_internal(srcx, srcw, destx, clipx, clipw); } int clip(int& srcx, int& srcy, int& srcw, int& srch, int& destx, int& desty) { // Start with x-dim. return (clip_internal(srcx, srcw, destx, clipx, clipw) && clip_internal(srcy, srch, desty, clipy, cliph)); } Image_buffer(unsigned int w, unsigned int h, int dpth); public: friend class Image_buffer8; friend class Image_buffer16; virtual ~Image_buffer() { delete [] bits; // In case Image_window didn't. } friend class Image_window; unsigned char *get_bits() // Get ->data. { return bits; } unsigned int get_width() { return width; } unsigned int get_height() { return height; } unsigned int get_line_width() { return line_width; } void clear_clip() // Reset clip to whole window. { clipx = clipy = 0; clipw = width; cliph = height; } // Set clip. void set_clip(int x, int y, int w, int h) { clipx = x; clipy = y; clipw = w; cliph = h; } // Is rect. visible within clip? int is_visible(int x, int y, int w, int h) { return (!(x >= clipx + clipw || y >= clipy + cliph || x + w <= clipx || y + h <= clipy)); } /* * 16-bit color methods. Default is to ignore them. */ // Fill with given pixel. virtual void fill16(unsigned short pix) { } // Fill rect. wth pixel. virtual void fill16(unsigned short pix, int srcw, int srch, int destx, int desty) { } // Copy rectangle into here. virtual void copy16(unsigned short *src_pixels, int srcw, int srch, int destx, int desty) { } // Copy rect. with transp. color. virtual void copy_transparent16(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { } /* * 8-bit color methods: */ // Fill with given (8-bit) value. virtual void fill8(unsigned char val) = 0; // Fill rect. with pixel. virtual void fill8(unsigned char val, int srcw, int srch, int destx, int desty) = 0; // Fill line with pixel. virtual void fill_line8(unsigned char val, int srcw, int destx, int desty) = 0; // Copy rectangle into here. virtual void copy8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) = 0; // Copy line to here. virtual void copy_line8(unsigned char *src_pixels, int srcw, int destx, int desty) = 0; // Copy with translucency table. virtual void copy_line_translucent8( unsigned char *src_pixels, int srcw, int destx, int desty, int first_translucent, int last_translucent, Xform_palette *xforms) = 0; // Apply translucency to a line. virtual void fill_line_translucent8(unsigned char val, int srcw, int destx, int desty, Xform_palette& xform) = 0; // Apply translucency to a rectangle virtual void fill_translucent8(unsigned char val, int srcw, int srch, int destx, int desty, Xform_palette& xform) = 0; // Copy rect. with transp. color. virtual void copy_transparent8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) = 0; /* * Depth-independent methods: */ virtual Image_buffer *create_another(int w, int h) = 0; // Copy within itself. virtual void copy(int srcx, int srcy, int srcw, int srch, int destx, int desty) = 0; // Get rect. into another buf. virtual void get(Image_buffer *dest, int srcx, int srcy) = 0; // Put rect. back. virtual void put(Image_buffer *src, int destx, int desty) = 0; virtual void fill_static(int black, int gray, int white) = 0; }; #endif exult-1.2/imagewin/imagewin.h0000644000175000001440000002223307631060063011746 /** ** Imagewin.h - A window to blit images into. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_IMAGEWIN #define INCL_IMAGEWIN 1 //#include "SDL_video.h" #include "imagebuf.h" #include "exult_types.h" #include struct SDL_Surface; struct SDL_RWops; #ifdef HAVE_OPENGL #define IF_OPENGL(a,b) if (scaler == OpenGL) a; else b #else #define IF_OPENGL(a,b) b #endif /* * Here's the top-level class to use for image buffers. Image_window * should be derived from it. */ class Image_window { public: // Firstly just some public scaler stuff // The scaler types. ScalerNames needs to match this #ifdef HAVE_OPENGL enum ScalerType { point = 0, interlaced = 1, bilinear = 2, BilinearPlus = 3, SaI = 4, SuperEagle = 5, Super2xSaI = 6, Scale2x = 7, OpenGL = 8, NoScaler = -1, NumScalers = 9 }; #else enum ScalerType { point = 0, interlaced = 1, bilinear = 2, BilinearPlus = 3, SaI = 4, SuperEagle = 5, Super2xSaI = 6, Scale2x = 7, OpenGL = 8, NoScaler = -1, NumScalers = 8 // no OpenGL. (But leave it in the enum.) }; #endif static const char *ScalerNames[]; static ScalerType get_scaler_for_name(const std::string &name); inline static const char *get_name_for_scaler(int num) { return ScalerNames[num]; } protected: Image_buffer *ibuf; // Where the data is actually stored. int scale; // Only 1 or 2 for now. int scaler; // What scaler do we want to use bool uses_palette; // Does this window have a palette bool fullscreen; // Rendering fullscreen. SDL_Surface *surface; // Represents window in memory. (has palette) SDL_Surface *scaled_surface; // 2X surface if scaling, else 0. (only used when scaling) SDL_Surface *unscaled_surface; // Unscaled surface (used for screenshots only) // Method to blit scaled: void (Image_window::*show_scaled)(int x, int y, int w, int h); /* * Scaled blits: */ void show_scaled8to16_2xSaI(int x, int y, int w, int h); void show_scaled8to555_2xSaI(int x, int y, int w, int h); void show_scaled8to565_2xSaI(int x, int y, int w, int h); void show_scaled8to32_2xSaI(int x, int y, int w, int h); void show_scaled8to16_Super2xSaI(int x, int y, int w, int h); void show_scaled8to555_Super2xSaI(int x, int y, int w, int h); void show_scaled8to565_Super2xSaI(int x, int y, int w, int h); void show_scaled8to32_Super2xSaI(int x, int y, int w, int h); void show_scaled8to16_bilinear(int x, int y, int w, int h); void show_scaled8to555_bilinear(int x, int y, int w, int h); void show_scaled8to565_bilinear(int x, int y, int w, int h); void show_scaled8to32_bilinear(int x, int y, int w, int h); void show_scaled8to16_SuperEagle(int x, int y, int w, int h); void show_scaled8to555_SuperEagle(int x, int y, int w, int h); void show_scaled8to565_SuperEagle(int x, int y, int w, int h); void show_scaled8to32_SuperEagle(int x, int y, int w, int h); void show_scaled_point(int x, int y, int w, int h); void show_scaled_interlace(int x, int y, int w, int h); void show_scale2x_noblur(int x, int y, int w, int h); void show_scaled8to16_BilinearPlus(int x, int y, int w, int h); void show_scaled8to555_BilinearPlus(int x, int y, int w, int h); void show_scaled8to565_BilinearPlus(int x, int y, int w, int h); void show_scaled8to32_BilinearPlus(int x, int y, int w, int h); void show_scaledOpenGL(int x, int y, int w, int h); /* * Image info. */ // Create new SDL surface. void create_surface(unsigned int w, unsigned int h); void free_surface(); // Free it. bool try_scaler(int w, int h, uint32 flags); public: // Create with given buffer. Image_window(Image_buffer *ib, int scl = 1, bool fs = false, int sclr = point) : ibuf(ib), scale(scl), scaler(sclr), uses_palette(true), fullscreen(fs), surface(0), scaled_surface(0), show_scaled(0) { create_surface(ibuf->width, ibuf->height); } virtual ~Image_window(); int get_scale() // Returns 1 or 2. { return scale; } int get_scaler() // Returns 1 or 2. { return scaler; } bool is_palettized() // Does the window have a palette? { return uses_palette; } // Is rect. visible within clip? int is_visible(int x, int y, int w, int h) { return ibuf->is_visible(x, y, w, h); } // Set title. void set_title(const char *title); Image_buffer *get_ibuf() { return ibuf; } int get_width() { return ibuf->width; } int get_height() { return ibuf->height; } int ready() // Ready to draw? { return (ibuf->bits != 0); } bool is_fullscreen() { return fullscreen; } // Create a compatible image buffer. Image_buffer *create_buffer(int w, int h); // Resize event occurred. void resized(unsigned int neww, unsigned int nehh, int newsc, int newscaler = point); void show(); // Repaint entire window. // Repaint rectangle. void show(int x, int y, int w, int h); void toggle_fullscreen(); // Set palette. virtual void set_palette(unsigned char *rgbs, int maxval, int brightness = 100) { } // Rotate palette colors. virtual void rotate_colors(int first, int num, int upd) { } /* * 16-bit color methods. */ // Fill with given pixel. void fill16(unsigned short pix) { ibuf->fill16(pix); } // Fill rect. wth pixel. void fill16(unsigned short pix, int srcw, int srch, int destx, int desty) { ibuf->fill16(pix, srcw, srch, destx, desty); } // Copy rectangle into here. void copy16(unsigned short *src_pixels, int srcw, int srch, int destx, int desty) { ibuf->copy16(src_pixels, srcw, srch, destx, desty); } // Copy rect. with transp. color. void copy_transparent16(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { ibuf->copy_transparent16(src_pixels, srcw, srch, destx, desty); } /* * 8-bit color methods: */ // Fill with given (8-bit) value. void fill8(unsigned char val) { ibuf->fill8(val); } // Fill rect. wth pixel. void fill8(unsigned char val, int srcw, int srch, int destx, int desty) { IF_OPENGL(opengl_fill8(val, srcw, srch, destx, desty), ibuf->fill8(val, srcw, srch, destx, desty)); } // Fill line with pixel. void fill_line8(unsigned char val, int srcw, int destx, int desty) { ibuf->fill_line8(val, srcw, destx, desty); } // Copy rectangle into here. void copy8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { ibuf->copy8(src_pixels, srcw, srch, destx, desty); } // Copy line to here. void copy_line8(unsigned char *src_pixels, int srcw, int destx, int desty) { ibuf->copy_line8(src_pixels, srcw, destx, desty); } // Copy with translucency table. void copy_line_translucent8( unsigned char *src_pixels, int srcw, int destx, int desty, int first_translucent, int last_translucent, Xform_palette *xforms) { ibuf->copy_line_translucent8(src_pixels, srcw, destx, desty, first_translucent, last_translucent, xforms); } // Apply translucency to a line. void fill_line_translucent8(unsigned char val, int srcw, int destx, int desty, Xform_palette& xform) { ibuf->fill_line_translucent8(val, srcw, destx, desty, xform); } // Apply translucency to a rectangle virtual void fill_translucent8(unsigned char val, int srcw, int srch, int destx, int desty, Xform_palette& xform) { IF_OPENGL(opengl_fill_translucent8(val, srcw, srch, destx, desty, xform), ibuf->fill_translucent8(val, srcw, srch, destx, desty, xform)); } // Copy rect. with transp. color. void copy_transparent8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty) { ibuf->copy_transparent8(src_pixels, srcw, srch, destx, desty); } /* * OpenGL: */ #ifdef HAVE_OPENGL // Fill rect. wth pixel. void opengl_fill8(unsigned char val, int srcw, int srch, int destx, int desty); virtual void opengl_fill_translucent8(unsigned char val, int srcw, int srch, int destx, int desty, Xform_palette& xform); #endif /* * Depth-independent methods: */ void clear_clip() // Reset clip to whole window. { ibuf->clear_clip(); } // Set clip. void set_clip(int x, int y, int w, int h) { ibuf->set_clip(x, y, w, h); } // Copy within itself. void copy(int srcx, int srcy, int srcw, int srch, int destx, int desty) { ibuf->copy(srcx, srcy, srcw, srch, destx, desty); } // Get rect. into another buf. void get(Image_buffer *dest, int srcx, int srcy) { ibuf->get(dest, srcx, srcy); } // Put rect. back. void put(Image_buffer *src, int destx, int desty) { ibuf->put(src, destx, desty); } bool screenshot(SDL_RWops *dst); }; #endif /* INCL_IMAGEWIN */ exult-1.2/imagewin/imagebuf.cc0000644000175000001440000000247507323144024012067 /** ** Imagebuf.cc - A window to blit images into. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "imagebuf.h" /* * Create buffer. */ Image_buffer::Image_buffer ( unsigned int w, // Desired width, height. unsigned int h, int dpth // Depth (bits/pixel). ) : width(w), height(h), depth(dpth), bits(0), line_width(w), clipx(0), clipy(0), clipw(w), cliph(h) { switch (depth) // What depth? { case 8: pixel_size = 1; break; case 15: case 16: pixel_size = 2; break; case 32: pixel_size = 4; break; } } exult-1.2/imagewin/iwin8.cc0000644000175000001440000001146510054030561011340 /** ** Iwin8.h - 8-bit image window. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "SDL_video.h" #include "iwin8.h" #include "exult_types.h" #include "gamma.h" #include #ifndef UNDER_CE using std::memmove; #endif GammaTable Image_window8::GammaRed(256); GammaTable Image_window8::GammaBlue(256); GammaTable Image_window8::GammaGreen(256); Image_window8::Image_window8(unsigned int w, unsigned int h, int scl, bool fs, int sclr) : Image_window(new Image_buffer8(w, h, (Image_buffer *) 0), scl, fs, sclr) { ib8 = (Image_buffer8 *) ibuf; } Image_window8::~Image_window8() { } void Image_window8::get_gamma (float &r, float &g, float &b) { r = GammaRed.get_gamma(); g = GammaGreen.get_gamma(); b = GammaBlue.get_gamma(); } void Image_window8::set_gamma (float r, float g, float b) { GammaRed.set_gamma(r); GammaGreen.set_gamma(g); GammaBlue.set_gamma(b); } /* * Convert rgb value. */ inline unsigned short Get_color8 ( unsigned char val, int maxval, int brightness // 100=normal. ) { uint32 c = (((uint32) val)*brightness*255L)/ (100*maxval); return (c <= 255L ? (unsigned short) c : 255); } /* * Set palette. */ void Image_window8::set_palette ( unsigned char *rgbs, // 256 3-byte entries. int maxval, // Highest val. for each color. int brightness // Brightness control (100 = normal). ) { // Get the colors. SDL_Color colors2[256]; for (int i = 0; i < 256; i++) { colors2[i].r = colors[i*3] = GammaRed[Get_color8(rgbs[3*i], maxval, brightness)]; colors2[i].g = colors[i*3+1] = GammaGreen[Get_color8(rgbs[3*i + 1], maxval, brightness)]; colors2[i].b = colors[i*3+2] = GammaBlue[Get_color8(rgbs[3*i + 2], maxval, brightness)]; } SDL_SetColors(surface, colors2, 0, 256); if (surface != unscaled_surface) SDL_SetColors(unscaled_surface, colors2, 0, 256); } /* * Rotate a range of colors. */ void Image_window8::rotate_colors ( int first, // Palette index of 1st. int num, // # in range. int upd // 1 to update hardware palette. ) { first *= 3; num *= 3; int cnt = num - 3; // Shift downward. unsigned char c0 = colors[first+num-3]; unsigned char c1 = colors[first+num-2]; unsigned char c2 = colors[first+num-1]; memmove(colors+first+3,colors+first,cnt); colors[first ] = c0; // Shift 1st to end. colors[first+1] = c1; // Shift 1st to end. colors[first+2] = c2; // Shift 1st to end. if (upd) // Take effect now? { SDL_Color colors2[256]; for (int i = 0; i < 256; i++) { colors2[i].r = colors[i*3]; colors2[i].g = colors[i*3+1]; colors2[i].b = colors[i*3+2]; } SDL_SetColors(surface, colors2, 0, 256); if (surface != unscaled_surface) SDL_SetColors(unscaled_surface, colors2, 0, 256); } } //a nearest-average-colour 1/3 scaler unsigned char* Image_window8::mini_screenshot() { int i; if (!surface) return 0; unsigned char* pixels = ibuf->get_bits(); int pitch = ibuf->get_line_width(); unsigned char* buf = new Uint8[96*60]; const int w = 3*96, h = 3*60; for (int y = 0; y < h; y+=3) for (int x = 0; x < w; x+=3) #if 0 buf[y*w/9 + x/3] = pixels[ pitch * (y + (get_height()-h)/2) + x + (get_width()-w)/2 ]; #else { //calculate average colour int r=0, g=0, b=0; for (i=0; i<3; i++) for (int j=0; j<3; j++) { r+=colors[0 + 3*pixels[ pitch * (j + y + (get_height()-h)/2) + i + x + (get_width()-w)/2 ]]; g+=colors[1 + 3*pixels[ pitch * (j + y + (get_height()-h)/2) + i + x + (get_width()-w)/2 ]]; b+=colors[2 + 3*pixels[ pitch * (j + y + (get_height()-h)/2) + i + x + (get_width()-w)/2 ]]; } r = r/9; g = g/9; b = b/9; //find nearest-colour in non-rotating palette int bestdist = INT_MAX, bestindex = -1; for (i=0; i<224; i++) { int dist = (colors[0+3*i]-r)*(colors[0+3*i]-r)+ (colors[1+3*i]-g)*(colors[1+3*i]-g)+ (colors[2+3*i]-b)*(colors[2+3*i]-b); if (dist < bestdist) { bestdist = dist; bestindex = i; } } buf[y*w/9 + x/3] = bestindex; } #endif return buf; } exult-1.2/imagewin/scale.h0000644000175000001440000000767607631060063011253 /** ** Scale.h - Trying to scale with bilinear interpolation. ** ** Written: 6/14/00 - JSF **/ #ifndef INCL_SCALE #define INCL_SCALE 1 // Scale 2x using 2xSaI template void Scale_2xSaI ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ); // Super Eagle Scaler template void Scale_SuperEagle ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ); // Super 2xSaI Scaler template void Scale_Super2xSaI ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ); //Scale X2 with bilinear interpolation. template void Scale_2xBilinear ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ); //Scale X2 with bilinear plus interpolation. template void Scale_2xBilinearPlus ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ); // Point Sampling Scaler void Scale_point ( const unsigned char *source, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels, // Pixels (words)/line for dest. const int factor // Scale factor ); // Interlaced Point Sampling Scaler void Scale_interlace ( const unsigned char *source, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels, // Pixels (words)/line for dest. const int factor // Scale factor ); void Scale2x_noblur ( const unsigned char *src1, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels // Pixels (words)/line for dest. ); #include "scale.cc" /* Seems to be needed. */ #endif exult-1.2/imagewin/scale.cc0000644000175000001440000012063310054030561011367 /** ** Scale.cc - Trying to scale with bilinear interpolation. ** ** Written: 6/14/00 - JSF **/ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_video.h" #ifndef ALPHA_LINUX_CXX # include #endif #include "exult_types.h" #ifndef UNDER_CE using std::memcpy; #endif /** ** 2xSaI scaling filter source code adapted for Exult ** August 29 2000, originally written in May 1999 ** by Derek Liauw Kie Fa (DerekL666@yahoo.com/D.A.K.L.LiauwKieFa@student.tudelft.nl) ** This source is made available under the terms of the GNU GPL ** I'd appreciate it I am given credit in the program or documentation **/ template inline Dest_pixel Interpolate_2xSaI (Source_pixel colorA, Source_pixel colorB, const Manip_pixels &manip) { unsigned int r0, r1, g0, g1, b0, b1; manip.split_source(colorA, r0, g0, b0); manip.split_source(colorB, r1, g1, b1); int r = (r0 + r1)>>1; int g = (g0 + g1)>>1; int b = (b0 + b1)>>1; return manip.rgb(r, g, b); } template inline Dest_pixel OInterpolate_2xSaI (Source_pixel colorA, Source_pixel colorB, Source_pixel colorC, const Manip_pixels &manip) { unsigned int r0, r1, g0, g1, b0, b1; unsigned int r2, g2, b2; manip.split_source(colorA, r0, g0, b0); manip.split_source(colorB, r1, g1, b1); manip.split_source(colorC, r2, g2, b2); unsigned int r = ((r0<<2) + (r0<<1) + r1 + r2)>>3; unsigned int g = ((g0<<2) + (g0<<1) + g1 + g2)>>3; unsigned int b = ((b0<<2) + (b0<<1) + b1 + b2)>>3; return manip.rgb(r, g, b); } template inline Dest_pixel QInterpolate_2xSaI (Source_pixel colorA, Source_pixel colorB, Source_pixel colorC, Source_pixel colorD, const Manip_pixels &manip) { unsigned int r0, r1, g0, g1, b0, b1; unsigned int r2, r3, g2, g3, b2, b3; manip.split_source(colorA, r0, g0, b0); manip.split_source(colorB, r1, g1, b1); manip.split_source(colorC, r2, g2, b2); manip.split_source(colorD, r3, g3, b3); unsigned int r = (r0 + r1 + r2 + r3)>>2; unsigned int g = (g0 + g1 + g2 + g3)>>2; unsigned int b = (b0 + b1 + b2 + b3)>>2; return manip.rgb(r, g, b); } template inline int GetResult1(Source_pixel A, Source_pixel B, Source_pixel C, Source_pixel D) { int x = 0; int y = 0; int r = 0; if (A == C) x+=1; else if (B == C) y+=1; if (A == D) x+=1; else if (B == D) y+=1; if (x <= 1) r+=1; if (y <= 1) r-=1; return r; } template inline int GetResult2(Source_pixel A, Source_pixel B, Source_pixel C, Source_pixel D) { int x = 0; int y = 0; int r = 0; if (A == C) x+=1; else if (B == C) y+=1; if (A == D) x+=1; else if (B == D) y+=1; if (x <= 1) r-=1; if (y <= 1) r+=1; return r; } // 2xSaI scaler template void Scale_2xSaI ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ) { Source_pixel *srcPtr = source + (srcx + srcy*sline_pixels); Dest_pixel *dstPtr = dest + (2*srcy*dline_pixels + 2*srcx); if (srcx + srcw >= sline_pixels) { srcw = sline_pixels - srcx; } // Init offset to prev. line, next 2. int prev1_yoff = srcy ? sline_pixels : 0; int next1_yoff = sline_pixels, next2_yoff = 2*sline_pixels; // Figure threshholds for counters. int ybeforelast = sheight - 2 - srcy; int xbeforelast = sline_pixels - 2 - srcx; for (int y = 0; y < srch; y++, prev1_yoff = sline_pixels) { if (y >= ybeforelast) // Last/next-to-last row? if (y == ybeforelast) next2_yoff = sline_pixels; else // Very last line? next2_yoff = next1_yoff = 0; Source_pixel *bP = srcPtr; Dest_pixel *dP = dstPtr; int prev1_xoff = srcx ? 1 : 0; int next1_xoff = 1, next2_xoff = 2; for (int x = 0; x < srcw; x++) { Source_pixel colorA, colorB; Source_pixel colorC, colorD, colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP; Dest_pixel product, product1, product2, orig; // Last/next-to-last row? if (x >= xbeforelast) if (x == xbeforelast) next2_xoff = 1; else next2_xoff = next1_xoff = 0; //--------------------------------------- // Map of the pixels: I|E F|J // G|A B|K // H|C D|L // M|N O|P colorI = *(bP- prev1_yoff - prev1_xoff); colorE = *(bP- prev1_yoff); colorF = *(bP- prev1_yoff + next1_xoff); colorJ = *(bP- prev1_yoff + next2_xoff); colorG = *(bP - prev1_xoff); colorA = *(bP); colorB = *(bP + next1_xoff); colorK = *(bP + next2_xoff); colorH = *(bP + next1_yoff - prev1_xoff); colorC = *(bP + next1_yoff); colorD = *(bP + next1_yoff + next1_xoff); colorL = *(bP + next1_yoff + next2_xoff); colorM = *(bP + next2_yoff - prev1_xoff); colorN = *(bP + next2_yoff); colorO = *(bP + next2_yoff + next1_xoff); colorP = *(bP + next2_yoff + next2_xoff); if ((colorA == colorD) && (colorB != colorC)) { if ( ((colorA == colorE) && (colorB == colorL)) || ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) ) { //product = colorA; manip.copy(product, colorA); } else { //product = INTERPOLATE(colorA, colorB); product = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, manip); } if (((colorA == colorG) && (colorC == colorO)) || ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) ) { //product1 = colorA; manip.copy(product1, colorA); } else { //product1 = INTERPOLATE(colorA, colorC); product1 = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorC, manip); } //product2 = colorA; manip.copy(product2, colorA); } else if ((colorB == colorC) && (colorA != colorD)) { if (((colorB == colorF) && (colorA == colorH)) || ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) ) { //product = colorB; manip.copy(product, colorB); } else { //product = INTERPOLATE(colorA, colorB); product = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, manip); } if (((colorC == colorH) && (colorA == colorF)) || ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) ) { //product1 = colorC; manip.copy(product1, colorC); } else { //product1 = INTERPOLATE(colorA, colorC); product1 = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorC, manip); } //product2 = colorB; manip.copy(product2, colorB); } else if ((colorA == colorD) && (colorB == colorC)) { if (colorA == colorB) { //product = colorA; manip.copy(product, colorA); //product1 = colorA; manip.copy(product1, colorA); //product2 = colorA; manip.copy(product2, colorA); } else { register int r = 0; //product1 = INTERPOLATE(colorA, colorC); product1 = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorC, manip); //product = INTERPOLATE(colorA, colorB); product = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, manip); r += GetResult1 (colorA, colorB, colorG, colorE); r += GetResult2 (colorB, colorA, colorK, colorF); r += GetResult2 (colorB, colorA, colorH, colorN); r += GetResult1 (colorA, colorB, colorL, colorO); if (r > 0) //product2 = colorA; manip.copy(product2, colorA); else if (r < 0) //product2 = colorB; manip.copy(product2, colorB); else { //product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); product2 = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, colorC, colorD, manip); } } } else { //product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); product2 = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, colorC, colorD, manip); if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) { //product = colorA; manip.copy(product, colorA); } else if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) { //product = colorB; manip.copy(product, colorB); } else { //product = INTERPOLATE(colorA, colorB); product = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorB, manip); } if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) { //product1 = colorA; manip.copy(product1, colorA); } else if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) { //product1 = colorC; manip.copy(product1, colorC); } else { //product1 = INTERPOLATE(colorA, colorC); product1 = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(colorA, colorC, manip); } } //product = colorA | (product << 16); //product1 = product1 | (product2 << 16); manip.copy(orig, colorA); *dP = orig; *(dP+1) = product; *(dP+dline_pixels) = product1; *(dP+dline_pixels+1) = product2; bP += 1; dP += 2; prev1_xoff = 1; }//end of for ( finish= width etc..) srcPtr += sline_pixels; dstPtr += 2*dline_pixels; prev1_yoff = 1; }; } template void Scale_Super2xSaI ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ) { Source_pixel *srcPtr = source + (srcx + srcy*sline_pixels); Dest_pixel *dstPtr = dest + (2*srcy*dline_pixels + 2*srcx); if (srcx + srcw >= sline_pixels) { srcw = sline_pixels - srcx; } int ybeforelast1 = sheight - 1 - srcy; int ybeforelast2 = sheight - 2 - srcy; int xbeforelast1 = sline_pixels - 1 - srcx; int xbeforelast2 = sline_pixels - 2 - srcx; for (int y = 0; y < srch; y++) { Source_pixel *bP = srcPtr; Dest_pixel *dP = dstPtr; for (int x = 0; x < srcw; x++) { Source_pixel color4, color5, color6; Source_pixel color1, color2, color3; Source_pixel colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; Dest_pixel product1a, product1b, product2a, product2b; //--------------------------------------- B0 B1 B2 B3 // 4 5 6 S2 // 1 2 3 S1 // A0 A1 A2 A3 //-------------------------------------- int add1, add2; int sub1; int nextl1, nextl2; int prevl1; if (x == 0) sub1 = 0; else sub1 = 1; if (x >= xbeforelast2) add2 = 0; else add2 = 1; if (x >= xbeforelast1) add1 = 0; else add1 = 1; if (y == 0) prevl1 = 0; else prevl1 = sline_pixels; if (y >= ybeforelast2) nextl2 = 0; else nextl2 = sline_pixels; if (y >= ybeforelast1) nextl1 = 0; else nextl1 = sline_pixels; colorB0 = *(bP- prevl1 - sub1); colorB1 = *(bP- prevl1); colorB2 = *(bP- prevl1 + add1); colorB3 = *(bP- prevl1 + add1 + add2); color4 = *(bP - sub1); color5 = *(bP); color6 = *(bP + add1); colorS2 = *(bP + add1 + add2); color1 = *(bP + nextl1 - sub1); color2 = *(bP + nextl1); color3 = *(bP + nextl1 + add1); colorS1 = *(bP + nextl1 + add1 + add2); colorA0 = *(bP + nextl1 + nextl2 - sub1); colorA1 = *(bP + nextl1 + nextl2); colorA2 = *(bP + nextl1 + nextl2 + add1); colorA3 = *(bP + nextl1 + nextl2 + add1 + add2); if (color2 == color6 && color5 != color3) { //product2b = product1b = color2; manip.copy(product2b, color2); product1b = product2b; } else if (color5 == color3 && color2 != color6) { //product2b = product1b = color5; manip.copy(product2b, color5); product1b = product2b; } else if (color5 == color3 && color2 == color6) { register int r = 0; //r += GetResult (color6, color5, color1, colorA1); //r += GetResult (color6, color5, color4, colorB1); //r += GetResult (color6, color5, colorA2, colorS1); //r += GetResult (color6, color5, colorB2, colorS2); r += GetResult1 (color5, color6, color4, colorB1); r += GetResult2 (color6, color5, colorA2, colorS1); r += GetResult2 (color6, color5, color1, colorA1); r += GetResult1 (color5, color6, colorB2, colorS2); if (r > 0) { //product2b = product1b = color6; manip.copy(product2b, color6); product1b = product2b; } else if (r < 0) { //product2b = product1b = color5; manip.copy(product2b, color5); product1b = product2b; } else { //product2b = product1b = INTERPOLATE (color5, color6); product1b = product2b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, manip); } } else { if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) //product2b = Q_INTERPOLATE (color3, color3, color3, color2); product2b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color3, color3, color3, color2, manip); else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) //product2b = Q_INTERPOLATE (color2, color2, color2, color3); product2b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color3, color2, color2, color2, manip); else //product2b = INTERPOLATE (color2, color3); product2b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color3, manip); if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) //product1b = Q_INTERPOLATE (color6, color6, color6, color5); product1b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, color6, color6, manip); else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) //product1b = Q_INTERPOLATE (color6, color5, color5, color5); product1b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color6, color5, color5, color5, manip); else //product1b = INTERPOLATE (color5, color6); product1b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, manip); } if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) //product2a = INTERPOLATE (color2, color5); product2a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color2, manip); else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) //product2a = INTERPOLATE(color2, color5); product2a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color2, manip); else //product2a = color2; manip.copy(product2a, color2); if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) //product1a = INTERPOLATE (color2, color5); product1a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color2, manip); else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) //product1a = INTERPOLATE(color2, color5); product1a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color2, manip); else //product1a = color5; manip.copy(product1a, color5); *dP = product1a; *(dP+1) = product1b; *(dP+dline_pixels) = product2a; *(dP+dline_pixels+1) = product2b; bP += 1; dP += 2; } srcPtr += sline_pixels; dstPtr += 2*dline_pixels; }; } template void Scale_SuperEagle ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ) { // Need to ensure that the update is alligned to 4 pixels - Colourless // The idea was to prevent artifacts from appearing, but it doesn't seem // to help /* { int sx = ((srcx-4)/4)*4; int ex = ((srcx+srcw+7)/4)*4; int sy = ((srcy-4)/4)*4; int ey = ((srcy+srch+7)/4)*4; if (sx < 0) sx = 0; if (sy < 0) sy = 0; if (ex > sline_pixels) ex = sline_pixels; if (ey > sheight) ey = sheight; srcx = sx; srcy = sy; srcw = ex - sx; srch = ey - sy; } */ Source_pixel *srcPtr = source + (srcx + srcy*sline_pixels); Dest_pixel *dstPtr = dest + (2*srcy*dline_pixels + 2*srcx); if (srcx + srcw >= sline_pixels) { srcw = sline_pixels - srcx; } int ybeforelast1 = sheight - 1 - srcy; int ybeforelast2 = sheight - 2 - srcy; int xbeforelast1 = sline_pixels - 1 - srcx; int xbeforelast2 = sline_pixels - 2 - srcx; for (int y = 0; y < srch; y++) { Source_pixel *bP = srcPtr; Dest_pixel *dP = dstPtr; for (int x = 0; x < srcw; x++) { Source_pixel color4, color5, color6; Source_pixel color1, color2, color3; Source_pixel colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; Dest_pixel product1a, product1b, product2a, product2b; //--------------------------------------- B0 B1 B2 B3 // 4 5 6 S2 // 1 2 3 S1 // A0 A1 A2 A3 //-------------------------------------- int add1, add2; int sub1; int nextl1, nextl2; int prevl1; if (x == 0) sub1 = 0; else sub1 = 1; if (x >= xbeforelast2) add2 = 0; else add2 = 1; if (x >= xbeforelast1) add1 = 0; else add1 = 1; if (y == 0) prevl1 = 0; else prevl1 = sline_pixels; if (y >= ybeforelast2) nextl2 = 0; else nextl2 = sline_pixels; if (y >= ybeforelast1) nextl1 = 0; else nextl1 = sline_pixels; colorB0 = *(bP- prevl1 - sub1); colorB1 = *(bP- prevl1); colorB2 = *(bP- prevl1 + add1); colorB3 = *(bP- prevl1 + add1 + add2); color4 = *(bP - sub1); color5 = *(bP); color6 = *(bP + add1); colorS2 = *(bP + add1 + add2); color1 = *(bP + nextl1 - sub1); color2 = *(bP + nextl1); color3 = *(bP + nextl1 + add1); colorS1 = *(bP + nextl1 + add1 + add2); colorA0 = *(bP + nextl1 + nextl2 - sub1); colorA1 = *(bP + nextl1 + nextl2); colorA2 = *(bP + nextl1 + nextl2 + add1); colorA3 = *(bP + nextl1 + nextl2 + add1 + add2); if (color2 == color6 && color5 != color3) { //product1b = product2a = color2; manip.copy(product2a, color2); product1b = product2a; if ((color1 == color2) || (color6 == colorB2)) { //product1a = INTERPOLATE (color2, color5); //product1a = INTERPOLATE (color2, product1a); product1a = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color2, color2, color5, manip); } else { //product1a = INTERPOLATE (color5, color6); product1a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color6, color5, manip); } if ((color6 == colorS2) || (color2 == colorA1)) { //product2b = INTERPOLATE (color2, color3); //product2b = INTERPOLATE (color2, product2b); product2b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color2, color2, color3, manip); } else { //product2b = INTERPOLATE (color2, color3); product2b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color3, manip); } } else if (color5 == color3 && color2 != color6) { //product2b = product1a = color5; manip.copy(product1a, color5); product2b = product1a; if ((colorB1 == color5) || (color3 == colorS1)) { //product1b = INTERPOLATE (color5, color6); //product1b = INTERPOLATE (color5, product1b); product1b = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color5, color5, color6, manip); } else { //product1b = INTERPOLATE (color5, color6); product1b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, manip); } if ((color3 == colorA2) || (color4 == color5)) { //product2a = INTERPOLATE (color5, color2); //product2a = INTERPOLATE (color5, product2a); product2a = QInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color5, color5, color5, manip); } else { //product2a = INTERPOLATE (color2, color3); product2a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color3, color2, manip); } } else if (color5 == color3 && color2 == color6) { register int r = 0; //r += GetResult (color6, color5, color1, colorA1); //r += GetResult (color6, color5, color4, colorB1); //r += GetResult (color6, color5, colorA2, colorS1); //r += GetResult (color6, color5, colorB2, colorS2); r += GetResult1 (color5, color6, color4, colorB1); r += GetResult2 (color6, color5, colorA2, colorS1); r += GetResult2 (color6, color5, color1, colorA1); r += GetResult1 (color5, color6, colorB2, colorS2); if (r > 0) { //product1b = product2a = color2; manip.copy(product2a, color2); product1b = product2a; //product1a = product2b = INTERPOLATE (color5, color6); product1a = product2b = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, manip); } else if (r < 0) { //product2b = product1a = color5; manip.copy(product1a, color5); product2b = product1a; //product1b = product2a = INTERPOLATE (color5, color6); product1b = product2a = Interpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, manip); } else { //product2b = product1a = color5; manip.copy(product1a, color5); product2b = product1a; //product1b = product2a = color2; manip.copy(product2a, color2); product1b = product2a; } } else { //product2b = product1a = INTERPOLATE (color2, color6); //product2b = Q_INTERPOLATE (color3, color3, color3, product2b); //product1a = Q_INTERPOLATE (color5, color5, color5, product1a); product2b = OInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color3, color2, color6, manip); product1a = OInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color5, color6, color2, manip); //product2a = product1b = INTERPOLATE (color5, color3); //product2a = Q_INTERPOLATE (color2, color2, color2, product2a); //product1b = Q_INTERPOLATE (color6, color6, color6, product1b); product2a = OInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color2, color5, color3, manip); product1b = OInterpolate_2xSaI< Source_pixel, Dest_pixel, Manip_pixels>(color6, color5, color3, manip); } *dP = product1a; *(dP+1) = product1b; *(dP+dline_pixels) = product2a; *(dP+dline_pixels+1) = product2b; bP += 1; dP += 2; } srcPtr += sline_pixels; dstPtr += 2*dline_pixels; }; } /** ** End of 2xSaI code **/ typedef unsigned int COMPONENT; // fill `row' with the the disassembled color components from the original // pixel values in `from'; if we run out of source pixels, just keep copying // the last one we got template inline void fill_rgb_row ( Source_pixel *from, int src_width, // number of pixels to read from 'from' COMPONENT *row, int width, // number of pixels to write into 'row' const Manip_pixels& manip ) { COMPONENT *copy_start = row + src_width*3; COMPONENT *all_stop = row + width*3; while (row < copy_start) { COMPONENT& r = *row++; COMPONENT& g = *row++; COMPONENT& b = *row++; manip.split_source(*from++, r, g, b); } // any remaining elements to be written to 'row' are a replica of the // preceding pixel COMPONENT *p = row-3; while (row < all_stop) { // we're guaranteed three elements per pixel; could unroll the loop // further, especially with a Duff's Device, but the gains would be // probably limited (judging by profiler output) *row++ = *p++; *row++ = *p++; *row++ = *p++; } } template void Scale_2xBilinear ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ) { Source_pixel *from = source + srcy*sline_pixels + srcx; Dest_pixel *to = dest + 2*srcy*dline_pixels + 2*srcx; Dest_pixel *to_odd = to + dline_pixels; // the following are static because we don't want to be freeing and // reallocating space on each call, as malloc()s are usually very // expensive; we do allow it to grow though static unsigned buff_size = 0; static COMPONENT *rgb_row_cur = 0; static COMPONENT *rgb_row_next = 0; if (buff_size < sline_pixels+1) { delete [] rgb_row_cur; delete [] rgb_row_next; buff_size = sline_pixels+1; rgb_row_cur = new COMPONENT[buff_size*3]; rgb_row_next = new COMPONENT[buff_size*3]; } int from_width = sline_pixels - srcx; if (srcw+1 < from_width) from_width = srcw+1; fill_rgb_row(from, from_width, rgb_row_cur, srcw+1, manip); for (unsigned y=0; y < srch; y++) { Source_pixel *from_orig = from; Dest_pixel *to_orig = to; if (y+1 < sheight) fill_rgb_row(from+sline_pixels, from_width, rgb_row_next, srcw+1, manip); else fill_rgb_row(from, from_width, rgb_row_next, srcw+1, manip); // every pixel in the src region, is extended to 4 pixels in the // destination, arranged in a square 'quad'; if the current src // pixel is 'a', then in what follows 'b' is the src pixel to the // right, 'c' is the src pixel below, and 'd' is the src pixel to // the right and down COMPONENT *cur_row = rgb_row_cur; COMPONENT *next_row = rgb_row_next; COMPONENT *ar = cur_row++; COMPONENT *ag = cur_row++; COMPONENT *ab = cur_row++; COMPONENT *cr = next_row++; COMPONENT *cg = next_row++; COMPONENT *cb = next_row++; for (unsigned x=0; x < srcw; x++) { COMPONENT *br = cur_row++; COMPONENT *bg = cur_row++; COMPONENT *bb = cur_row++; COMPONENT *dr = next_row++; COMPONENT *dg = next_row++; COMPONENT *db = next_row++; // upper left pixel in quad: just copy it in *to++ = manip.rgb(*ar, *ag, *ab); // upper right *to++ = manip.rgb((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); // lower left *to_odd++ = manip.rgb((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); // lower right *to_odd++ = manip.rgb((*ar+*br+*cr+*dr)>>2, (*ag+*bg+*cg+*dg)>>2, (*ab+*bb+*cb+*db)>>2); // 'b' becomes 'a', 'd' becomes 'c' ar = br; ag = bg; ab = bb; cr = dr; cg = dg; cb = db; } // the "next" rgb row becomes the current; the old current rgb row is // recycled and serves as the new "next" row COMPONENT *temp; temp = rgb_row_cur; rgb_row_cur = rgb_row_next; rgb_row_next = temp; // update the pointers for start of next pair of lines from = from_orig + sline_pixels; to = to_orig + 2*dline_pixels; to_odd = to + dline_pixels; } } template void Scale_2xBilinearPlus ( Source_pixel *source, // ->source pixels. int srcx, int srcy, // Start of rectangle within src. int srcw, int srch, // Dims. of rectangle. int sline_pixels, // Pixels (words)/line for source. int sheight, // Source height. Dest_pixel *dest, // ->dest pixels. int dline_pixels, // Pixels (words)/line for dest. const Manip_pixels& manip // Manipulator methods. ) { Source_pixel *from = source + srcy*sline_pixels + srcx; Dest_pixel *to = dest + 2*srcy*dline_pixels + 2*srcx; Dest_pixel *to_odd = to + dline_pixels; // the following are static because we don't want to be freeing and // reallocating space on each call, as malloc()s are usually very // expensive; we do allow it to grow though static unsigned buff_size = 0; static COMPONENT *rgb_row_cur = 0; static COMPONENT *rgb_row_next = 0; if (buff_size < sline_pixels+1) { delete [] rgb_row_cur; delete [] rgb_row_next; buff_size = sline_pixels+1; rgb_row_cur = new COMPONENT[buff_size*3]; rgb_row_next = new COMPONENT[buff_size*3]; } int from_width = sline_pixels - srcx; if (srcw+1 < from_width) from_width = srcw+1; fill_rgb_row(from, from_width, rgb_row_cur, srcw+1, manip); for (unsigned y=0; y < srch; y++) { Source_pixel *from_orig = from; Dest_pixel *to_orig = to; if (y+1 < sheight) fill_rgb_row(from+sline_pixels, from_width, rgb_row_next, srcw+1, manip); else fill_rgb_row(from, from_width, rgb_row_next, srcw+1, manip); // every pixel in the src region, is extended to 4 pixels in the // destination, arranged in a square 'quad'; if the current src // pixel is 'a', then in what follows 'b' is the src pixel to the // right, 'c' is the src pixel below, and 'd' is the src pixel to // the right and down COMPONENT *cur_row = rgb_row_cur; COMPONENT *next_row = rgb_row_next; COMPONENT *ar = cur_row++; COMPONENT *ag = cur_row++; COMPONENT *ab = cur_row++; COMPONENT *cr = next_row++; COMPONENT *cg = next_row++; COMPONENT *cb = next_row++; for (unsigned x=0; x < srcw; x++) { COMPONENT *br = cur_row++; COMPONENT *bg = cur_row++; COMPONENT *bb = cur_row++; COMPONENT *dr = next_row++; COMPONENT *dg = next_row++; COMPONENT *db = next_row++; // upper left pixel in quad: just copy it in //*to++ = manip.rgb(*ar, *ag, *ab); #ifdef USE_ORIGINAL_BILINEAR_PLUS *to++ = manip.rgb( (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3, (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3, (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3); #else *to++ = manip.rgb( (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4, (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4, (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4); #endif // upper right *to++ = manip.rgb((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); // lower left *to_odd++ = manip.rgb((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); // lower right *to_odd++ = manip.rgb((*ar+*br+*cr+*dr)>>2, (*ag+*bg+*cg+*dg)>>2, (*ab+*bb+*cb+*db)>>2); // 'b' becomes 'a', 'd' becomes 'c' ar = br; ag = bg; ab = bb; cr = dr; cg = dg; cb = db; } // the "next" rgb row becomes the current; the old current rgb row is // recycled and serves as the new "next" row COMPONENT *temp; temp = rgb_row_cur; rgb_row_cur = rgb_row_next; rgb_row_next = temp; // update the pointers for start of next pair of lines from = from_orig + sline_pixels; to = to_orig + 2*dline_pixels; to_odd = to + dline_pixels; } } #if 0 /* Testing */ void test() { unsigned short *src, *dest; Manip16to16 manip; Scale2x (src, 20, 40, dest, manip); unsigned char *src8; Manip8to16 manip8(0); // ++++DOn't try to run this! Scale2x (src8, 20, 40, dest, manip8); } #endif // // Point Sampling Scaler // void Scale_point ( const unsigned char *source, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels, // Pixels (words)/line for dest. const int factor // Scale factor ) { source += srcy*sline_pixels + srcx; dest += srcy*factor*dline_pixels + srcx*factor; char data; unsigned char *dest2; const unsigned char *source2; const unsigned char * limit_y = source + srch*sline_pixels; const unsigned char * limit_x = source + srcw; if (factor == 2) { uint16 *dest16; uint16 *dest16_2; uint16 data16; while (source < limit_y) { source2 = source; dest16 = (uint16*) dest; dest += dline_pixels; dest16_2 = (uint16*) dest; while (source2 < limit_x) { data16 = *source2++; data16 |= data16 << 8; *dest16++ = data16; *dest16_2++ = data16; } dest += dline_pixels; limit_x += sline_pixels; source += sline_pixels; } } else { const unsigned int y2_pixels = dline_pixels*factor; const unsigned char * limit_y2 = dest; const unsigned char * limit_x2; while (source < limit_y) { limit_y2 += y2_pixels; while (dest < limit_y2) { limit_x2 = dest2 = dest; source2 = source; while (source2 < limit_x) { data = *source2++; limit_x2 += factor; while (dest2 < limit_x2) *dest2++ = data; } dest += dline_pixels; } limit_x += sline_pixels; source += sline_pixels; } } } // // Interlaced Point Sampling Scaler // void Scale_interlace ( const unsigned char *source, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels, // Pixels (words)/line for dest. const int factor // Scale factor ) { source += srcy*sline_pixels + srcx; dest += srcy*factor*dline_pixels + srcx*factor; char data; unsigned char *dest2; const unsigned char *source2; const unsigned char * limit_y = source + srch*sline_pixels; const unsigned char * limit_x = source + srcw; if (factor == 2) { uint16 *dest16; uint16 data16; while (source < limit_y) { source2 = source; dest16 = (uint16*) dest; while (source2 < limit_x) { data16 = *source2++; data16 |= data16 << 8; *dest16++ = data16; } dest += dline_pixels; dest += dline_pixels; limit_x += sline_pixels; source += sline_pixels; } } else { bool visible_line = ((srcy * factor) % 2 == 0); const unsigned int y2_pixels = dline_pixels*factor; const unsigned char * limit_y2 = dest; const unsigned char * limit_x2; while (source < limit_y) { limit_y2 += y2_pixels; while (dest < limit_y2) { if (visible_line) { limit_x2 = dest2 = dest; source2 = source; while (source2 < limit_x) { data = *source2++; limit_x2 += factor; while (dest2 < limit_x2) *dest2++ = data; } } dest += dline_pixels; visible_line = !visible_line; } limit_x += sline_pixels; source += sline_pixels; } } } // // Scale2X algorithm by Andrea Mazzoleni. // /* This file is part of the Scale2x project. * * Copyright (C) 2001-2002 Andrea Mazzoleni * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ void Scale2x_noblur ( const unsigned char *src, // ->source pixels. const int srcx, const int srcy, // Start of rectangle within src. const int srcw, const int srch, // Dims. of rectangle. const int sline_pixels, // Pixels (words)/line for source. const int sheight, // Source height. unsigned char *dest, // ->dest pixels. const int dline_pixels // Pixels (words)/line for dest. ) { dest += srcy*2*dline_pixels + srcx*2; unsigned char *dest0 = dest, *dest1 = dest + dline_pixels; // ->current row. const unsigned char *src1 = src + srcy*sline_pixels + srcx; const unsigned char *src0 = src1 - sline_pixels; // ->prev. row. const unsigned char *src2 = src1 + sline_pixels; // ->next row. const unsigned char * limit_y = src1 + srch*sline_pixels; const unsigned char * limit_x = src1 + srcw; // Very end of source surface: const unsigned char * end_src = src + sheight*sline_pixels; if (src0 < src) src0 = src1; // Don't go before row 0. if (srcx + srcw == sline_pixels) // Going to right edge? limit_x--; // Stop 1 pixel before it. while (src1 < limit_y) { if (src2 > end_src) src2 = src1; // On last row. if (srcx == 0) // First pixel. { dest0[0] = dest1[0] = src1[0]; if (src1[1] == src0[0] && src2[0] != src0[0]) dest0[1] = src0[0]; else dest0[1] = src1[0]; if (src1[1] == src2[0] && src0[0] != src2[0]) dest1[1] = src2[0]; else dest1[1] = src1[0]; ++src0; ++src1; ++src2; dest0 += 2; dest1 += 2; } // Middle pixels. while (src1 < limit_x) { if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) dest0[0] = src0[0]; else dest0[0] = src1[0]; if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) dest0[1] = src0[0]; else dest0[1] = src1[0]; if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) dest1[0] = src2[0]; else dest1[0] = src1[0]; if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) dest1[1] = src2[0]; else dest1[1] = src1[0]; ++src0; ++src1; ++src2; dest0 += 2; dest1 += 2; } if (srcx + srcw == sline_pixels) { // End pixel in row. if (src1[-1] == src0[0] && src2[0] != src0[0]) dest0[0] = src0[0]; else dest0[0] = src1[0]; if (src1[-1] == src2[0] && src0[0] != src2[0]) dest1[0] = src2[0]; else dest1[0] = src1[0]; dest0[1] = src1[0]; dest1[1] = src1[0]; ++src0; ++src1; ++src2; dest0 += 2; dest1 += 2; } src0 += sline_pixels - srcw; src1 += sline_pixels - srcw; src2 += sline_pixels - srcw; dest1 += dline_pixels - 2*srcw; if (src0 == src1) // End of first row? src0 -= sline_pixels; limit_x += sline_pixels; dest0 = dest1; dest1 += dline_pixels; } } exult-1.2/imagewin/ibuf16.h0000644000175000001440000001063207724430452011250 /* * ibuf16.h - 16-bit image buffer. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_IBUF16 #define INCL_IBUF16 1 #include "imagebuf.h" /* * A 16-bit image buffer: */ class Image_buffer16 : public Image_buffer { unsigned short *palette; // Palette for 8-bit graphics. void create_default_palette(); unsigned short *get_pixels() // Cast bits. { return (unsigned short *) bits; } public: Image_buffer16(unsigned int w, unsigned int h, int dpth) : Image_buffer(w, h, dpth), palette(0) { create_default_palette(); bits = new unsigned char[w*h*2]; } ~Image_buffer16() { delete palette; } // Create pixel from r,g,b values. unsigned short rgb(unsigned short r, unsigned short g, unsigned short b) { return ((r&0x1f) << 11) + ((g&0x1f) << 6) + (b&0x1f); } // Set a palette color. void set_palette_color(unsigned char num, unsigned short r, unsigned short g, unsigned short b) { palette[num] = rgb(r, g, b); } // Set palette. void set_palette(unsigned char *rgbs, int maxval, int brightness = 100); // Rotate palette colors. void rotate_colors(int first, int num, int upd); /* * 16-bit color methods. */ // Fill with given pixel. virtual void fill16(unsigned short pix); // Fill rect. wth pixel. virtual void fill16(unsigned short pix, int srcw, int srch, int destx, int desty); // Fill line with pixel. virtual void fill_line16(unsigned short pix, int srcw, int destx, int desty); // Copy rectangle into here. virtual void copy16(unsigned short *src_pixels, int srcw, int srch, int destx, int desty); /* * Depth-independent methods: */ virtual Image_buffer *create_another(int w, int h) { return new Image_buffer16(w, h, depth); } // Copy within itself. virtual void copy(int srcx, int srcy, int srcw, int srch, int destx, int desty); // Get rect. into another buf. virtual void get(Image_buffer *dest, int srcx, int srcy); // Put rect. back. virtual void put(Image_buffer *src, int destx, int desty); virtual void fill_static(int black, int gray, int white); /* * 8-bit color methods: */ // Fill with given (8-bit) value. virtual void fill8(unsigned char val) { Image_buffer16::fill16(palette[val]); } // Fill rect. wth pixel. virtual void fill8(unsigned char val, int srcw, int srch, int destx, int desty) { Image_buffer16::fill16( palette[val], srcw, srch, destx, desty); } // Fill line with pixel. virtual void fill_line8(unsigned char val, int srcw, int destx, int desty) { Image_buffer16::fill_line16(palette[val], srcw, destx, desty); } // Copy rectangle into here. virtual void copy8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty); // Copy line to here. virtual void copy_line8(unsigned char *src_pixels, int srcw, int destx, int desty); // Copy with translucency table. virtual void copy_line_translucent8( unsigned char *src_pixels, int srcw, int destx, int desty, int first_translucent, int last_translucent, Xform_palette *xforms) { copy_line8(src_pixels, srcw, destx, desty); } // Apply translucency to a line. virtual void fill_line_translucent8(unsigned char val, int srcw, int destx, int desty, Xform_palette& xform) { fill_line8(val, srcw, destx, desty); } // Apply translucency to a rectangle virtual void fill_translucent8(unsigned char val, int srcw, int srch, int destx, int desty, Xform_palette& xform) { fill8(val, srcw, srcw, destx, desty); } // Copy rect. with transp. color. virtual void copy_transparent8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty); }; #endif exult-1.2/imagewin/ibuf8.cc0000644000175000001440000003335610026506335011330 /* * ibuf8.cc - 8-bit image buffer. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ibuf8.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #include "exult_types.h" #include "utils.h" using std::cerr; using std::endl; /* * Copy an area of the image within itself. */ void Image_buffer8::copy ( int srcx, int srcy, // Where to start. int srcw, int srch, // Dimensions to copy. int destx, int desty // Where to copy to. ) { int ynext, yfrom, yto; // Figure y stuff. if (srcy >= desty) // Moving up? { ynext = line_width; yfrom = srcy; yto = desty; } else // Moving down. { ynext = -line_width; yfrom = srcy + srch - 1; yto = desty + srch - 1; } unsigned char *to = bits + yto*line_width + destx; unsigned char *from = bits + yfrom*line_width + srcx; // Go through lines. while (srch--) { std::memmove((char *) to, (char *) from, srcw); to += ynext; from += ynext; } } /* * Get a rectangle from here into another Image_buffer. */ void Image_buffer8::get ( Image_buffer *dest, // Copy to here. int srcx, int srcy // Upper-left corner of source rect. ) { int srcw = dest->width, srch = dest->height; int destx = 0, desty = 0; // Constrain to window's space. (Note // convoluted use of clip().) if (!clip(destx, desty, srcw, srch, srcx, srcy)) return; unsigned char *to = (unsigned char *) dest->bits + desty*dest->line_width + destx; unsigned char *from = (unsigned char *) bits + srcy*line_width + srcx; // Figure # pixels to next line. int to_next = dest->line_width - srcw; int from_next = line_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *to++ = *from++; to += to_next; from += from_next; } } /* * Retrieve data from another buffer. */ void Image_buffer8::put ( Image_buffer *src, // Copy from here. int destx, int desty // Copy to here. ) { Image_buffer8::copy8((unsigned char *) src->bits, src->get_width(), src->get_height(), destx, desty); } /* * Fill buffer with random static */ void Image_buffer8::fill_static(int black, int gray, int white) { unsigned char *p = bits; for (int i = width*height; i > 0; --i) { switch (std::rand()%5) { case 0: case 1: *p++ = black; break; case 2: case 3: *p++ = gray; break; case 4: *p++ = white; break; } } } /* * Fill with a given 8-bit value. */ void Image_buffer8::fill8 ( unsigned char pix ) { unsigned char *pixels = bits; int cnt = line_width*height; for (int i = 0; i < cnt; i++) *pixels++ = pix; } /* * Fill a rectangle with an 8-bit value. */ void Image_buffer8::fill8 ( unsigned char pix, int srcw, int srch, int destx, int desty ) { int srcx = 0, srcy = 0; // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned char *pixels = (unsigned char *) bits + desty*line_width + destx; int to_next = line_width - srcw;// # pixels to next line. while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *pixels++ = pix; pixels += to_next; // Get to start of next line. } } /* * Fill a line with a given 8-bit value. */ void Image_buffer8::fill_line8 ( unsigned char pix, int srcw, int destx, int desty ) { int srcx = 0; // Constrain to window's space. if (!clip_x(srcx, srcw, destx, desty)) return; unsigned char *pixels = (unsigned char *) bits + desty*line_width + destx; std::memset(pixels, pix, srcw); } /* * Copy another rectangle into this one. */ void Image_buffer8::copy8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, int srch, // Dimensions of source. int destx, int desty ) { if (!src_pixels) { cerr << "WTF! src_pixels in Image_buffer8::copy8 was 0!" << endl; return; } int srcx = 0, srcy = 0; int src_width = srcw; // Save full source width. // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; #if !(defined(__sparc__) || defined(__zaurus__)) uint32 *to = (uint32*) (bits + desty*line_width + destx); uint32 *from = (uint32*) (src_pixels + srcy*src_width + srcx); int to_next = line_width - srcw;// # pixels to next line. int from_next = src_width - srcw; // Need to know if we end dword alligned int end_align = srcw%4; // The actual aligned width in dwords int aligned = srcw/4; uint8 *to8; uint8 *from8; while (srch--) // Do each line. { int counter = aligned; while (counter--) *to++ = *from++; to8 = (uint8*) to; from8 = (uint8*) from; counter = end_align; while (counter--) *to8++ = *from8++; to = (uint32*) (to8+to_next); from = (uint32*) (from8+from_next); } #else uint8 *to = bits + desty*line_width + destx; uint8 *from = src_pixels + srcy*src_width + srcx; while (srch--) { std::memcpy(to, from, srcw); from += src_width; to += line_width; } #endif } /* * Copy a line into this buffer. */ void Image_buffer8::copy_line8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, // Width to copy. int destx, int desty ) { int srcx = 0; // Constrain to window's space. if (!clip_x(srcx, srcw, destx, desty)) return; unsigned char *to = bits + desty*line_width + destx; unsigned char *from = src_pixels + srcx; std::memcpy(to, from, srcw); } /* * Copy a line into this buffer where some of the colors are translucent. */ void Image_buffer8::copy_line_translucent8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, // Width to copy. int destx, int desty, int first_translucent, // Palette index of 1st trans. color. int last_translucent, // Index of last trans. color. Xform_palette *xforms // Transformers. Need same # as // (last_translucent - // first_translucent + 1). ) { int srcx = 0; // Constrain to window's space. if (!clip_x(srcx, srcw, destx, desty)) return; unsigned char *to = (unsigned char *) bits + desty*line_width + destx; unsigned char *from = src_pixels + srcx; for (int i = srcw; i; i--) { // Get char., and transform. unsigned char c = *from++; if (c >= first_translucent && c <= last_translucent) // Use table to shift existing pixel. c = xforms[c - first_translucent][*to]; *to++ = c; } } /* * Apply a translucency table to a line. */ void Image_buffer8::fill_line_translucent8 ( unsigned char val, // Ignored for this method. int srcw, int destx, int desty, Xform_palette& xform // Transform table. ) { int srcx = 0; // Constrain to window's space. if (!clip_x(srcx, srcw, destx, desty)) return; unsigned char *pixels = (unsigned char *) bits + desty*line_width + destx; while (srcw--) { *pixels = xform[*pixels]; pixels++; } } /* * Apply a translucency table to a rectangle. */ void Image_buffer8::fill_translucent8 ( unsigned char /* val */, // Not used. int srcw, int srch, int destx, int desty, Xform_palette& xform // Transform table. ) { int srcx = 0, srcy = 0; // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned char *pixels = (unsigned char *) bits + desty*line_width + destx; int to_next = line_width - srcw;// # pixels to next line. while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--, pixels++) *pixels = xform[*pixels]; pixels += to_next; // Get to start of next line. } } /* * Copy another rectangle into this one, with 0 being the transparent * color. */ void Image_buffer8::copy_transparent8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, int srch, // Dimensions of source. int destx, int desty ) { int srcx = 0, srcy = 0; int src_width = srcw; // Save full source width. // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned char *to = bits + desty*line_width + destx; unsigned char *from = src_pixels + srcy*src_width + srcx; int to_next = line_width - srcw;// # pixels to next line. int from_next = src_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--, to++) { register int chr = *from++; if (chr) *to = chr; } to += to_next; from += from_next; } } // Slightly Optimized RLE Painter void Image_buffer8::paint_rle (int xoff, int yoff, unsigned char *inptr) { uint8* in = inptr; int scanlen; const int right = clipx+clipw; const int bottom = clipy+cliph; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; int scanx = xoff + (sint16) Read2(in); int scany = yoff + (sint16) Read2(in); // Is there somthing on screen? bool on_screen = true; if (scanx >= right || scany >= bottom || scany < clipy || scanx+scanlen < clipx) on_screen = false; if (!encoded) // Raw data? { // Only do the complex calcs if we think it could be on screen if (on_screen) { // Do we need to skip pixels at the start? if (scanx < clipx) { const int delta = clipx-scanx; in += delta; scanlen -= delta; scanx = clipx; } // Do we need to skip pixels at the end? int skip = scanx+scanlen - right; if (skip < 0) skip = 0; // Is there anything to put on the screen? if (skip < scanlen) { unsigned char *dest = bits + scany*line_width + scanx; unsigned char *end = in+scanlen-skip; while (in < end) *dest++ = *in++; in += skip; continue; } } in += scanlen; continue; } else // Encoded { unsigned char *dest = bits + scany*line_width + scanx; while (scanlen) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. // Only do the complex calcs if we think it could be on screen if (on_screen && scanx < right && scanx+bcnt > clipx) { if (repeat) // Const Colour { // Do we need to skip pixels at the start? if (scanx < clipx) { const int delta = clipx-scanx; dest += delta; bcnt -= delta; scanlen -= delta; scanx = clipx; } // Do we need to skip pixels at the end? int skip = scanx+bcnt - right; if (skip < 0) skip = 0; // Is there anything to put on the screen? if (skip < bcnt) { unsigned char col = *in++; unsigned char *end = dest+bcnt-skip; while (dest < end) *dest++ = col; // dest += skip; - Don't need it scanx += bcnt; scanlen -= bcnt; continue; } // Make sure all the required values get // properly updated // dest += bcnt; - Don't need it scanx += bcnt; scanlen -= bcnt; ++in; continue; } else { // Do we need to skip pixels at the start? if (scanx < clipx) { const int delta = clipx-scanx; dest += delta; in += delta; bcnt -= delta; scanlen -= delta; scanx = clipx; } // Do we need to skip pixels at the end? int skip = scanx+bcnt - right; if (skip < 0) skip = 0; // Is there anything to put on the screen? if (skip < bcnt) { unsigned char *end = dest+bcnt-skip; while (dest < end) *dest++ = *in++; // dest += skip; - Don't need it in += skip; scanx += bcnt; scanlen -= bcnt; continue; } // Make sure all the required values get // properly updated // dest += skip; - Don't need it scanx += bcnt; scanlen -= bcnt; in += bcnt; continue; } } // Make sure all the required values get // properly updated dest += bcnt; scanx += bcnt; scanlen -= bcnt; if (!repeat) in += bcnt; else ++in; continue; } } } } /* * Convert this image to 32-bit RGBA and return the allocated buffer. */ unsigned char *Image_buffer8::rgba ( unsigned char *pal, // 3*256 bytes (rgbrgbrgb...). unsigned char transp, // Transparent value. int first_translucent, // Palette index of 1st trans. color. int last_translucent, // Index of last trans. color. Xform_palette *xforms // Transformers. Need same # as // (last_translucent - // first_translucent + 1). ) { int cnt = line_width*height; // Allocate destination buffer. uint32 *buf32 = new uint32[cnt]; uint32 *ptr32 = buf32; unsigned char *pixels = bits; for (int i = 0; i < cnt; i++) { unsigned char pix = *pixels++; if (pix == transp) // Transparent? Store Alpha=0. { *ptr32++ = 0; continue; } unsigned char r,g,b,a; // Pieces of the color. if (pix >= first_translucent && pix <= last_translucent) { // Get actual color & alpha from tbl. Xform_palette& xf = xforms[pix - first_translucent]; r = xf.r; g = xf.g; b = xf.b; a = xf.a; } else { r = pal[3*pix]; g = pal[3*pix+1]; b = pal[3*pix + 2]; a = 255; } *ptr32++ = (static_cast(r)<<0) + (static_cast(g) << 8) + (static_cast(b) << 16) + (static_cast(a) << 24); } return reinterpret_cast(buf32); } exult-1.2/imagewin/savepcx.cc0000644000175000001440000001550710054030561011754 /* Copyright (C) 2000 Willem Jan Palenstijn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* A large part of this code is from the GIMP's PCX plugin: "This code is based in parts on code by Francisco Bustamante, but the largest portion of the code has been rewritten and is now maintained occasionally by Nick Lamb njl195@zepler.org.uk." It has been partly rewritten to use an SDL surface as input. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "SDL_video.h" #include "SDL_endian.h" #include #ifndef UNDER_CE using std::cout; using std::endl; using std::free; using std::malloc; #endif #if SDL_BYTEORDER == SDL_LIL_ENDIAN #define qtohl(x) (x) #define qtohs(x) (x) #else #define qtohl(x) \ ((Uint32)((((Uint32)(x) & 0x000000ffU) << 24) | \ (((Uint32)(x) & 0x0000ff00U) << 8) | \ (((Uint32)(x) & 0x00ff0000U) >> 8) | \ (((Uint32)(x) & 0xff000000U) >> 24))) #define qtohs(x) \ ((Uint16)((((Uint16)(x) & 0x00ff) << 8) | \ (((Uint16)(x) & 0xff00) >> 8))) #endif #define htoql(x) qtohl(x) #define htoqs(x) qtohs(x) typedef struct PCX_Header { Uint8 manufacturer; Uint8 version; Uint8 compression; Uint8 bpp; Sint16 x1, y1; Sint16 x2, y2; Sint16 hdpi; Sint16 vdpi; Uint8 colormap[48]; Uint8 reserved; Uint8 planes; Sint16 bytesperline; Sint16 color; Uint8 filler[58]; } PCX_Header; static void writeline (SDL_RWops *dst, Uint8* buffer, int bytes) { Uint8 value, count, tmp; Uint8 *finish = buffer + bytes; while (buffer < finish) { value = *(buffer++); count = 1; while (buffer < finish && count < 63 && *buffer == value) { count++; buffer++; } if (value < 0xc0 && count == 1) { SDL_RWwrite(dst, &value, 1, 1); } else { tmp = count + 0xc0; SDL_RWwrite(dst, &tmp, 1, 1); SDL_RWwrite(dst, &value, 1, 1); } } } static void save_8 (SDL_RWops *dst, int width, int height, int pitch, Uint8* buffer) { int row; for (row = 0; row < height; ++row) { writeline (dst, buffer, width); buffer += pitch; } } static void save_24 (SDL_RWops *dst, int width, int height, int pitch, Uint8* buffer) { int x, y, c; Uint8 *line; line = (Uint8 *) malloc (width); for (y = 0; y < height; ++y) { for (c = 2; c >= 0; --c) { for (x = 0; x < width; ++x) { line[x] = buffer[(3*x) + c]; } writeline (dst, line, width); } buffer += pitch; } free (line); } static bool save_image(SDL_Surface *surface, SDL_RWops *dst) { Uint8 *cmap = 0; Uint8 *pixels; Uint8 tmp; int width, height, pitch; int colors = 0, i; PCX_Header header; width = surface->w; height = surface->h; pixels = (Uint8*)surface->pixels; pitch = surface->pitch; header.manufacturer = 0x0a; header.version = 5; header.compression = 1; if (surface->format->palette && surface->format->BitsPerPixel == 8) { colors = surface->format->palette->ncolors; cmap = (Uint8*)malloc(3*colors); for (i = 0; i < colors; i++) { cmap[3*i] = surface->format->palette->colors[i].r; cmap[3*i+1] = surface->format->palette->colors[i].g; cmap[3*i+2] = surface->format->palette->colors[i].b; } header.bpp = 8; header.bytesperline = htoqs (width); header.planes = 1; header.color = htoqs (1); } else if (surface->format->BitsPerPixel == 24) { header.bpp = 8; header.bytesperline = htoqs (width); header.planes = 3; header.color = htoqs(1); } else { return false; } header.x1 = 0; header.y1 = 0; header.x2 = htoqs (width - 1); header.y2 = htoqs (height - 1); header.hdpi = htoqs (300); header.vdpi = htoqs (300); header.reserved = 0; /* write header */ /* fp_offset = SDL_RWtell(dst);*/ SDL_RWwrite(dst, &header, sizeof(PCX_Header), 1); if (cmap) { save_8 (dst, width, height, pitch, pixels); /* write palette */ tmp = 0x0c; SDL_RWwrite(dst, &tmp, 1, 1); SDL_RWwrite(dst, cmap, 3, colors); /* fill unused colors */ tmp = 0; for (i = colors; i < 256; i++) { SDL_RWwrite(dst, &tmp, 1, 1); SDL_RWwrite(dst, &tmp, 1, 1); SDL_RWwrite(dst, &tmp, 1, 1); } free(cmap); } else { save_24 (dst, width, height, pitch, pixels); } return true; } bool SavePCX_RW (SDL_Surface *saveme, SDL_RWops *dst, bool freedst) { SDL_Surface *surface; bool found_error = false; cout << "Taking screenshot..."; surface = NULL; if ( dst ) { if ( saveme->format->palette ) { if ( saveme->format->BitsPerPixel == 8 ) { surface = saveme; } else { found_error = true; cout << saveme->format->BitsPerPixel << "bpp PCX files not supported" << endl; } } else if ( (saveme->format->BitsPerPixel == 24) && #if SDL_BYTEORDER == SDL_LIL_ENDIAN (saveme->format->Rmask == 0x00FF0000) && (saveme->format->Gmask == 0x0000FF00) && (saveme->format->Bmask == 0x000000FF) #else (saveme->format->Rmask == 0x000000FF) && (saveme->format->Gmask == 0x0000FF00) && (saveme->format->Bmask == 0x00FF0000) #endif ) { surface = saveme; } else { SDL_Rect bounds; /* Convert to 24 bits per pixel */ surface = SDL_CreateRGBSurface(SDL_SWSURFACE, saveme->w, saveme->h, 24, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x00FF0000, 0x0000FF00, 0x000000FF, #else 0x000000FF, 0x0000FF00, 0x00FF0000, #endif 0); if ( surface != NULL ) { bounds.x = 0; bounds.y = 0; bounds.w = saveme->w; bounds.h = saveme->h; if ( SDL_LowerBlit(saveme, &bounds, surface, &bounds) < 0 ) { SDL_FreeSurface(surface); cout << "Couldn't convert image to 24 bpp for screenshot"; found_error = true; surface = NULL; } } } } else { /* no valid target */ } if ( surface && (SDL_LockSurface(surface) == 0) ) { found_error |= !save_image(surface, dst); /* Close it up.. */ SDL_UnlockSurface(surface); if ( surface != saveme ) { SDL_FreeSurface(surface); } } if ( freedst && dst ) { SDL_RWclose(dst); } if (!found_error) { cout << "Done!" << endl; return true; } return false; } exult-1.2/imagewin/imagescl.cc0000644000175000001440000004165707631060063012103 /** ** Imagescl.cc - Methods to blit with scaling. ** ** Written: 6/16/2000 - JSF **/ /* Copyright (C) 2000 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "imagewin.h" #include "scale.h" #ifndef ALPHA_LINUX_CXX # include #endif #include "exult_types.h" /* * Manipulate from 8-bit to 16-bit pixels. */ class Manip8to16 { protected: SDL_Color *colors; // Palette for source window. SDL_PixelFormat *fmt; // Format of dest. pixels. public: Manip8to16(SDL_Color *c, SDL_PixelFormat *f) : colors(c), fmt(f) { } uint16 rgb(unsigned int r, unsigned int g, unsigned int b) const { return ((r>>fmt->Rloss)<Rshift) | ((g>>fmt->Gloss)<Gshift) | ((b>>fmt->Bloss)<Bshift); } void copy(uint16& dest, unsigned char src) const { SDL_Color& color = colors[src]; dest = rgb(color.r, color.g, color.b); } void split_source(unsigned char pix, unsigned int& r, unsigned int& g, unsigned int& b) const { SDL_Color& color = colors[pix]; r = color.r; g = color.g; b = color.b; } void split_dest(uint16 pix, unsigned int& r, unsigned int& g, unsigned int& b) const { r = ((pix&fmt->Rmask)>>fmt->Rshift)<Rloss; g = ((pix&fmt->Gmask)>>fmt->Gshift)<Gloss; b = ((pix&fmt->Bmask)>>fmt->Bshift)<Bloss; } }; /* * Manipulate from 8-bit to 16-bit 555 format. */ class Manip8to555 : public Manip8to16 { public: Manip8to555(SDL_Color *c) : Manip8to16(c, 0) { } uint16 rgb(unsigned int r, unsigned int g, unsigned int b) const { return ((r>>3)<<10)|((g>>3)<<5)|(b>>3); } void copy(uint16& dest, unsigned char src) const { SDL_Color& color = colors[src]; dest = rgb(color.r, color.g, color.b); } void split_dest(uint16 pix, unsigned int& r, unsigned int& g, unsigned int& b) const { r = (((pix&0x7c00)>>10)<<3); g = (((pix&0x03e0)>>5)<<3); b = ((pix&0x001f)<<3); } }; /* * Manipulate from 8-bit to 16-bit 565 format. */ class Manip8to565 : public Manip8to16 { public: Manip8to565(SDL_Color *c) : Manip8to16(c, 0) { } uint16 rgb(unsigned int r, unsigned int g, unsigned int b) const { return ((r>>3)<<11)|((g>>2)<<5)|(b>>3); } void copy(uint16& dest, unsigned char src) const { SDL_Color& color = colors[src]; dest = rgb(color.r, color.g, color.b); } void split_dest(uint16 pix, unsigned int& r, unsigned int& g, unsigned int& b) const { r = (((pix&0xf800)>>11)<<3); g = (((pix&0x07e0)>>5)<<2); b = ((pix&0x001f)<<3); } }; /* * Manipulate from 8-bit to 32-bit pixels. */ class Manip8to32 { SDL_Color *colors; // Source palette. SDL_PixelFormat *fmt; // Format of dest. pixels. public: Manip8to32(SDL_Color *c, SDL_PixelFormat *f) : colors(c), fmt(f) { } uint32 rgb(unsigned int r, unsigned int g, unsigned int b) const { return ((r>>fmt->Rloss)<Rshift) | ((g>>fmt->Gloss)<Gshift) | ((b>>fmt->Bloss)<Bshift); } void copy(uint32& dest, unsigned char src) const { SDL_Color& color = colors[src]; dest = rgb(color.r, color.g, color.b); } void split_source(unsigned char pix, unsigned int& r, unsigned int& g, unsigned int& b) const { SDL_Color& color = colors[pix]; r = color.r; g = color.g; b = color.b; } void split_dest(uint32 pix, unsigned int& r, unsigned int& g, unsigned int& b) const { r = ((pix&fmt->Rmask)>>fmt->Rshift)<Rloss; g = ((pix&fmt->Gmask)>>fmt->Gshift)<Gloss; b = ((pix&fmt->Bmask)>>fmt->Bshift)<Bloss; } }; /* * Manipulate from 16-bit to 16-bit pixels (555 bits in each case). */ class Manip16to16 { public: static void copy(uint16& dest, uint16 src) { dest = src; } static void split_source(uint16 pix, unsigned int& r, unsigned int& g, unsigned int& b) { r = (pix>>10)&0x1f; g = (pix>>5)&0x1f; b = pix&0x1f; } static void split_dest(uint16 pix, unsigned int& r, unsigned int& g, unsigned int& b) { split_source(pix, r, g, b); } static uint16 rgb(unsigned int r, unsigned int g, unsigned int b) { return ((r&0x1f)<<10) | ((g&0x1f)<<5) | (b&0x1f); } }; inline void increase_area(int& x, int& y, int& w, int& h, int left, int right, int top, int bottom, int buf_width, int buf_height) { x -= left; w += left+right; y -= top; h += top+bottom; if (x < 0) { w += x; x = 0; } if (y < 0) { h += y; y = 0; } if (x + w > buf_width) w = buf_width - x; if (y + h > buf_height) h = buf_height - y; } /* * Scaling methods: */ // // 2xSaI Filtering // void Image_window::show_scaled8to16_2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to16 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to555_2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to555 manip(surface->format->palette->colors); Scale_2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to565_2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to565 manip(surface->format->palette->colors); Scale_2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to32_2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to32 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint32 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } // // Super2xSaI Filtering // void Image_window::show_scaled8to16_Super2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to16 manip(surface->format->palette->colors, scaled_surface->format); Scale_Super2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to555_Super2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to555 manip(surface->format->palette->colors); Scale_Super2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to565_Super2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to565 manip(surface->format->palette->colors); Scale_Super2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to32_Super2xSaI ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to32 manip(surface->format->palette->colors, scaled_surface->format); Scale_Super2xSaI (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint32 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } // // SuperEagle Filtering // void Image_window::show_scaled8to16_SuperEagle ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to16 manip(surface->format->palette->colors, scaled_surface->format); Scale_SuperEagle (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to555_SuperEagle ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to555 manip(surface->format->palette->colors); Scale_SuperEagle (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to565_SuperEagle ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to565 manip(surface->format->palette->colors); Scale_SuperEagle (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to32_SuperEagle ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 2,2,1,1, ibuf->width, ibuf->height); Manip8to32 manip(surface->format->palette->colors, scaled_surface->format); Scale_SuperEagle (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint32 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } // // 2x Bilinear Filtering // void Image_window::show_scaled8to16_bilinear ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to16 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xBilinear (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to555_bilinear ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to555 manip(surface->format->palette->colors); Scale_2xBilinear (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to565_bilinear ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to565 manip(surface->format->palette->colors); Scale_2xBilinear (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to32_bilinear ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to32 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xBilinear (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint32 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } // // 2x Bilinear Plus Filtering // void Image_window::show_scaled8to16_BilinearPlus ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to16 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xBilinearPlus (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to555_BilinearPlus ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to555 manip(surface->format->palette->colors); Scale_2xBilinearPlus (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to565_BilinearPlus ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to565 manip(surface->format->palette->colors); Scale_2xBilinearPlus (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint16 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } void Image_window::show_scaled8to32_BilinearPlus ( int x, int y, int w, int h // Area to show. ) { increase_area(x,y,w,h, 1,1,1,1, ibuf->width, ibuf->height); Manip8to32 manip(surface->format->palette->colors, scaled_surface->format); Scale_2xBilinearPlus (ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (uint32 *) scaled_surface->pixels, scaled_surface->pitch/ scaled_surface->format->BytesPerPixel, manip); SDL_UpdateRect(scaled_surface, 2*x, 2*y, 2*w, 2*h); } // // Point Sampling // void Image_window::show_scaled_point ( int x, int y, int w, int h // Area to show. ) { Scale_point ((unsigned char *)ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (unsigned char *) surface->pixels, surface->pitch, scale); SDL_UpdateRect(surface, scale*x, scale*y, scale*w, scale*h); } // // Interlaced Point Sampling // void Image_window::show_scaled_interlace ( int x, int y, int w, int h // Area to show. ) { Scale_interlace ((unsigned char *)ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (unsigned char *) surface->pixels, surface->pitch, scale); SDL_UpdateRect(surface, scale*x, scale*y, scale*w, scale*h); } // // Scale2x (no blurring) by Andrea Mazzoleni. // void Image_window::show_scale2x_noblur ( int x, int y, int w, int h // Area to show. ) { Scale2x_noblur ((unsigned char *)ibuf->get_bits(), x, y, w, h, ibuf->line_width, ibuf->height, (unsigned char *) surface->pixels, surface->pitch ); SDL_UpdateRect(surface, scale*x, scale*y, scale*w, scale*h); } // // OpenGL 'scaler': // void Image_window::show_scaledOpenGL ( int x, int y, int w, int h // Area to show. ) { SDL_GL_SwapBuffers(); // Blit. } exult-1.2/imagewin/imagewin.cc0000644000175000001440000004026510054030561012102 /** ** Imagewin.cc - A window to blit images into. ** ** Written: 8/13/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "imagewin.h" #ifndef ALPHA_LINUX_CXX # include # include # include # include #endif #include "exult_types.h" #include "utils.h" #include "SDL_video.h" #include "SDL_error.h" #ifdef HAVE_OPENGL #include #endif bool SavePCX_RW (SDL_Surface *saveme, SDL_RWops *dst, bool freedst); #ifndef UNDER_CE using std::cout; using std::cerr; using std::endl; using std::exit; #endif // This is all the names of the scalers. It needs to match the ScalerType enum const char *Image_window::ScalerNames[] = { "Point", "Interlaced", "Bilinear", "BilinearPlus", "2xSaI", "SuperEagle", "Super2xSaI", "Scale2X", "OpenGL", 0 }; Image_window::ScalerType Image_window::get_scaler_for_name(const std::string &scaler) { std::string sclr = to_uppercase(scaler); for (int s = 0; s < NumScalers; s++) { std::string sclr2 = to_uppercase(ScalerNames[s]); if (sclr == sclr2) return (ScalerType) s; } return NoScaler; } /* * Get best depth. Returns bits/pixel. */ static int Get_best_depth ( ) { // Get video info. const SDL_VideoInfo *vinfo = SDL_GetVideoInfo(); // The "best" format: return (vinfo->vfmt->BitsPerPixel); } /* * Destroy window. */ Image_window::~Image_window ( ) { free_surface(); delete ibuf; } /* * Create the surface. */ void Image_window::create_surface ( unsigned int w, unsigned int h ) { ibuf->width = w; ibuf->height = h; Uint32 flags = (fullscreen?SDL_FULLSCREEN:0) | SDL_SWSURFACE | SDL_HWPALETTE; uses_palette = true; show_scaled = 0; unscaled_surface = surface = scaled_surface = 0; #if defined(__zaurus__) flags &= ~SDL_FULLSCREEN; // Zaurus would crash in fullscreen mode #else if (try_scaler(w, h, flags)) return; // everyone else can test the try_scaler function #endif if (!surface) // No scaling, or failed? { unscaled_surface = surface = SDL_SetVideoMode(w, h, ibuf->depth, flags); scale = 1; } if (!surface) { cout << "Couldn't set video mode (" << w << ", " << h << ") at " << ibuf->depth << " bpp depth: " << SDL_GetError() << endl; exit(-1); } ibuf->bits = (unsigned char *) surface->pixels; // Update line size in words. ibuf->line_width = surface->pitch/ibuf->pixel_size; } bool Image_window::try_scaler(int w, int h, uint32 flags) { // OpenGL if (scaler ==OpenGL) { #ifdef HAVE_OPENGL // Get info. about video. const SDL_VideoInfo *vinfo = SDL_GetVideoInfo(); if (!vinfo) { cout << "SDL_GetVideoInfo() failed: " << SDL_GetError() << endl; return false; } // Set up SDL video flags. int video_flags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE | (flags&SDL_FULLSCREEN); // Can surface be in video RAM? if (vinfo->hw_available) video_flags |= SDL_HWSURFACE; else video_flags |= SDL_SWSURFACE; if (vinfo->blit_hw) // Hardware blits? video_flags |= SDL_HWACCEL; // Want double-buffering. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Allocate surface. int hwdepth = vinfo->vfmt->BitsPerPixel; // +++++For now create 8-bit surface // to avoid crashing places we // haven't converted yet. if ((scaled_surface = SDL_SetVideoMode(scale*w, scale*h, hwdepth, video_flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { show_scaled = &Image_window::show_scaledOpenGL; } else { cerr << "Couldn't allocate surface: " << SDL_GetError() << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } #else cerr << "OpenGL not supported" << endl; #endif } // 2xSaI scaler else if (scale == 2 && scaler == SaI) { int hwdepth; if ( SDL_VideoModeOK(w, h, 32, flags)) hwdepth = 32; else if ( SDL_VideoModeOK(w, h, 16, flags)) hwdepth = 16; else hwdepth = Get_best_depth(); if ((hwdepth != 16 && hwdepth != 32) || ibuf->depth != 8) cout << "Doubling from " << ibuf->depth << "bits to " << hwdepth << " not yet supported." << endl; else if ((scaled_surface = SDL_SetVideoMode(2*w, 2*h, hwdepth, flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { // Get color mask info. SDL_PixelFormat *fmt = scaled_surface->format; uint32 r = fmt->Rmask, g=fmt->Gmask, b=fmt->Bmask; if (hwdepth == 16) { show_scaled = (r == 0xf800 && g == 0x7e0 &&b == 0x1f) ? &Image_window::show_scaled8to565_2xSaI : (r == 0x7c00 && g == 0x3e0 && b == 0x1f) ? &Image_window::show_scaled8to555_2xSaI : &Image_window::show_scaled8to16_2xSaI; } else show_scaled = &Image_window::show_scaled8to32_2xSaI; uses_palette = false; } else { cout << "Couldn't create scaled surface" << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } } else if (scale == 2 && scaler == bilinear) // Bilinear scaler { int hwdepth; if ( SDL_VideoModeOK(w, h, 32, flags)) hwdepth = 32; else if ( SDL_VideoModeOK(w, h, 16, flags)) hwdepth = 16; else hwdepth = Get_best_depth(); if ((hwdepth != 16 && hwdepth != 32) || ibuf->depth != 8) cout << "Doubling from " << ibuf->depth << "bits to " << hwdepth << " not yet supported." << endl; else if ((scaled_surface = SDL_SetVideoMode(2*w, 2*h, hwdepth, flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { // Get color mask info. SDL_PixelFormat *fmt = scaled_surface->format; uint32 r = fmt->Rmask, g=fmt->Gmask, b=fmt->Bmask; if (hwdepth == 16) { show_scaled = (r == 0xf800 && g == 0x7e0 &&b == 0x1f) ? &Image_window::show_scaled8to565_bilinear : (r == 0x7c00 && g == 0x3e0 && b == 0x1f) ? &Image_window::show_scaled8to555_bilinear : &Image_window::show_scaled8to16_bilinear; } else show_scaled = &Image_window::show_scaled8to32_bilinear; uses_palette = false; } else { cout << "Couldn't create scaled surface" << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } } else if (scale == 2 && scaler == BilinearPlus) // Bilinear Plus scaler { int hwdepth; if ( SDL_VideoModeOK(w, h, 32, flags)) hwdepth = 32; else if ( SDL_VideoModeOK(w, h, 16, flags)) hwdepth = 16; else hwdepth = Get_best_depth(); if ((hwdepth != 16 && hwdepth != 32) || ibuf->depth != 8) cout << "Doubling from " << ibuf->depth << "bits to " << hwdepth << " not yet supported." << endl; else if ((scaled_surface = SDL_SetVideoMode(2*w, 2*h, hwdepth, flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { // Get color mask info. SDL_PixelFormat *fmt = scaled_surface->format; uint32 r = fmt->Rmask, g=fmt->Gmask, b=fmt->Bmask; if (hwdepth == 16) { show_scaled = (r == 0xf800 && g == 0x7e0 &&b == 0x1f) ? &Image_window::show_scaled8to565_BilinearPlus : (r == 0x7c00 && g == 0x3e0 && b == 0x1f) ? &Image_window::show_scaled8to555_BilinearPlus : &Image_window::show_scaled8to16_BilinearPlus; } else show_scaled = &Image_window::show_scaled8to32_BilinearPlus; uses_palette = false; } else { cout << "Couldn't create scaled surface" << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } } else if (scale == 2 && scaler == SuperEagle) { int hwdepth; if ( SDL_VideoModeOK(w, h, 32, flags)) hwdepth = 32; else if ( SDL_VideoModeOK(w, h, 16, flags)) hwdepth = 16; else hwdepth = Get_best_depth(); if ((hwdepth != 16 && hwdepth != 32) || ibuf->depth != 8) cout << "Doubling from " << ibuf->depth << "bits to " << hwdepth << " not yet supported." << endl; else if ((scaled_surface = SDL_SetVideoMode(2*w, 2*h, hwdepth, flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { // Get color mask info. SDL_PixelFormat *fmt = scaled_surface->format; uint32 r = fmt->Rmask, g=fmt->Gmask, b=fmt->Bmask; if (hwdepth == 16) { show_scaled = (r == 0xf800 && g == 0x7e0 &&b == 0x1f) ? &Image_window::show_scaled8to565_SuperEagle : (r == 0x7c00 && g == 0x3e0 && b == 0x1f) ? &Image_window::show_scaled8to555_SuperEagle : &Image_window::show_scaled8to16_SuperEagle; } else show_scaled = &Image_window::show_scaled8to32_SuperEagle; uses_palette = false; } else { cout << "Couldn't create scaled surface" << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } } else if (scale == 2 && scaler == Super2xSaI) { int hwdepth; if ( SDL_VideoModeOK(w, h, 32, flags)) hwdepth = 32; else if ( SDL_VideoModeOK(w, h, 16, flags)) hwdepth = 16; else hwdepth = Get_best_depth(); if ((hwdepth != 16 && hwdepth != 32) || ibuf->depth != 8) cout << "Doubling from " << ibuf->depth << "bits to " << hwdepth << " not yet supported." << endl; else if ((scaled_surface = SDL_SetVideoMode(2*w, 2*h, hwdepth, flags)) != 0 && (unscaled_surface = surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) != 0) { // Get color mask info. SDL_PixelFormat *fmt = scaled_surface->format; uint32 r = fmt->Rmask, g=fmt->Gmask, b=fmt->Bmask; if (hwdepth == 16) { show_scaled = (r == 0xf800 && g == 0x7e0 &&b == 0x1f) ? &Image_window::show_scaled8to565_Super2xSaI : (r == 0x7c00 && g == 0x3e0 && b == 0x1f) ? &Image_window::show_scaled8to555_Super2xSaI : &Image_window::show_scaled8to16_Super2xSaI; } else show_scaled = &Image_window::show_scaled8to32_Super2xSaI; uses_palette = false; } else { cout << "Couldn't create scaled surface" << endl; delete surface; delete scaled_surface; surface = scaled_surface = 0; } } else if (scale >= 2 && scaler == interlaced) { surface = SDL_SetVideoMode(w*scale, h*scale, ibuf->depth, flags); unscaled_surface = scaled_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0); if (surface && scaled_surface) { show_scaled = &Image_window::show_scaled_interlace; ibuf->bits = (unsigned char *) scaled_surface->pixels; // Update line size in words. ibuf->line_width = scaled_surface->pitch/ibuf->pixel_size; return true; } else { cout << "Couldn't create 8bit scaled surface" << endl; if (surface) delete surface; if (scaled_surface) delete scaled_surface; surface = scaled_surface = 0; } } else if (scale == 2 && scaler == Scale2x) { surface = SDL_SetVideoMode(w*scale, h*scale, ibuf->depth, flags); unscaled_surface = scaled_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0); if (surface && scaled_surface) { show_scaled = &Image_window::show_scale2x_noblur; ibuf->bits = (unsigned char *) scaled_surface->pixels; // Update line size in words. ibuf->line_width = scaled_surface->pitch/ibuf->pixel_size; return true; } else { cout << "Couldn't create 8bit scaled surface" << endl; if (surface) delete surface; if (scaled_surface) delete scaled_surface; surface = scaled_surface = 0; } } else if (scale >= 2) { surface = SDL_SetVideoMode(w*scale, h*scale, ibuf->depth, flags); unscaled_surface = scaled_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0); if (surface && scaled_surface) { show_scaled = &Image_window::show_scaled_point; ibuf->bits = (unsigned char *) scaled_surface->pixels; // Update line size in words. ibuf->line_width = scaled_surface->pitch/ibuf->pixel_size; return true; } else { cout << "Couldn't create 8bit scaled surface" << endl; if (surface) delete surface; if (scaled_surface) delete scaled_surface; surface = scaled_surface = 0; } } return false; } /* * Free the surface. */ void Image_window::free_surface ( ) { if (!surface) return; SDL_FreeSurface(surface); ibuf->bits = 0; surface = 0; if (scaled_surface) { SDL_FreeSurface(scaled_surface); scaled_surface = 0; } } /* * Create a compatible buffer. */ Image_buffer *Image_window::create_buffer ( int w, int h // Dimensions. ) { Image_buffer *newbuf = ibuf->create_another(w, h); return (newbuf); } /* * Window was resized. */ void Image_window::resized ( unsigned int neww, unsigned int newh, int newsc, int newscaler ) { if (surface) { if (neww == ibuf->width && newh == ibuf->height && newsc == scale && scaler == newscaler) return; // Nothing changed. free_surface(); // Delete old image. } scale = newsc; scaler = newscaler; create_surface(neww, newh); // Create new one. } /* * Repaint window. */ void Image_window::show ( ) { if (!ready()) return; if (show_scaled) // 2X scaling? (this->*show_scaled)(0, 0, ibuf->width, ibuf->height); else SDL_UpdateRect(surface, 0, 0, ibuf->width, ibuf->height); } /* * Repaint portion of window. */ void Image_window::show ( int x, int y, int w, int h ) { if (!ready()) return; int srcx = 0, srcy = 0; if (!ibuf->clip(srcx, srcy, w, h, x, y)) return; if (show_scaled) // 2X scaling? (this->*show_scaled)(x, y, w, h); else SDL_UpdateRect(surface, x, y, w, h); } /* * Toggle fullscreen. */ void Image_window::toggle_fullscreen() { Uint32 flags; int w, h, bpp; SDL_Surface *surf = scaled_surface&&surface==unscaled_surface?scaled_surface:surface; w = unscaled_surface->w; h = unscaled_surface->h; bpp = surf->format->BitsPerPixel; if ( fullscreen ) { cout << "Switching to windowed mode."<flags & ~SDL_FULLSCREEN; } else { cout << "Switching to fullscreen mode."<flags | SDL_FULLSCREEN; } // First see if it's allowed. if ( SDL_VideoModeOK(w, h, bpp, flags) ) { free_surface(); // Delete old. fullscreen = !fullscreen; create_surface(w, h); // Create new. } } bool Image_window::screenshot(SDL_RWops *dst) { if (!surface) return false; return SavePCX_RW(unscaled_surface, dst, true); } void Image_window::set_title(const char *title) { SDL_WM_SetCaption(title, 0); } #ifdef HAVE_OPENGL /* * Fill a rectangle with an 8-bit value. */ void Image_window::opengl_fill8 ( unsigned char pix, int srcw, int srch, int destx, int desty ) { SDL_Color *colors = surface->format->palette->colors; SDL_Color& color = colors[pix]; glDisable(GL_TEXTURE_2D); // Disable texture-mapping. glPushMatrix(); int x = destx; // Left edge. int y = -(desty + srch); glTranslatef(x, y, 0); glBegin(GL_QUADS); { glColor3ub(color.r, color.g, color.b); glVertex3i(0, 0, 0); glVertex3i(srcw, 0, 0); glVertex3i(srcw, srch, 0); glVertex3i(0, srch, 0); } glEnd(); glPopMatrix(); } /* * Apply a translucency table to a rectangle. */ void Image_window::opengl_fill_translucent8 ( unsigned char /* val */, // Not used. int srcw, int srch, int destx, int desty, Xform_palette& xform // Transform table. ) { glDisable(GL_TEXTURE_2D); // Disable texture-mapping. int x = destx; // Left edge. int y = -(desty + srch); glBegin(GL_QUADS); { glColor4ub(xform.r, xform.g, xform.b, xform.a); glVertex2i(x, y); glVertex2i(x + srcw, y); glVertex2i(x + srcw, y + srch); glVertex2i(x, y + srch); } glEnd(); } #endif exult-1.2/imagewin/Makefile.am0000644000175000001440000000062407500250505012026 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libimagewin.la libimagewin_la_SOURCES = \ ibuf16.cc \ ibuf16.h \ ibuf8.cc \ ibuf8.h \ imagebuf.cc \ imagebuf.h \ imagescl.cc \ imagewin.cc \ imagewin.h \ iwin8.cc \ iwin8.h \ scale.h \ savepcx.cc EXTRA_DIST = \ scale.cc exult-1.2/imagewin/Makefile.in0000644000175000001440000002472410061527050012044 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files $(SDL_CFLAGS) $(INCDIRS) $(WINDOWING_SYSTEM) \ $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libimagewin.la libimagewin_la_SOURCES = \ ibuf16.cc \ ibuf16.h \ ibuf8.cc \ ibuf8.h \ imagebuf.cc \ imagebuf.h \ imagescl.cc \ imagewin.cc \ imagewin.h \ iwin8.cc \ iwin8.h \ scale.h \ savepcx.cc EXTRA_DIST = \ scale.cc subdir = imagewin mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libimagewin_la_LDFLAGS = libimagewin_la_LIBADD = am_libimagewin_la_OBJECTS = ibuf16.lo ibuf8.lo imagebuf.lo imagescl.lo \ imagewin.lo iwin8.lo savepcx.lo libimagewin_la_OBJECTS = $(am_libimagewin_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/ibuf16.Plo $(DEPDIR)/ibuf8.Plo \ @AMDEP_TRUE@ $(DEPDIR)/imagebuf.Plo $(DEPDIR)/imagescl.Plo \ @AMDEP_TRUE@ $(DEPDIR)/imagewin.Plo $(DEPDIR)/iwin8.Plo \ @AMDEP_TRUE@ $(DEPDIR)/savepcx.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libimagewin_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libimagewin_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu imagewin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libimagewin.la: $(libimagewin_la_OBJECTS) $(libimagewin_la_DEPENDENCIES) $(CXXLINK) $(libimagewin_la_LDFLAGS) $(libimagewin_la_OBJECTS) $(libimagewin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ibuf16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ibuf8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/imagebuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/imagescl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/imagewin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/iwin8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/savepcx.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/imagewin/ibuf8.h0000644000175000001440000000677107724430452011202 /* * ibuf8.h - 8-bit image buffer. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_IBUF8 #define INCL_IBUF8 1 #include "imagebuf.h" /* * An 8-bit image buffer: */ class Image_buffer8 : public Image_buffer { // Private ctor. for Image_window8. Image_buffer8(unsigned int w, unsigned int h, Image_buffer *) : Image_buffer(w, h, 8) { } public: Image_buffer8(unsigned int w, unsigned int h) : Image_buffer(w, h, 8) { bits = new unsigned char[w*h]; } friend class Image_window8; /* * Depth-independent methods: */ virtual Image_buffer *create_another(int w, int h) { return new Image_buffer8(w, h); } // Copy within itself. virtual void copy(int srcx, int srcy, int srcw, int srch, int destx, int desty); // Get rect. into another buf. virtual void get(Image_buffer *dest, int srcx, int srcy); // Put rect. back. virtual void put(Image_buffer *src, int destx, int desty); virtual void fill_static(int black, int gray, int white); /* * 8-bit color methods: */ // Fill with given (8-bit) value. virtual void fill8(unsigned char val); // Fill rect. wth pixel. virtual void fill8(unsigned char val, int srcw, int srch, int destx, int desty); // Fill line with pixel. virtual void fill_line8(unsigned char val, int srcw, int destx, int desty); // Copy rectangle into here. virtual void copy8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty); // Copy line to here. virtual void copy_line8(unsigned char *src_pixels, int srcw, int destx, int desty); // Copy with translucency table. virtual void copy_line_translucent8( unsigned char *src_pixels, int srcw, int destx, int desty, int first_translucent, int last_translucent, Xform_palette *xforms); // Apply translucency to a line. virtual void fill_line_translucent8(unsigned char val, int srcw, int destx, int desty, Xform_palette& xform); // Apply translucency to a rectangle virtual void fill_translucent8(unsigned char val, int srcw, int srch, int destx, int desty, Xform_palette& xform); // Copy rect. with transp. color. virtual void copy_transparent8(unsigned char *src_pixels, int srcw, int srch, int destx, int desty); // Get/put a single pixel. unsigned char get_pixel8(int x, int y) { return bits[y*line_width + x]; } void put_pixel8(unsigned char pix, int x, int y) { if (x >= clipx && x < clipx + clipw && y >= clipy && y < clipy + cliph) bits[y*line_width + x] = pix; } void paint_rle (int xoff, int yoff, unsigned char *in); // Convert to 32-bit rgba. unsigned char *rgba(unsigned char *pal, unsigned char transp, int first_translucent = 256, int last_translucent = 256, Xform_palette *xforms = 0); }; #endif exult-1.2/imagewin/ibuf16.cc0000644000175000001440000002120610054030561011370 /* * ibuf16.cc - 16-bit image buffer. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ibuf16.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #ifndef UNDER_CE using std::memmove; #endif /* * Create a default palette for 8-bit graphics on a 16-bit display. */ void Image_buffer16::create_default_palette ( ) { delete palette; // Delete old. palette = new unsigned short[256]; for (int i = 0; i < 256; i++) palette[i] = rgb(4*((i >> 5) & 0x7), 4*((i >> 2) & 0x7), 9*(i & 0x3)); } /* * Fill with a given 16-bit value. */ void Image_buffer16::fill16 ( unsigned short pix ) { unsigned short *pixels = get_pixels(); int cnt = line_width*height; for (int i = 0; i < cnt; i++) *pixels++ = pix; } /* * Fill a rectangle with a 16-bit value. */ void Image_buffer16::fill16 ( unsigned short pix, int srcw, int srch, int destx, int desty ) { int srcx = 0, srcy = 0; // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *pixels = get_pixels() + desty*line_width + destx; int to_next = line_width - srcw;// # pixels to next line. while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *pixels++ = pix; pixels += to_next; // Get to start of next line. } } /* * Fill a line with a given 16-bit value. */ void Image_buffer16::fill_line16 ( unsigned short pix, int srcw, int destx, int desty ) { int srcx = 0, srcy = 0, srch = 1; // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *pixels = get_pixels() + desty*line_width + destx; for (int cnt = srcw; cnt; cnt--) *pixels++ = pix; } /* * Copy another rectangle into this one. */ void Image_buffer16::copy16 ( unsigned short *src_pixels, // Source rectangle pixels. int srcw, int srch, // Dimensions of source. int destx, int desty ) { int srcx = 0, srcy = 0; int src_width = srcw; // Save full source width. // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *to = get_pixels() + desty*line_width + destx; unsigned short *from = src_pixels + srcy*src_width + srcx; int to_next = line_width - srcw;// # pixels to next line. int from_next = src_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *to++ = *from++; to += to_next; from += from_next; } } /* * Copy an area of the image within itself. */ void Image_buffer16::copy ( int srcx, int srcy, // Where to start. int srcw, int srch, // Dimensions to copy. int destx, int desty // Where to copy to. ) { int ynext, yfrom, yto; // Figure y stuff. if (srcy >= desty) // Moving up? { ynext = line_width; yfrom = srcy; yto = desty; } else // Moving down. { ynext = -line_width; yfrom = srcy + srch - 1; yto = desty + srch - 1; } unsigned short *to = get_pixels() + yto*line_width + destx; unsigned short *from = get_pixels() + yfrom*line_width + srcx; // Go through lines. while (srch--) { memmove((char *) to, (char *) from, srcw * 2); to += ynext; from += ynext; } } /* * Get a rectangle from here into another Image_buffer. */ void Image_buffer16::get ( Image_buffer *dest, // Copy to here. int srcx, int srcy // Upper-left corner of source rect. ) { int srcw = dest->get_width(), srch = dest->get_height(); int destx = 0, desty = 0; // Constrain to window's space. (Note // convoluted use of clip().) if (!clip(destx, desty, srcw, srch, srcx, srcy)) return; unsigned short *to = (unsigned short *) dest->bits + desty*dest->line_width + destx; unsigned short *from = get_pixels() + srcy*line_width + srcx; // Figure # pixels to next line. int to_next = dest->line_width - srcw; int from_next = line_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *to++ = *from++; to += to_next; from += from_next; } } /* * Retrieve data from another buffer. */ void Image_buffer16::put ( Image_buffer *src, // Copy from here. int destx, int desty // Copy to here. ) { Image_buffer16::copy16((unsigned short *) src->bits, src->get_width(), src->get_height(), destx, desty); } /* * Fill buffer with random static */ void Image_buffer16::fill_static(int black, int gray, int white) { unsigned short *p = get_pixels(); unsigned short black16 = palette[black]; unsigned short gray16 = palette[gray]; unsigned short white16 = palette[white]; for (int i = width*height; i > 0; --i) { switch (std::rand()%5) { case 0: case 1: *p++ = black16; break; case 2: case 3: *p++ = gray16; break; case 4: *p++ = white16; break; } } } /* * Convert rgb value. */ inline unsigned char Get_color16 ( unsigned char val, int maxval, int brightness // 100=normal. ) { unsigned int c = (((unsigned int) val)*brightness*32)/ (100*(maxval + 1)); return (c < 32 ? c : 31); } /* * Set palette. */ void Image_buffer16::set_palette ( unsigned char *rgbs, // 256 3-byte entries. int maxval, // Highest val. for each color. int brightness // Brightness control (100 = normal). ) { // Get the colors. for (int i = 0; i < 3*256; i += 3) { unsigned char r = Get_color16(rgbs[i], maxval, brightness); unsigned char g = Get_color16(rgbs[i + 1], maxval, brightness); unsigned char b = Get_color16(rgbs[i + 2], maxval, brightness); set_palette_color(i/3, r, g, b); } } /* * Rotate a range of colors. */ void Image_buffer16::rotate_colors ( int first, // Palette index of 1st. int num, // # in range. int upd // 1 to update hardware now. ) { int cnt = num - 1; // Shift downward. int c0 = palette[first]; for (int i = first; cnt; i++, cnt--) palette[i] = palette[i + 1]; palette[first + num - 1] = c0; // Shift 1st to end. // +++++upd? } /* * Copy another rectangle into this one. */ void Image_buffer16::copy8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, int srch, // Dimensions of source. int destx, int desty ) { int srcx = 0, srcy = 0; int src_width = srcw; // Save full source width. // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *to = get_pixels() + desty*line_width + destx; unsigned char *from = src_pixels + srcy*src_width + srcx; int to_next = line_width - srcw;// # pixels to next line. int from_next = src_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--) *to++ = palette[*from++]; to += to_next; from += from_next; } } /* * Copy a line into this buffer. */ void Image_buffer16::copy_line8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, // Width to copy. int destx, int desty ) { int srcx = 0, srcy = 0, srch = 1; // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *to = get_pixels() + desty*line_width + destx; unsigned char *from = src_pixels + srcx; for (int cnt = srcw; cnt; cnt--) *to++ = palette[*from++]; } /* * Copy another rectangle into this one, with 0 being the transparent * color. */ void Image_buffer16::copy_transparent8 ( unsigned char *src_pixels, // Source rectangle pixels. int srcw, int srch, // Dimensions of source. int destx, int desty ) { int srcx = 0, srcy = 0; int src_width = srcw; // Save full source width. // Constrain to window's space. if (!clip(srcx, srcy, srcw, srch, destx, desty)) return; unsigned short *to = get_pixels() + desty*line_width + destx; unsigned char *from = src_pixels + srcy*src_width + srcx; int to_next = line_width - srcw;// # pixels to next line. int from_next = src_width - srcw; while (srch--) // Do each line. { for (int cnt = srcw; cnt; cnt--, to++) { register int chr = *from++; if (chr) *to = palette[chr]; } to += to_next; from += from_next; } } exult-1.2/palette.cc0000644000175000001440000001771510054030531010141 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "files/U7file.h" #include "palette.h" #include "ibuf8.h" #include "utils.h" #include "fnames.h" #include "gamewin.h" #include "SDL_timer.h" #ifndef UNDER_CE using std::memcpy; using std::memset; using std::size_t; using std::string; #endif Palette::Palette() : win(Game_window::get_instance()->get_win()), palette(-1), brightness(100), faded_out(false), fades_enabled(true), max_val(63) { } Palette::~Palette() { } /* * Fade the current palette in or out. * Note: If pal_num != -1, the current palette is set to it. */ void Palette::fade ( int cycles, // Length of fade. int inout, // 1 to fade in, 0 to fade to black. int pal_num // 0-11, or -1 for current. ) { if (pal_num == -1) pal_num = palette; load(PALETTES_FLX, pal_num); if(inout) fade_in(cycles); else fade_out(cycles); faded_out = !inout; // Be sure to set flag. } /* * Flash the current palette red. */ void Palette::flash_red ( ) { int savepal = palette; set(PALETTE_RED); // Palette 8 is the red one. win->show(); SDL_Delay(100); set(savepal); Game_window::get_instance()->set_painted(); } /* * Read in a palette. */ void Palette::set ( int pal_num, // 0-11, or -1 to leave unchanged. int new_brightness, // New percentage, or -1. bool repaint ) { if ((palette == pal_num || pal_num == -1) && (brightness == new_brightness || new_brightness == -1)) return; // Already set. if (pal_num != -1) palette = pal_num; // Store #. if (new_brightness > 0) brightness = new_brightness; if (faded_out) return; // In the black. load(PALETTES_FLX, palette); // could throw! set_brightness(brightness); apply(repaint); } void Palette::apply(bool repaint) { win->set_palette(pal1, max_val, brightness); if (repaint) win->show(); } /* * Returns 0 if file not found. */ void Palette::load(const char *fname, int index, const char *xfname, int xindex) { size_t len; char *buf = 0; if (std::strncmp(fname, "/", sizeof("/") - 1) == 0 && is_system_path_defined("")) { // Check in "patch" dir. first. string pname("/"); pname += fname + sizeof("/") - 1; U7object pal(pname.c_str(), index); try { buf = pal.retrieve(len); } catch (exult_exception& e) { buf = 0; } } if (!buf) // Not in patch. { U7object pal(fname, index); buf = pal.retrieve(len);// this may throw an exception } if(len==768) { // Simple palette if (xindex >= 0) { // Get xform table. U7object xform(xfname, xindex); unsigned char *xbuf = 0; size_t xlen; try { #if 0 /* +++++TESTING */ xbuf = new unsigned char[256]; Game_window *gwin = Game_window::get_instance(); memcpy(xbuf, gwin->get_xform(11 - xindex - 1), 256); #else xbuf = (unsigned char *) xform.retrieve( xlen); #endif for (int i = 0; i < 256; i++) { int ix = xbuf[i]; pal1[3*i] = buf[3*ix]; pal1[3*i+1] = buf[3*ix+1]; pal1[3*i+2] = buf[3*ix+2]; } } catch( const std::exception & err ) { xindex = -1; } delete [] xbuf; } if (xindex < 0) // Set the first palette memcpy(pal1,buf,768); memset(pal2,0,768); // The second one is black } else { // Double palette for(int i=0; i<768; i++) { pal1[i]=buf[i*2]; pal2[i]=buf[i*2+1]; } } delete [] buf; } /*void Palette::load(const char *fname, int index, const char *xfname, int xindex) { U7object pal(fname, index); size_t len; char *buf; pal.retrieve(&buf, len); // this may throw an exception if(len==768) { // Simple palette if (xindex >= 0) // Get xform table. { U7object xform(xfname, xindex); unsigned char *xbuf; size_t xlen; if (!xform.retrieve(&xbuf, xlen)) xindex = -1; else for (int i = 0; i < 256; i++) { int ix = xbuf[i]; pal1[3*i] = buf[3*ix]; pal1[3*i+1] = buf[3*ix+1]; pal1[3*i+2] = buf[3*ix+2]; } delete [] xbuf; } if (xindex < 0) // Set the first palette memcpy(pal1,buf,768); memset(pal2,0,768); // The second one is black } else { // Double palette for(int i=0; i<768; i++) { pal1[i]=buf[i*2]; pal2[i]=buf[i*2+1]; } } delete [] buf; } */ void Palette::set_brightness(int bright) { brightness = bright; } void Palette::fade_in(int cycles) { if (fades_enabled) { unsigned char fade_pal[768]; unsigned int ticks = SDL_GetTicks() + 20; for (int i = 0; i <= cycles; i++) { for(int c=0; c < 768; c++) fade_pal[c] = ((pal1[c]-pal2[c])*i)/cycles+pal2[c]; win->set_palette(fade_pal, max_val, brightness); // Frame skipping on slow systems if (i == cycles || ticks >= SDL_GetTicks() || !Game_window::get_instance()->get_frame_skipping()) win->show(); while (ticks >= SDL_GetTicks()) ; ticks += 20; } } else { win->set_palette(pal1, max_val, brightness); win->show(); } } void Palette::fade_out(int cycles) { if (fades_enabled) { unsigned char fade_pal[768]; unsigned int ticks = SDL_GetTicks() + 20; for (int i = cycles; i >= 0; i--) { for(int c=0; c < 768; c++) fade_pal[c] = ((pal1[c]-pal2[c])*i)/cycles+pal2[c]; win->set_palette(fade_pal, max_val, brightness); // Frame skipping on slow systems if (i == 0 || ticks >= SDL_GetTicks() || !Game_window::get_instance()->get_frame_skipping()) win->show(); while (ticks >= SDL_GetTicks()) ; ticks += 20; } } else { win->set_palette(pal2, max_val, brightness); win->show(); } //Messes up sleep. win->set_palette(pal1, max_val, brightness); } // Find index (0-255) of closest color (r,g,b < 64). int Palette::find_color(int r, int g, int b) { int best_index = -1; long best_distance = 0xfffffff; // But don't search rotating colors. for (int i = 0; i < 0xe0; i++) { // Get deltas. long dr = r - pal1[3*i], dg = g - pal1[3*i + 1], db = b - pal1[3*i + 2]; // Figure distance-squared. long dist = dr*dr + dg*dg + db*db; if (dist < best_distance) { // Better than prev? best_index = i; best_distance = dist; } } return best_index; } /* * Create a translucency table for this palette seen through a given * color. (Based on a www.gamedev.net article by Jesse Towner.) */ void Palette::create_trans_table ( // Color to blend with: unsigned char br, unsigned bg, unsigned bb, int alpha, // 0-255, applied to 'blend' color. unsigned char *table // 256 indices are stored here. ) { for (int i = 0; i < 256; i++) { int newr = ((int) br * alpha)/255 + ((int) pal1[i*3] * (255 - alpha))/255; int newg = ((int) bg * alpha)/255 + ((int) pal1[i*3 + 1] * (255 - alpha))/255; int newb = ((int) bb * alpha)/255 + ((int) pal1[i*3 + 2] * (255 - alpha))/255; table[i] = find_color(newr, newg, newb); } } void Palette::show() { for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { win->fill8(y*16+x, 8, 8, x*8, y*8); } } } void Palette::set_color(int nr, int r, int g, int b) { pal1[nr*3] = r; pal1[nr*3+1] = g; pal1[nr*3+2] = b; } void Palette::set_palette(unsigned char palnew[768]) { memcpy(pal1,palnew,768); memset(pal2,0,768); } void Palette::set_max_val(int max) { max_val = max; } int Palette::get_max_val() { return max_val; } exult-1.2/README.1ST0000644000175000001440000000664707557111626007507 *** EXULT 1.0 - READ CAREFULLY *** After more than four years since the first release by Jeff in September 1998, Exult has finally reached a level of maturity and playbility which we believe warrants its release as an 1.0 version. What does the Exult Team mean by 1.0 ? We mean that you can play both "Ultima VII: The Black Gate" and "Ultima VII part 2: Serpent Isle" together with their respective add-ons "Forge of Virtue" and "Silver Seed" from beginning to end, with no plot holes. This does not mean the experience is perfect: we are not aiming for a precise replica of the originals (use a low-end 486 with DOS 5.0, a SoundBlaster and a Roland MT-32 for that). There are many things where Exult behaves differently (party formation, combat, stealing, etc.) but we don't think these detract from the fun and enjoyment of playing these great games. We've done our best to add improvements which we believe add to the game, and give it a more modern feel. Most of these can be disabled and enabled at will. During the Beta phase, no new features have been added to Exult and we worked exclusively on stabilization and documentation. Now that we are satisfied with stability on all platforms, we are releasing Exult 1.0. Exult development is currently branched in two: a stable branch, to which only bugfixes are applied, and from which subsequent 1.0.x releases will be made, and a development 1.1.x branch which focuses on new features and especially on getting ExultStudio and the other tools working. The differences between the two branches is listed further down this file in the Appendix. If you have used Exult before, you should really start new games for both BG and SI as previous versions may have generated incorrect savegames. If you experience problems with old savegames, you are on your own. Please read the documentation and the FAQ very carefully before reporting problems with Exult. If you want to report bugs, use the bug tracker on our SourceForge project page http://sourceforge.net/tracker/?atid=102335&group_id=2335&func=browse Provide a good description of the bug, a way to reproduce it, a savegame immediately before triggering the bug, and a description of your computer's configuration (OS, CPU, soundcard, videocard). Remember: Exult runs on many platforms, not just yours. As usual, we are available on the mailing list (mailto:exult-general@lists.sourceforge.net), on our forum (http://exult.sourceforge.net/forum/list.php?f=1) and on IRC (#exult on irc.openprojects.net) and we will try to help as much as we can. Have fun The Exult Team APPENDIX: Differences between Exult 1.0.x and Exult 1.1.x As 1.0.x is only for bug fixes new features have only been added to 1.1.x. These features are: - Exult Studio works only with 1.1.x now - Only the 1.1.x branch has been ported to the Zaurus - Keyboard movement - Digital music as better sounding alternative to MIDI music - FM Synth emulation, another alternative to MIDI music - Gumps now optionally pause the game - Combat with the Spellbook works now - Bookmarked Spell is saved and restored - Using "evil" spells can now get you into trouble with the guards - Feeding also uses drinks now - Avatar always uses the correct bed now - Experimental OpenGL hardware-accelerated support - More support for weapon/ammo powers - A "--nomenu" command-line arg, that gets you directly into the game - Partly fixes problem where two combatants rush towards each other but keep going after they meet exult-1.2/README.axp0000755000175000001440000001003007400401520007626 Exult on Alpha/Linux -------------------- Running Exult on Alpha/Linux has no special restrictions, but compiling it does, since the current (2.95.2) g++ is known to be broken on this platform. This document discusses how Exult can be built on the Alpha anyway. 1. Problem description ---------------------- GCC's g++ frontend on Alpha/Linux is, simply put, broken. This is very visible when using code optimization, but even without optimization, incorrect virtual function tables are being generated. This doesn't happen everywhere, but it affects Exult; therefore, compiling Exult can't be done with g++ at the moment. Compaq has provided us with an alternative, though: DEC's cxx compiler, ported to Alpha/Linux. This compiler is non-free, but available without charge from their website. Unfortunately, most Linux system headers appear to be set up for g++, which does some magical internal name mangling. This doesn't conform to the standard, but, more importantly, it breaks cxx, unless names are mangled manually. cxx has two other problems: It does not appear to like static methods that use templates, and its object files don't work with many versions of ld (specifically, it requires ld to accept --style=compaq. All modern ld versions from the GNU binutils claim that they do, but most of them are lying). Finally, ladebug appears to be either too slow or- in some way (multithreading)- incompatible with Exult or one of the libraries (SDL?) used by it. Sections 3 and 4 will discuss how these problems can be worked around. As far as I know, all other issues are general 64 bit cleanness issues. 2. Updates and binaries ----------------------- Up-to-date information about Exult on Alpha/Linux and pre-compiled binaries can be found at http://www.darmstadt.gmd.de/~jameson/exult/ 3. Preparing for the compilation -------------------------------- First, I'd like to point out that it may take a while until your system meets all preconditions required for compiling Exult. If you just want to play the game, it might be easier to use a pre-compiled binary from the URL mentioned in section 2. All right, if you're still reading this, you appear to be seriously considering to compile the beast. Here's what you'll need: - Compaq cxx for your Alpha/Linux flavor - Compaq's libots Compaq ccc might be required as well; I had it and cpml installed, too (just in case). Refer to http://www.support.compaq.com/alpha-tools/software/index.html for instructions on downloading these tools for non-commercial usage. Also, you'll need to link the generated object files. As discussed in section 1, your version of ld might not cut it. Try running "ld --style=compaq"; if you get an error message, you'll need a different version. I copied mine from one of the Compaq Test Drive systems, which you can get a free account for. Matching versions of the GNU binutils should be available in a more official way from Compaq somewhere; please contact me if you're found a place that carries them. If you got a new ld, you will need to replace yours with the new one. Remember to make a backup first! 4. Compiling ------------ ./configure --enable-long-long-warnings --with-cxx="cxx -O5 -D__inline__=inline" should do it for normal compiles. If you want to debug, you should use "-g3" instead of "-O5", or an appropriate combination of both (refer to the cxx man page for details). The --enable-long-long-warnings is required because cxx passes the -Wno-long-long option on to the linker, which chokes on it. Therefore, -Wno-long-long must not be used for compiles, which is enforced by the --enable-long-long-warnings option. If everything went well, your system should be set up for compilation. Run "make" and (as superuser) "make install". Some sort of "make install" or equivalent action is required for Exult to install its own data files. You should now have an "exult" binary ready to run! -- Christoph Reichenbach Please contact me if you find any of the information contained herein to be wrong, incomplete, or misleading. [Last updated on 12/08/2000] exult-1.2/bggame.h0000644000175000001440000000266607724430447007612 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BGGAME_H #define BGGAME_H #include "game.h" class BG_Game: public Game { public: BG_Game(); ~BG_Game(); virtual void play_intro(); virtual void end_game(bool success); virtual void top_menu(); virtual void show_quotes(); virtual void show_credits(); virtual bool new_game(Vga_file &shapes); virtual int get_start_tile_x() { return (64*c_tiles_per_chunk); } virtual int get_start_tile_y() { return (136*c_tiles_per_chunk); } virtual void show_journey_failed(); static bool is_installed(); private: Vga_file shapes; void scene_lord_british(); void scene_butterfly(); void scene_guardian(); void scene_desk(); void scene_moongate(); }; #endif exult-1.2/autoarray.h0000644000175000001440000000444007724430447010367 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "exult_types.h" template class autoarray { private: std::size_t size_; T *data_; public: #ifdef HAVE_NO_EXCEPTIONS inline static range_error(const std::string& what_arg) { std::cerr << "Range Error: " << what_arg << std::endl; #ifdef DEBUG *((int *)(0)) = 0; #else std::exit(-1); #endif } #else class range_error : public std::exception { std::string what_; public: range_error (const std::string& what_arg): what_ (what_arg) { } const char *what(void) const throw () { return what_.c_str(); } virtual ~range_error() throw () { } }; #endif autoarray() : size_(0), data_(0) { } autoarray(std::size_t n) : size_(n),data_(n?new T[n]:0) { } #ifdef HAVE_NO_EXCEPTIONS T &operator[](sint32 i) #else T &operator[](sint32 i) throw(range_error) #endif { if(i>=(sint32)size_ || i < 0) throw range_error("out of bounds"); if(data_) return data_[i]; throw range_error("no data"); } ~autoarray() { if(data_) delete [] data_; } autoarray(const autoarray &a) : size_(0),data_(0) { if(a.data_) { data_=new T[a.size_]; memcpy(data_,a.data_,a.size_); size_=a.size_; } } autoarray &operator=(const autoarray &a) { if(data_) { delete [] data_; size_=0; } if(a.data_) { data_=new T[a.size_]; memcpy(data_,a.data_,a.size_); size_=a.size_; } return *this; } void set_size(std::size_t new_size) { if(data_) { delete [] data_; } data_=new T[new_size]; size_=new_size; } }; exult-1.2/headers/0000777000175000001440000000000010062225324007665 5exult-1.2/headers/gamma.h0000644000175000001440000000301110054030560011024 /* Gamma Table Class Copyright (C) 2000 Ryan Nunn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_GAMMA #define INCL_GAMMA 1 #ifndef ALPHA_LINUX_CXX # include #endif #ifndef UNDER_CE using std::pow; #endif template class GammaTable { private: unsigned size; float sizef; T *table; float gamma; // No GammaTable() { } public: inline const float & get_gamma () { return gamma; } inline void set_gamma (float g) { if (g < 0.001f) g = 0.001f; if (g == gamma) return; gamma = g; for (unsigned i = 0; i < size; i++) table[i] = (T) (pow (i / sizef, 1 / gamma) * sizef); } GammaTable (unsigned int s, float g = 1) : sizef(-1), gamma(-1) { sizef += size = s>2?s:2; table = new T [size]; set_gamma(g); } ~GammaTable () { delete [] table; } inline const T & operator [] (const T &i) const { return table[i]; } }; #endif //INCL_GAMMA exult-1.2/headers/exceptions.h0000755000175000001440000000716107724430452012156 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EXCEPTIONS_H #define EXCEPTIONS_H #ifndef ALPHA_LINUX_CXX # include #endif #include #include /* * Base class of all our exceptions, providing a storage for the error message */ class exult_exception : public std::exception { std::string what_; int errno_; public: exult_exception (const char *what_arg): what_ (what_arg), errno_(errno) { } exult_exception (const std::string& what_arg): what_ (what_arg), errno_(errno) { } const char *what() const throw () { return what_.c_str(); } int get_errno(void) const { return errno_; } virtual ~exult_exception () throw() {} }; /* * A quit exception can be thrown to quit the program */ class quit_exception : public exult_exception { int result_; public: quit_exception (int result = 0): exult_exception ("Quit"), result_(result) { } int get_result(void) const { return result_; } }; /* * Classes which should not be replicatable throw an replication_exception */ class replication_exception : public exult_exception { public: replication_exception (const char *what_arg): exult_exception (what_arg) { } replication_exception (const std::string& what_arg): exult_exception (what_arg) { } }; // Some handy macros which you can use to make a class non-replicable #define UNREPLICATABLE_CLASS(NAME) NAME(const NAME &) { throw replication_exception( #NAME " cannot be replicated"); }; \ NAME &operator=(const NAME &) { throw replication_exception( #NAME " cannot be replicated"); return *this; } #define UNREPLICATABLE_CLASS_I(NAME,INIT) NAME(const NAME &) : INIT { throw replication_exception( #NAME " cannot be replicated"); }; \ NAME &operator=(const NAME &) { throw replication_exception( #NAME " cannot be replicated"); return *this; } /* * File errors */ class file_exception : public exult_exception { public: file_exception (const char *what_arg): exult_exception (what_arg) { } file_exception (const std::string& what_arg): exult_exception (what_arg) { } }; class file_open_exception : public file_exception { static const std::string prefix_; public: file_open_exception (const std::string& file): file_exception("Error opening file "+file) { } }; class file_write_exception : public file_exception { static const std::string prefix_; public: file_write_exception(const std::string& file): file_exception("Error writing to file "+file) { } }; class file_read_exception : public file_exception { static const std::string prefix_; public: file_read_exception(const std::string& file): file_exception("Error reading from file "+file) { } }; class wrong_file_type_exception : public file_exception { public: wrong_file_type_exception (const std::string& file, const std::string& type): file_exception("File "+file+" is not of type "+type) { } }; /* * Exception that gets fired when the user aborts something */ class UserBreakException { }; #endif exult-1.2/headers/common_types.h0000644000175000001440000000510707724430452012504 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef COMMON_TYPES_H #define COMMON_TYPES_H #ifdef HAVE_CONFIG_H # include #endif #include #ifdef BEOS // BeOS headers already define these types #include typedef int8 sint8; typedef int16 sint16; typedef int32 sint32; #else #ifndef EX_TYPE_INT8 # define EX_TYPE_INT8 char /* guaranteed by ISO */ #endif #ifndef EX_TYPE_INT16 # if (SIZEOF_SHORT == 2) # define EX_TYPE_INT16 short # elif (SIZEOF_INT == 2) # define EX_TYPE_INT16 int # else # error "Please make sure a 16 bit type is provided by exult_types.h" # endif #endif /* !EX_TYPE_INT16 */ #ifndef EX_TYPE_INT32 # if (SIZEOF_INT == 4) # define EX_TYPE_INT32 int # elif (SIZEOF_LONG == 4) # define EX_TYPE_INT32 long # elif (SIZEOF_LONG_LONG == 4) # define EX_TYPE_INT32 long long # else # error "Please make sure a 32 bit type is provided by exult_types.h" # endif #endif /* !EX_TYPE_INT32 */ typedef unsigned EX_TYPE_INT8 uint8; typedef unsigned EX_TYPE_INT16 uint16; typedef unsigned EX_TYPE_INT32 uint32; typedef signed EX_TYPE_INT8 sint8; typedef signed EX_TYPE_INT16 sint16; typedef signed EX_TYPE_INT32 sint32; #endif //BeOS /* * Empty string */ extern const std::string c_empty_string; // Debug #ifdef DEBUG # define COUT(x) do { std::cout << x << std::endl; std::cout.flush(); } while (0) # define CERR(x) do { std::cerr << x << std::endl; std::cerr.flush(); } while (0) #else # define COUT(x) do { } while(0) # define CERR(x) do { } while(0) #endif // Two very useful macros that one should use instead of pure delete; they will additionally // set the old object pointer to 0, thus helping prevent double deletes (not that "delete 0" // is a no-op. #define FORGET_OBJECT(x) do { delete x; x = 0; } while(0) #define FORGET_ARRAY(x) do { delete [] x; x = 0; } while(0) #endif exult-1.2/segfile.cc0000644000175000001440000000363507724430450010133 /* * segfile.cc - Handle access to to a data file consisting of segments. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "exceptions.h" #include "segfile.h" #include "utils.h" /* * Open file. */ Segment_file::Segment_file ( std::string nm // Path to file. ) : filename(nm), num_segments(0) { U7open(file, filename.c_str()); file.seekg(0x54); // Get # of segments. num_segments = Read4(file); if( !file.good() ) throw file_read_exception(filename); } /* * Read in a given segment. * * returns the data in a new allocated buffer so it should be freed by the caller. */ char* Segment_file::retrieve ( uint32 index, // Number desired. std::size_t& len ) { char *buffer; if (index >= num_segments) throw exult_exception("objnum too large in read_object()"); file.seekg(0x80 + 8*index); // Get to info. long offset = Read4(file); // Get offset, length. len = Read4(file); if (!len) throw file_read_exception(filename); file.seekg(offset); // Get to data. buffer = new char[len]; // Allocate buffer. file.read(buffer, len); // Read it. if( !file.good() ) throw file_read_exception(filename); return buffer; } exult-1.2/cheat_screen.h0000644000175000001440000000675607724430447011017 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CHEAT_SCREEN_H #define CHEAT_SCREEN_H class Game_window; class Image_buffer8; class Font; class Game_clock; class Actor; class CheatScreen { Actor *grabbed; static const char *schedules[33]; static const char *flag_names[64]; public: CheatScreen(); ~CheatScreen(); void show_screen(); void SetGrabbedActor (Actor *g) { grabbed = g; } void ClearThisGrabbedActor (Actor *g) const { if (g==grabbed) g = 0; } private: enum Cheat_Prompt { CP_Command = 0, CP_HitKey = 1, CP_NotAvail = 2, CP_InvalidNPC = 3, CP_InvalidCom = 4, CP_Canceled = 5, CP_ClockSet = 6, CP_InvalidTime = 7, CP_InvalidShape = 8, CP_InvalidValue = 9, CP_Created = 10, CP_ShapeSet = 11, CP_ValueSet = 12, CP_NameSet = 13, CP_WrongShapeFile = 14, CP_ChooseNPC = 16, CP_EnterValue = 17, CP_Minute = 18, CP_Hour = 19, CP_Day = 20, CP_Shape = 21, CP_Activity = 22, CP_XCoord = 23, CP_YCoord = 24, CP_Lift = 25, CP_GFlagNum = 26, CP_NFlagNum = 27, CP_Name = 32 }; Game_window* gwin; Image_buffer8* ibuf; Font* font; Game_clock *clock; int maxx, maxy; int centerx, centery; Palette pal; void SharedPrompt (char *input, const Cheat_Prompt &mode); bool SharedInput (char *input, int len, int &command, Cheat_Prompt &mode, bool &activate); void NormalLoop(); void NormalDisplay (); void NormalMenu(); void NormalActivate (char *input, int &command, Cheat_Prompt &mode); bool NormalCheck (char *input, int &command, Cheat_Prompt &mode, bool &activate); void ActivityDisplay (); Cheat_Prompt GlobalFlagLoop(int num); Cheat_Prompt TimeSetLoop(); Cheat_Prompt NPCLoop(int num); void NPCDisplay (Actor *actor, int &num); void NPCMenu(Actor *actor, int &num); void NPCActivate (char *input, int &command, Cheat_Prompt &mode, Actor *actor, int &num); bool NPCCheck (char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor, int &num); void FlagLoop(Actor *actor); void FlagMenu(Actor *actor); void FlagActivate (char *input, int &command, Cheat_Prompt &mode, Actor *actor); bool FlagCheck (char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor); Cheat_Prompt AdvancedFlagLoop(int flagnum, Actor *actor); void BusinessLoop(Actor *actor); void BusinessDisplay (Actor *actor); void BusinessMenu(Actor *actor); void BusinessActivate (char *input, int &command, Cheat_Prompt &mode, Actor *actor, int &time, int &prev); bool BusinessCheck (char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor, int &time); void StatLoop(Actor *actor); void StatMenu(Actor *actor); void StatActivate (char *input, int &command, Cheat_Prompt &mode, Actor *actor); bool StatCheck (char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor); }; #endif exult-1.2/Makefile.studio.mingw0000644000175000001440000001045510060711772012266 # Exult Studio makefile for use in Windows with mingw using GCC 3.2 and msys shell # The shell IS required! # Where is Exult Studio will be installed. U7PATH=C:/Ultima7 # Only used for snapshots STUDIOPATH=C:/Studio TOOLSPATH=C:/GimpPlugin SRC=. VPATH=$(SRC):$(SRC)/files:$(SRC)/shapes:$(SRC)/imagewin:$(SRC)/mapedit:$(SRC)/server:$(SRC)/objs:$(SRC)/conf # If this doesn't work, insert output of `pkg-config --cflags gtk+-win32-2.0` manually GTK_INCLUDES = `pkg-config --cflags gtk+-win32-2.0` # If this doesn't work, insert output of `pkg-config --libs gtk+-win32-2.0` manually GTK_LIBS = `pkg-config --libs gtk+-win32-2.0` # If this doesn't work, insert output of 'pkg-config --cflags libglade-2.0' manually LIBGLADE_INCLUDES = `pkg-config --cflags libglade-2.0` # If this doesn't work, insert output of 'pkg-config --libs libglade-2.0' manually LIBGLADE_LIBS = `pkg-config --libs libglade-2.0` # If this doesn't work, insert output of 'pkg-config --cflags freetype2' manually FREETYPE2_INCLUDES = `pkg-config --cflags freetype2` # If this doesn't work, insert output of 'pkg-config --libs freetype2' manually FREETYPE2_LIBS = `pkg-config --libs freetype2` # If this doesn't work, insert output of 'pkg-config --cflags gimp-2.0' manually GIMP_INCLUDES = `pkg-config --cflags gimp-2.0` # If this doesn't work, insert output of 'pkg-config --libs gimp-2.0' manually GIMP_LIBS = `pkg-config --libs gimp-2.0` INCLUDES= -I$(SRC) -I$(SRC)/shapes -I$(SRC)/mapedit -I$(SRC)/imagewin \ -I$(SRC)/files -I$(SRC)/headers -I$(SRC)/server -I$(SRC)/objs -I$(SRC)/conf $(GTK_INCLUDES) $(LIBGLADE_INCLUDES) $(FREETYPE2_INCLUDES) $(GIMP_INCLUDES) CPPFLAGS= -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DEXULT_DATADIR=\"data\" -DUSE_EXULTSTUDIO -DHAVE_PNG_H -DHAVE_FREETYPE2 $(INCLUDES) CXXFLAGS= -O2 -mms-bitfields -DHAVE_EXT_HASH_MAP -DHAVE_EXT_HASH_SET -DHAVE_SSTREAM CXX=g++ CFLAGS= -O2 -mms-bitfields CC=gcc LIBS=$(GTK_LIBS) $(LIBGLADE_LIBS) $(FREETYPE2_LIBS) -liberty -lole32 -lpng -luuid -lz -mwindows EXEC=exult_studio.exe EXP_FILE=exult_studio.exp SERVER_OBJS=objserial.o servemsg.o servewin32.o MAPEDIT_OBJS=chunklst.o combo.o eggedit.o compile.o execbox.o exult_studio.o locator.o npcedit.o \ objbrowse.o objedit.o paledit.o shapedraw.o shapefile.o shapegroup.o \ shapeedit.o shapelst.o studio.o FILES_OBJS=Flat.o Flex.o IFF.o listfiles.o msgfile.o Table.o U7file.o utils.o IMAGEWIN_OBJS=ibuf8.o imagebuf.o SHAPES_OBJS=font.o fontgen.o fontvga.o items.o pngio.o monstinf.o shapeinf.o shapevga.o shapewrite.o u7drag.o vgafile.o CONF_OBJS=Configuration.o XMLEntity.o MISC_OBJS=exultstudioico.o windrag.o OBJS=$(MAPEDIT_OBJS) $(FILES_OBJS) $(IMAGEWIN_OBJS) $(SHAPES_OBJS) $(SERVER_OBJS) $(CONF_OBJS) $(MISC_OBJS) $(EXEC): $(OBJS) $(EXP_FILE) $(CXX) $(EXP_FILE) -o $@ $(OBJS) $(LIBS) $(EXP_FILE): $(OBJS) dlltool --output-exp $@ $(OBJS) -D $(EXEC) exultstudioico.o: $(SRC)/win32/exultstudioico.rc $(SRC)/win32/exultstudio.ico windres --include-dir $(SRC)/win32 $(SRC)/win32/exultstudioico.rc $@ u7shp.exe : u7shp.o $(CXX) -o $(@) $+ $(GTK_LIBS) $(GIMP_LIBS) -mwindows allclean: clean clean: rm -f $(OBJS) $(EXP_FILE) $(EXEC) u7shp.exe u7shp.o install: $(EXEC) mkdir -p $(U7PATH) strip $(EXEC) -o $(U7PATH)/$(EXEC) mkdir -p $(U7PATH)/data cp mapedit/exult_studio.glade $(U7PATH)/data mkdir -p $(U7PATH)/data/estudio mkdir -p $(U7PATH)/data/estudio/new cp data/estudio/new/*.flx $(U7PATH)/data/estudio/new cp data/estudio/new/*.vga $(U7PATH)/data/estudio/new cp data/estudio/new/*.shp $(U7PATH)/data/estudio/new tools: u7shp.exe toolsinstall: tools strip u7shp.exe -o $(HOME)/u7shp.exe toolsdist: tools mkdir -p $(TOOLSPATH) strip u7shp.exe -o $(TOOLSPATH)/u7shp.exe cp mapedit/gimpwin32.txt $(TOOLSPATH) u2d $(TOOLSPATH)/*.txt dist: $(EXEC) mkdir -p $(STUDIOPATH) strip $(EXEC) -o $(STUDIOPATH)/$(EXEC) mkdir -p $(STUDIOPATH)/data cp docs/exult_studio.html $(STUDIOPATH) cp docs/exult_studio.txt $(STUDIOPATH) mkdir -p $(STUDIOPATH)/images cp docs/images/*.gif $(STUDIOPATH)/images cp docs/images/studio*.png $(STUDIOPATH)/images cp mapedit/exult_studio.glade $(STUDIOPATH)/data mkdir -p $(STUDIOPATH)/data/estudio mkdir -p $(STUDIOPATH)/data/estudio/new cp data/estudio/new/*.flx $(STUDIOPATH)/data/estudio/new cp data/estudio/new/*.vga $(STUDIOPATH)/data/estudio/new cp data/estudio/new/*.shp $(STUDIOPATH)/data/estudio/new u2d $(STUDIOPATH)/*.txt exult-1.2/actors.h0000644000175000001440000005145310003025430007631 /* * actors.h - Game actors. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_ACTORS #define INCL_ACTORS 1 #include "contain.h" #include "utils.h" // This is only included for Log2... #include "flags.h" class Image_window; class Game_window; class Npc_actor; class Actor_action; class Schedule; class Schedule_change; class Monster_info; class Monster_actor; class Weapon_info; class Dead_body; class Npc_timer_list; class Frames_sequence; class Animator; // The range of actors' rect. gumps: const int ACTOR_FIRST_GUMP = 57, ACTOR_LAST_GUMP = 68; /* * An actor: */ class Actor : public Container_game_object, public Time_sensitive { static Actor *editing; // NPC being edited by ExultStudio. protected: std::string name; // Its name. int usecode; // # of usecode function. bool usecode_assigned; // Usecode # explicitly assigned. bool unused; // If npc_num > 0, this NPC is unused // in the game. short npc_num; // # in Game_window::npcs list, or -1. short face_num; // Which shape for conversations. short party_id; // Index in party, or -1. int properties[12]; // Properties set/used in 'usecode'. unsigned char temperature; // Measure of coldness (0-63). short shape_save; // Our old shape, or -1. short oppressor; // NPC ID (>= 0) of oppressor, or -1. Game_object *target; // Who/what we're attacking. public: enum Attack_mode { // Setting from gump.+++++Save/restore. nearest = 0, weakest = 1, // Attack weakest. strongest = 2, beserk = 3, // Always attack, never retreat. protect = 4, // Protect NPC with halo. defend = 5, flank = 6, // Attempt to attack from side. flee = 7, random = 8, // Choose target at random. manual = 9 }; protected: // Party positions const static short party_pos[4][10][2]; Attack_mode attack_mode; // A frame sequence for each dir.: static Frames_sequence *avatar_frames[4]; static Frames_sequence *npc_frames[4]; Frames_sequence **frames; // Draw weapon in hand void paint_weapon(); unsigned char schedule_type; // Schedule type (Schedule_type). Tile_coord schedule_loc; // Location (x,y) of Shedule unsigned char next_schedule; // Used so correct schedule type // will be saved Schedule *schedule; // Current schedule. bool dormant; // I.e., off-screen. bool hit; // Just hit in combat. bool combat_protected; // 'Halo' on paperdoll screen. bool user_set_attack; // True if player set attack_mode. short alignment; // 'Feelings' towards Ava. See below. Game_object *spots[18]; // Where things can go. See 'Spots' // below for description. bool two_handed; // Carrying a two-handed item. bool two_fingered; // Carrying gauntlets (both fingers) unsigned char light_sources; // # of light sources readied. unsigned char usecode_dir; // Direction (0-7) for usecode anim. unsigned siflags:32; // 32 flags used in 'usecode'. unsigned type_flags:32; // 32 flags used in movement among other things unsigned char ident; int skin_color; Actor_action *action; // Controls current animation. int frame_time; // Time between frames in msecs. 0 if // actor not moving. int step_index; // Index into walking frames, 1 1st. Npc_timer_list *timers; // Timers for poison, hunger, etc. Rectangle weapon_rect; // Screen area weapon was drawn in. long rest_time; // # msecs. of not doing anything. void init(); // Clear stuff during construction. // Move and change frame. void movef(Map_chunk *old_chunk, Map_chunk *new_chunk, int new_sx, int new_sy, int new_frame, int new_lift); public: friend class Clear_hit; static void init_default_frames(); // Set usual frame sequence. Actor(const std::string &nm, int shapenum, int num = -1, int uc = -1); ~Actor(); // Blocked moving onto tile 't'? int is_blocked(Tile_coord& t, Tile_coord *f = 0); int ready_ammo(); // Find and ready appropriate ammo. void ready_best_weapon(); // Find best weapon and ready it. void unready_weapon(int spot); // Try to sheath weapon. // Force repaint of area taken. int add_dirty(int figure_rect = 0); void change_frame(int frnum); // Change frame & set to repaint. int figure_weapon_pos(int& weapon_x, int& weapon_y, int& weapon_frame); void use_food(); // Decrement food level. // Increment/decrement temperature. void check_temperature(bool freeze); // Get frame seq. for given dir. Frames_sequence *get_frames(int dir) { return frames[dir/2]; } int& get_step_index() // Get it (for updating). { return step_index; } // Get attack frames. int get_attack_frames(int weapon, bool projectile, int dir, signed char *frames) const; enum Alignment { // Describes alignment field. neutral = 0, friendly = 1, hostile = 2, unknown_align = 3 }; // Bees have this, & don't attack until // Spots where items are carried. enum Spots { // Index of each spot, starting at // upper, rt., going clkwise. head = 0, back = 1, belt = 2, lhand = 3, lfinger = 4, legs = 5, feet = 6, rfinger = 7, rhand = 8, torso = 9, neck = 10, ammo = 11, back2h_spot = 12, // SI (2 Handed weapons, Bedroll, // Bodies) shield_spot = 13, // SI (Sheild behind Backpack) ears_spot = 14, // SI cloak_spot = 15, // SI hands2_spot = 16, // SI (gloves, gauntlets) ucont_spot = 17, // SI Usecode Container lrhand = 100, // Special: uses lhand & rhand. - Used anymore? lrfinger = 101, // Special: uses lfinger & rfinger - Used anymore? special_spot = 102 // Special: SI non placeable }; int free_hand() const // Get index of a free hand, or -1. { // PREFER right hand. return two_handed ? -1 : (!spots[rhand] ? rhand : (!spots[lhand] ? lhand : -1)); } int free_finger() const // Get index of a free finger, or -1. { return two_fingered ? -1 : (!spots[lfinger] ? lfinger : (!spots[rfinger] ? rfinger : -1)); } inline bool is_two_handed() const { return two_handed; } inline bool is_two_fingered() const { return two_fingered; } int has_light_source() const // Carrying a torch? { return light_sources > 0; } Attack_mode get_attack_mode() { return attack_mode; } void set_attack_mode(Attack_mode amode, bool byuser = false) { attack_mode = amode; user_set_attack = byuser; } bool did_user_set_attack() const { return user_set_attack; } bool is_combat_protected() const { return combat_protected; } void set_combat_protected(bool v) { combat_protected = v; } int get_oppressor() const { return oppressor; } void set_oppressor(int opp) { oppressor = opp; } // This is not even a guess, it's a place holder enum Serpent_flags { // Bit #'s of flags: // petra = 4, // met = 5, // no_spell_casting = 6, naked = 8, // dont_move = 9 }; enum type_flags { tf_fly = 4, tf_walk = 5, tf_swim = 6, tf_ethereal = 7, tf_want_primary = 8, tf_sex = 9, tf_bleeding = 10, tf_in_party = 12, tf_in_action = 13, tf_conjured = 14, tf_summonned = 15 }; enum Item_properties { // Trying to figure out properties. strength = 0, // This is also max. health. dexterity = 1, intelligence = 2, health = 3, combat = 4, mana = 5, magic = 6, // Max. mana. training = 7, // Training points. exp = 8, // Experience. food_level = 9 }; enum Frames { // Frames 0-15. 16-31 are the same, // only S instead of N. standing = 0, step_right_frame = 1, step_left_frame = 2, ready_frame = 3, // Ready to fight? raise1_frame = 4, // 1-handed strikes. reach1_frame = 5, strike1_frame = 6, raise2_frame = 7, // 2-handed strikes. reach2_frame = 8, strike2_frame = 9, sit_frame = 10, bow_frame = 11, kneel_frame = 12, sleep_frame = 13, up_frame = 14, // Both hands reach up. out_frame = 15 // Both hands reach out. }; enum FIS_Type { // The types used in the call to fit_in_spot FIS_Other = 0, FIS_2Hand = 1, FIS_2Finger = 2, FIS_Spell = 3 }; int get_face_shapenum() const // Get "portrait" shape #. { return face_num; } // It's the NPC's #. int get_usecode() const { return usecode == -1 ? get_shapenum() : usecode; } Schedule *get_schedule() const { return schedule; } int get_frame_time() const // Return frame time if moving. { return frame_time; } void set_frame_time(int ftime) // Set walking speed. { frame_time = ftime; } void stand_at_rest(); // Stand (if not doing anyting else). void clear_rest_time() { rest_time = 0; } void resting(int msecs) // Increment rest time. { if ((rest_time += msecs) > 2000) stand_at_rest();// Stand (under certain conditions). } bool is_moving() const { return frame_time != 0; } bool is_dormant() const // Inactive (i.e., off-screen)? { return dormant; } bool is_dead() const { return (flags&(1<= 0 && prop < 12) ? properties[prop] : 0; } int get_effective_prop(int prop) const; bool is_dying() const // Dead when health below -1/3 str. { return properties[(int) health] < -(properties[(int) strength]/3); } int get_level() const // Get experience level. { return 1 + Log2(get_property(exp)/50); } Npc_timer_list *need_timers(); // Set/clear/get actor flag. virtual void set_flag(int flag); virtual void set_siflag(int flag); void set_type_flag(int flag); virtual void clear_flag(int flag); virtual void clear_siflag(int flag); void clear_type_flag(int flag); virtual int get_siflag(int flag) const; int get_type_flag(int flag) const; void set_type_flags(unsigned short tflags); int get_skin_color () const { return skin_color; } void set_skin_color (int color) { skin_color = color; set_actor_shape();} virtual int get_type_flags() const { return type_flags; } //++++++Is_dead() test messes up training. // unsigned char get_ident() { return is_dead() ? 0 : ident; } unsigned char get_ident() { return ident; } void set_ident(unsigned char id) { ident = id; } int get_temperature() const // Get/set measure of coldness. { return temperature; } void set_temperature(int t); int figure_warmth(); // Based on what's worn. bool is_unused() const // Free NPC? { return unused; } void set_unused(bool tf) { unused = tf; } int get_npc_num() const // Get its ID (1-num_npcs). { return npc_num; } // Get/set index within party. int get_party_id() const { return party_id; } void set_party_id(int i) { party_id = i; } // Set for Usecode animations. void set_usecode_dir(int d) { usecode_dir = d&7; } int get_usecode_dir() const { return usecode_dir; } virtual Actor *as_actor() // An actor? { return this; } void init_readied(); // Call Usecode to init. readied objs. // Remove an object. virtual void remove(Game_object *obj); // Add an object. virtual bool add(Game_object *obj, bool dont_check = false, bool combine = false); // Add to NPC 'readied' spot. virtual int add_readied(Game_object *obj, int index, int dont_check = 0, int force_pos = 0); virtual int find_readied(Game_object *obj); virtual Game_object *get_readied(int index) const { return index >= 0 && index < (int)(sizeof(spots)/sizeof(spots[0])) ? spots[index] : 0; } virtual void call_readied_usecode(int index, Game_object *obj, int eventid); virtual int get_max_weight(); // Get max. weight allowed. // Change member shape. virtual void change_member_shape(Game_object *obj, int newshape); // Move out of the way. virtual int move_aside(Actor *for_actor, int dir); // Get frame if rotated clockwise. virtual int get_rotated_frame(int quads); virtual int get_armor_points(); // Get total armor value. // Get total weapon value. virtual Weapon_info *get_weapon(int& points, int& shape); Weapon_info *get_weapon(int& points) { int sh; return get_weapon(points, sh); } static bool roll_to_win(int attacker, int defender); // Hit-point algorithm: bool figure_hit_points(Actor *attacker, int weapon_shape, int ammo_shape); // Under attack. virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0, int ammo_shape = 0); virtual void die(Actor *attacker); // We're dead. Actor *resurrect(Dead_body *body);// Bring back to life. Monster_actor *clone(); // Create another nearby to this. void mend_hourly(); // Restore HP's hourly. // Read from file. void read(DataSource* nfile, int num, bool has_usecode, bool& fix_unused); // Don't write out to IREG file. virtual void write_ireg(DataSource* out) { } virtual int get_ireg_size() { return 0; } void write(DataSource* nfile);// Write out (to 'npc.dat'). virtual void write_contents(DataSource* out); // Write contents void set_actor_shape(); // Set shape based on sex, skin color void set_polymorph(int shape); // Set a polymorph shape void set_polymorph_default(); // Set the default shape // Get the polymorph shape int get_polymorph () { return shape_save; } // Get the non polymorph shape (note, doesn't returned skin coloured shapes) // For usecode int get_shape_real(); // This does the same, but will return skin coloured shapes // For paperdolls/face stats int get_sexed_coloured_shape() { return shape_save!=-1?shape_save:get_shapenum(); } // Set schedule list. virtual void set_schedules(Schedule_change *list, int cnt) { } virtual void set_schedule_time_type(int time, int type) { } virtual void set_schedule_time_location(int time, int x, int y) { } virtual void remove_schedule(int time) { } virtual void get_schedules(Schedule_change *&list, int &cnt) { list = NULL, cnt = 0; } void show_inventory(); int inventory_shapenum(); bool was_hit() { return hit; } // Should be virtual??? void cache_out(); }; /* * Actor frame descriptions: 0 Standing 1 Walk 2 Walk 3 Beginning to attack 4-6 Attacking with one hand 7-9 Attacking with two hands 9 Also NPC shooting magic 10 Sitting down 11 Bending over (beginning to sit down) 12 Kneeling 11 Lying down 14 Casting spell (hands raised) 15 Casting spell (hands outstretched) */ /* * The main actor. */ class Main_actor : public Actor { public: Main_actor(const std::string &nm, int shapenum, int num = -1, int uc = -1) : Actor(nm, shapenum, num, uc) { frames = &avatar_frames[0]; } // For Time_sensitive: virtual void handle_event(unsigned long curtime, long udata); void get_followers(); // Get party to follow. // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame); // Update chunks after NPC moved. virtual void switched_chunks(Map_chunk *olist, Map_chunk *nlist); // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); virtual void die(Actor *attacker); // We're dead. }; /* * A non-player-character that one can converse (or fight) with: */ class Npc_actor : public Actor { unsigned char nearby; // Queued as a 'nearby' NPC. This is // to avoid being added twice. protected: unsigned char num_schedules; // # entries below. Schedule_change *schedules; // List of schedule changes. int find_schedule_change(int hour3); public: Npc_actor(const std::string &nm, int shapenum, int num = -1, int uc = -1); ~Npc_actor(); void set_nearby() // Set/clear/test 'nearby' flag. { nearby = true; } void clear_nearby() { nearby = false; } bool is_nearby() const { return nearby!=0; } // Set schedule list. virtual void set_schedules(Schedule_change *list, int cnt); virtual void set_schedule_time_type(int time, int type); virtual void set_schedule_time_location(int time, int x, int y); virtual void remove_schedule(int time); virtual void get_schedules(Schedule_change *&list, int &cnt); // Move and change frame. void movef(Map_chunk *old_chunk, Map_chunk *new_chunk, int new_sx, int new_sy, int new_frame, int new_lift); // Update schedule for new 3-hour time. virtual void update_schedule(int hour3, int backwards = 0, int delay = -1); // Render. virtual void paint(); // Run usecode function. virtual void activate(int event = 1); // For Time_sensitive: virtual void handle_event(unsigned long curtime, long udata); // Step onto an (adjacent) tile. virtual int step(Tile_coord t, int frame); // Remove/delete this object. virtual void remove_this(int nodel = 0); // Update chunks after NPC moved. virtual void switched_chunks(Map_chunk *olist, Map_chunk *nlist); // Move to new abs. location. virtual void move(int newtx, int newty, int newlift); virtual Npc_actor *as_npc() { return this; } }; /* * An actor's dead body: */ class Dead_body : public Container_game_object { short npc_num; // # of NPC it came from, or -1. public: Dead_body(int shapenum, int framenum, unsigned int tilex, unsigned int tiley, unsigned int lft, int n) : Container_game_object(shapenum, framenum, tilex, tiley, lft), npc_num(n) { } virtual ~Dead_body(); virtual int get_live_npc_num(); // Under attack. virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0, int ammo_shape = 0) { return this; } // Not affected. }; #endif exult-1.2/delobjs.h0000644000175000001440000000310107726531050007765 /* * delobjs.h - Game objects that have been removed, but need deleting. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DELOBJS_H #define DELOBJS_H 1 #include /* * "Less than" relation for objects */ class Less_objs { public: bool operator() (const Game_object *a, const Game_object *b) const { return a < b; } }; #define DELOBJ_DELAY (1000*60*3) /* 3 minutes. */ /* * A pool of removed game objects, waiting to be deleted, each with a * timestamp. */ class Deleted_objects : public std::map { public: Deleted_objects() : std::map () { } void insert(Game_object *obj) { (*this)[obj] = SDL_GetTicks() + DELOBJ_DELAY; } void flush(); // Delete them now. ~Deleted_objects() // Problems { flush(); } { } }; #endif /* DELOBJS_H */ exult-1.2/rect.h0000644000175000001440000000537607724430450007320 /* * rect.h - Rectangles. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef RECT_H #define RECT_H 1 #ifdef WIN32 #include #define Rectangle RECTX #endif /* * A rectangle: */ class Rectangle { public: // Let's make it all public. int x, y; // Position. int w, h; // Dimensions. Rectangle(int xin, int yin, int win, int hin) : x(xin), y(yin), w(win), h(hin) { } Rectangle() { } // An uninitialized one. // Is this point in it? int has_point(int px, int py) const { return (px >= x && px < x + w && py >= y && py < y + h); } // Add another to this one to get // a rect. that encloses both. Rectangle add(Rectangle& r2) const { int xend = x + w, yend = y + h; int xend2 = r2.x + r2.w, yend2 = r2.y + r2.h; Rectangle r; // Return this. r.x = x < r2.x ? x : r2.x; r.y = y < r2.y ? y : r2.y; r.w = (xend > xend2 ? xend : xend2) - r.x; r.h = (yend > yend2 ? yend : yend2) - r.y; return (r); } // Intersect another with this. Rectangle intersect(Rectangle& r2) const { int xend = x + w, yend = y + h; int xend2 = r2.x + r2.w, yend2 = r2.y + r2.h; Rectangle r; // Return this. r.x = x >= r2.x ? x : r2.x; r.y = y >= r2.y ? y : r2.y; r.w = (xend <= xend2 ? xend : xend2) - r.x; r.h = (yend <= yend2 ? yend : yend2) - r.y; return (r); } // Does it intersect another? int intersects(Rectangle r2) const { return (x >= r2.x + r2.w ? 0 : r2.x >= x + w ? 0 : y >= r2.y + r2.h ? 0 : r2.y >= y + h ? 0 : 1); } void shift(int deltax, int deltay) { x += deltax; y += deltay; } Rectangle& enlarge(int delta) // Add delta in each dir. { x -= delta; y -= delta; w += 2*delta; h += 2*delta; return *this; } int distance(int px, int py) // Get distance from a point (max. // dist. along x or y coord.) { int xdist = px <= x ? (x - px) : (px - x - w + 1); int ydist = py <= y ? (y - py) : (py - y - h + 1); int dist = xdist > ydist ? xdist : ydist; return dist < 0 ? 0 : dist; } }; #endif exult-1.2/gameclk.cc0000644000175000001440000001256107750412260010114 /* * gameclk.cc - Keep track of time. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include /* Debugging. */ #include "gameclk.h" #include "gamewin.h" #include "actors.h" #include "cheat.h" #include "game.h" /* * Set palette. */ void Game_clock::set_time_palette ( ) { Game_window *gwin = Game_window::get_instance(); Actor *main_actor = gwin->get_main_actor(); int new_palette; if (main_actor && main_actor->get_flag(Obj_flags::invisible)) { gwin->get_pal()->set(PALETTE_INVISIBLE); return; } if (cheat.in_infravision()) { gwin->get_pal()->set(PALETTE_DAY); return; } dungeon = gwin->is_in_dungeon(); if (dungeon || hour < 5) new_palette = PALETTE_NIGHT; else if (hour < 6) new_palette = PALETTE_DAWN; else if (hour < 19) new_palette = storm <= 0 ? PALETTE_DAY : PALETTE_DUSK; else if (hour < 21) new_palette = PALETTE_DUSK; else new_palette = PALETTE_NIGHT; if (light_source_level) { if (new_palette == PALETTE_NIGHT) new_palette = light_source_level == 1 ? PALETTE_DUSK : PALETTE_DAWN; else if (new_palette == PALETTE_DUSK) new_palette = PALETTE_DAWN; } // Gump mode, or light spell? if (gwin->is_special_light() && new_palette == PALETTE_NIGHT) new_palette = PALETTE_DAWN; gwin->get_pal()->set(new_palette); } /* * Set palette. Used for restoring a game. */ void Game_clock::set_palette ( ) { // Update palette to new time. set_time_palette(); } /* * Set the palette for a changed light source level. */ void Game_clock::set_light_source_level ( int lev ) { light_source_level = lev; set_time_palette(); } /* * Storm ending/starting. */ void Game_clock::set_storm ( bool onoff ) { storm += (onoff ? 1 : -1); set_time_palette(); // Update palette. } /* * Decrement food level and check hunger of the party members. */ void Game_clock::check_hunger ( ) { Game_window *gwin = Game_window::get_instance(); Actor *party[9]; // Get party + Avatar. int cnt = gwin->get_party(party, 1); for (int i = 0; i < cnt; i++) party[i]->use_food(); } static void Check_freezing ( ) { Game_window *gwin = Game_window::get_instance(); // Avatar's flag applies to party. bool freeze = gwin->get_main_actor()->get_flag(Obj_flags::freeze)!=false; Actor *party[9]; // Get party + Avatar. int cnt = gwin->get_party(party, 1); for (int i = 0; i < cnt; i++) party[i]->check_temperature(freeze); } /* * Increment clock. * * FOR NOW, skipping call to mend_npcs(). Not sure... */ void Game_clock::increment ( int num_minutes // # of minutes to increment. ) { Game_window *gwin = Game_window::get_instance(); int new_3hour, old_3hour, delta_3hour; long new_min; old_3hour = hour/3; // Remember current 3-hour period. num_minutes += time_factor/2; // Round to nearest 15 minutes. num_minutes -= num_minutes%time_factor; new_min = minute + num_minutes; hour += new_min/60; // Update hour. minute = new_min%60; day += hour/24; // Update day. hour %= 24; // Update palette to new time. set_time_palette(); new_3hour = hour/3; // New 3-hour period. delta_3hour = new_3hour - old_3hour; if (delta_3hour != 0) // In a new period? { // Update NPC schedules. if (Game::get_game_type() == SERPENT_ISLE) delta_3hour = 8; gwin->schedule_npcs(new_3hour, (delta_3hour +7)%8); } } /* * Advance clock. */ void Game_clock::handle_event ( unsigned long curtime, // Current time of day. long udata // ->game window. ) { Game_window *gwin = (Game_window *) udata; int min_old = minute; int hour_old = hour; // Time stopped? Don't advance. if (!gwin->is_time_stopped()) { minute += time_rate; if (Game::get_game_type() == SERPENT_ISLE) Check_freezing(); } while (minute >= 60) // advance to the correct hour (and day) { minute -= 60; if (++hour >= 24) { hour -= 24; day++; } set_time_palette(); gwin->mend_npcs(); // Restore HP's each hour. check_hunger(); // Use food, and print complaints. if (hour%3 == 0) // New 3-hour period? { // Update NPC schedules. gwin->schedule_npcs(hour/3); } } if ((hour != hour_old) || (minute/15 != min_old/15)) COUT("Clock updated to " << hour << ':' << minute); curtime += 60*1000/time_factor; // 15 changes per minute tqueue->add(curtime, this, udata); } /* * Fake an update to the next 3-hour period. */ void Game_clock::fake_next_period ( ) { minute = 0; hour = ((hour/3 + 1)*3); day += hour/24; // Update day. hour %= 24; Game_window *gwin = Game_window::get_instance(); set_time_palette(); check_hunger(); gwin->schedule_npcs(hour/3); gwin->mend_npcs(); // Just do it once, cheater. COUT("The hour is now " << hour); } exult-1.2/gamedat.cc0000644000175000001440000007076210054030531010106 /* * gamedat.cc - Create gamedat files from a savegame. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef WIN32 #ifndef UNDER_CE #include #endif #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include # include #endif #if (defined(XWIN) || defined(BEOS)) #include #elif defined(MACOS) #include #endif #include "exceptions.h" #include "fnames.h" #include "gamewin.h" #include "gameclk.h" #include "gamemap.h" #include "utils.h" #include "gump_utils.h" #include "game.h" #include "Flex.h" #include "databuf.h" #include "Newfile_gump.h" #include "Yesno_gump.h" #include "actors.h" #include "party.h" #include "version.h" #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::ifstream; using std::ios; using std::localtime; using std::memset; using std::ofstream; using std::ostream; using std::size_t; using std::strchr; using std::strcmp; using std::strcpy; using std::strlen; using std::strncpy; using std::time_t; using std::tm; using std::time_t; #endif // Save game compression level extern int save_compression; /* * Write out the gamedat directory from a saved game. * * Output: Aborts if error. */ void Game_window::restore_gamedat ( const char *fname // Name of savegame file. ) { // Check IDENTITY. char *id = get_game_identity(fname); char *static_identity = get_game_identity(INITGAME); // Note: "*" means an old game. if(!id || (*id != '*' && strcmp(static_identity, id) != 0)) { std::string msg("Wrong identity '"); msg += id; msg += "'. Open anyway?"; int ok = Yesno_gump::ask(msg.c_str()); if (!ok) return; } // Check for a ZIP file first #ifdef HAVE_ZIP_SUPPORT if (restore_gamedat_zip(fname) != false) return; #endif ifstream in_stream; #ifdef RED_PLASMA // Display red plasma during load... setup_load_palette(); #endif U7mkdir("", 0755); // Create dir. if not already there. Don't // use GAMEDAT define cause that's got a // trailing slash try { U7open(in_stream, fname); // Open file; throws an exception } catch(const file_exception & f) { if (!Game::is_editing()) // Ok if map-editing. throw f; std::cerr << "Warning (map-editing): Couldn't open '" << fname << "'" << endl; return; } StreamDataSource in(&in_stream); U7remove (USEDAT); U7remove (USEVARS); U7remove (U7NBUF_DAT); U7remove (NPC_DAT); U7remove (MONSNPCS); U7remove (FLAGINIT); U7remove (GWINDAT); U7remove (IDENTITY); U7remove (GSCHEDULE); U7remove ("/flags.flg"); U7remove (GSCRNSHOT); U7remove (GSAVEINFO); U7remove (GNEWGAMEVER); U7remove (GEXULTVER); U7remove (KEYRINGDAT); cout.flush(); in.seek(0x54); // Get to where file count sits. int numfiles = in.read4(); in.seek(0x80); // Get to file info. // Read pos., length of each file. long *finfo = new long[2*numfiles]; int i; for (i = 0; i < numfiles; i++) { finfo[2*i] = in.read4(); // The position, then the length. finfo[2*i + 1] = in.read4(); } for (i = 0; i < numfiles; i++) // Now read each file. { // Get file length. int len = finfo[2*i + 1] - 13; if (len <= 0) continue; in.seek(finfo[2*i]); // Get to it. char fname[50]; // Set up name. strcpy(fname, GAMEDAT); in.read(&fname[sizeof(GAMEDAT) - 1], 13); int namelen = strlen(fname); // Watch for names ending in '.'. if (fname[namelen - 1] == '.') fname[namelen - 1] = 0; ofstream out; U7open(out, fname); // Now read the file. char *buf = new char[len]; in.read(buf, len); out.write(buf, len); // Then write it out. delete [] buf; if (!out.good()) abort("Error writing '%s'.", fname); out.close(); CYCLE_RED_PLASMA(); } delete [] finfo; cout.flush(); #ifdef RED_PLASMA load_palette_timer = 0; #endif } /* * Write out the gamedat directory from a saved game. * * Output: Aborts if error. */ void Game_window::restore_gamedat ( int num // 0-9, currently. ) { char fname[50]; // Set up name. snprintf(fname, 50, SAVENAME, num, Game::get_game_type() == BLACK_GATE ? "bg" : "si"); restore_gamedat(fname); } /* * List of 'gamedat' files to save (in addition to 'iregxx'): */ static const char *bgsavefiles[] = { GSCRNSHOT, GSAVEINFO, // MUST BE FIRST!! IDENTITY, // MUST BE #2 GEXULTVER, GNEWGAMEVER, NPC_DAT, MONSNPCS, USEVARS, USEDAT, FLAGINIT, GWINDAT, GSCHEDULE }; static const int bgnumsavefiles = sizeof(bgsavefiles)/sizeof(bgsavefiles[0]); static const char *sisavefiles[] = { GSCRNSHOT, GSAVEINFO, // MUST BE FIRST!! IDENTITY, // MUST BE #2 GEXULTVER, GNEWGAMEVER, NPC_DAT, MONSNPCS, USEVARS, USEDAT, FLAGINIT, GWINDAT, GSCHEDULE, KEYRINGDAT }; static const int sinumsavefiles = sizeof(sisavefiles)/sizeof(sisavefiles[0]); /* * Save a single file into an IFF repository. * * Output: Length of data saved. * Errors reported. */ static long Savefile ( ostream& out, // Write here. const char *fname // Name of file to save. ) { ifstream in_stream; try { U7open(in_stream, fname); } catch (exult_exception& e) { if (Game::is_editing()) return 0; // Newly developed game. throw e; } StreamDataSource in(&in_stream); long len = in.getSize(); in.seek(0); char namebuf[13]; // First write 13-byte name. memset(namebuf, 0, sizeof(namebuf)); const char *base = strchr(fname, '/');// Want the base name. if (!base) base = strchr(fname, '\\'); if (base) base++; else base = fname; strncpy(namebuf, base, sizeof(namebuf)); out.write(namebuf, sizeof(namebuf)); char *buf = new char[len]; // Get it all at once. in.read(buf, len); out.write(buf, len); delete [] buf; if (!in_stream.good()) throw file_read_exception(fname); return len + 13; // Include filename. } static long SavefileFromDataSource( ostream& out, // write here DataSource& source, // read from here const char *fname // store data using this filename ) { long len = source.getSize(); char namebuf[13]; memset(namebuf, 0, sizeof(namebuf)); strncpy(namebuf, fname, sizeof(namebuf)); out.write(namebuf, sizeof(namebuf)); char *buf = new char[len]; source.read(buf, len); out.write(buf, len); delete [] buf; return len + 13; } /* * Save 'gamedat' into a given file. * * Output: 0 if error (reported). */ void Game_window::save_gamedat ( const char *fname, // File to create. const char *savename // User's savegame name. ) { // First check for compressed save game #ifdef HAVE_ZIP_SUPPORT if (save_compression > 0 && save_gamedat_zip(fname, savename) != false) return; #endif // setup correct file list int numsavefiles = (Game::get_game_type() == BLACK_GATE) ? bgnumsavefiles : sinumsavefiles; const char **savefiles = (Game::get_game_type() == BLACK_GATE) ? bgsavefiles : sisavefiles; ofstream out; U7open(out, fname); // Doing all IREG's + what's listed. int count = 12*12 + numsavefiles; // Use samename for title. Flex_writer flex(out, savename, count); int i; // Start with listed files. for (i = 0; i < numsavefiles; i++) { Savefile(out, savefiles[i]); flex.mark_section_done(); } // Now the Ireg's. for (int schunk = 0; schunk < 12*12; schunk++, i++) { char iname[80]; Savefile(out, map->get_schunk_file_name(U7IREG, schunk, iname)); flex.mark_section_done(); } bool result = flex.close(); // Write it all out. if (!result) // ++++Better error system needed?? throw file_write_exception(fname); return; } /* * Save to one of the numbered savegame files (and update save_names). * * Output: false if error (reported). */ void Game_window::save_gamedat ( int num, // 0-9, currently. const char *savename // User's savegame name. ) { char fname[50]; // Set up name. snprintf(fname, 50, SAVENAME, num, Game::get_game_type() == BLACK_GATE ? "bg" : "si"); save_gamedat(fname, savename); if (num >=0 && num < 10) { delete [] save_names[num]; // Update name save_names[num] = newstrdup(savename); } } /* * Read in the saved game names. */ void Game_window::read_save_names ( ) { for (size_t i = 0; i < sizeof(save_names)/sizeof(save_names[0]); i++) { char fname[50]; // Set up name. snprintf(fname, 50, SAVENAME, i, Game::get_game_type() == BLACK_GATE ? "bg" : "si"); ifstream in; try { U7open(in, fname); char buf[0x50]; // It's at start of file. memset(buf, 0, sizeof(buf)); in.read(buf, sizeof(buf) - 1); if (in.good()) // Okay if file not there. save_names[i] = newstrdup(buf); else save_names[i] = newstrdup(""); in.close(); } catch(const file_exception & f) { save_names[i] = newstrdup(""); } } } void Game_window::write_saveinfo() { ofstream out_stream; int i, j; int save_count = 1; try { ifstream in; U7open(in, GSAVEINFO); // Open file; throws an exception StreamDataSource ds(&in); ds.skip(10); // Skip 10 bytes. save_count += ds.read2(); in.close(); } catch(const file_exception & f) { } int party_size = party_man->get_count()+1; time_t t = std::time(0); struct tm *timeinfo = localtime (&t); U7open(out_stream, GSAVEINFO); // Open file; throws an exception - Don't care StreamDataSource out(&out_stream); // This order must match struct SaveGame_Details // Time that the game was saved out.write1(timeinfo->tm_min); out.write1(timeinfo->tm_hour); out.write1(timeinfo->tm_mday); out.write1(timeinfo->tm_mon+1); out.write2(timeinfo->tm_year + 1900); // The Game Time that the save was done at out.write1(clock->get_minute()); out.write1(clock->get_hour()); out.write2(clock->get_day()); out.write2(save_count); out.write1(party_size); out.write1(0); // Unused out.write1(timeinfo->tm_sec); // 15 // Packing for the rest of the structure for (j = reinterpret_cast(&(((SaveGame_Details *)0)->reserved0)); j < sizeof(SaveGame_Details); j++) out.write1(0); for (i=0; iget_member(i-1)); char name[18]; std::string namestr = npc->get_npc_name(); strncpy (name, namestr.c_str(), 18); out.write(name, 18); out.write2(npc->get_shapenum()); out.write4(npc->get_property(Actor::exp)); out.write4(npc->get_flags()); out.write4(npc->get_flags2()); out.write1(npc->get_property(Actor::food_level)); out.write1(npc->get_property(Actor::strength)); out.write1(npc->get_property(Actor::combat)); out.write1(npc->get_property(Actor::dexterity)); out.write1(npc->get_property(Actor::intelligence)); out.write1(npc->get_property(Actor::magic)); out.write1(npc->get_property(Actor::mana)); out.write1(npc->get_property(Actor::training)); out.write2(npc->get_property(Actor::health)); out.write2(npc->get_shapefile()); // Packing for the rest of the structure for (j = reinterpret_cast(&(((SaveGame_Party *)0)->reserved1)); j < sizeof(SaveGame_Party); j++) out.write1(0); } out_stream.close(); // Save Shape Shape_file *map = create_mini_screenshot(); U7open(out_stream, GSCRNSHOT); // Open file; throws an exception - Don't care map->save(&out); out_stream.close(); delete map; // Current Exult version U7open(out_stream, GEXULTVER); getVersionInfo(out_stream); out_stream.close(); // Exult version that started this game if (!U7exists(GNEWGAMEVER)) { U7open(out_stream, GNEWGAMEVER); out_stream << "Unknown" << endl; out_stream.close(); } } void Game_window::read_saveinfo(DataSource *in, SaveGame_Details *&details, SaveGame_Party *& party) { int i; details = new SaveGame_Details; // This order must match struct SaveGame_Details // Time that the game was saved details->real_minute = in->read1(); details->real_hour = in->read1(); details->real_day = in->read1(); details->real_month = in->read1(); details->real_year = in->read2(); // The Game Time that the save was done at details->game_minute = in->read1(); details->game_hour = in->read1(); details->game_day = in->read2(); details->save_count = in->read2(); details->party_size = in->read1(); details->unused = in->read1(); // Unused details->real_second = in->read1(); // 15 // Packing for the rest of the structure in->skip(sizeof(SaveGame_Details) - reinterpret_cast(&(((SaveGame_Details *)0)->reserved0))); party = new SaveGame_Party[details->party_size]; for (i=0; i<8 && iparty_size ; i++) { in->read(party[i].name, 18); party[i].shape = in->read2(); party[i].exp = in->read4(); party[i].flags = in->read4(); party[i].flags2 = in->read4(); party[i].food = in->read1(); party[i].str = in->read1(); party[i].combat = in->read1(); party[i].dext = in->read1(); party[i].intel = in->read1(); party[i].magic = in->read1(); party[i].mana = in->read1(); party[i].training = in->read1(); party[i].health = in->read2(); party[i].shape_file = in->read2(); // Packing for the rest of the structure in->skip (sizeof(SaveGame_Party) - reinterpret_cast(&(((SaveGame_Party *)0)->reserved1))); } } bool Game_window::get_saveinfo(int num, char *&name, Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party) { char fname[50]; // Set up name. snprintf(fname, 50, SAVENAME, num, Game::get_game_type() == BLACK_GATE ? "bg" : "si"); // First check for compressed save game #ifdef HAVE_ZIP_SUPPORT if (get_saveinfo_zip(fname, name, map, details, party) != false) return true; #endif ifstream in_stream; U7open(in_stream, fname); // Open file; throws an exception StreamDataSource in(&in_stream); // in case of an error. // Always try to Read Name char buf[0x50]; memset(buf, 0, sizeof(buf)); in.read(buf, sizeof(buf) - 1); name = new char [strlen (buf)+1]; strcpy (name, buf); // Isn't a flex, can't actually read it if (!Flex::is_flex(&in)) return false; // Now get dir info in.seek(0x54); // Get to where file count sits. int numfiles = in.read4(); in.seek(0x80); // Get to file info. // Read pos., length of each file. long *finfo = new long[2*numfiles]; int i; for (i = 0; i < numfiles; i++) { finfo[2*i] = in.read4(); // The position, then the length. finfo[2*i + 1] = in.read4(); } // Always first two entires for (i = 0; i < 2; i++) // Now read each file. { // Get file length. int len = finfo[2*i + 1] - 13; if (len <= 0) continue; in.seek(finfo[2*i]); // Get to it. char fname[50]; // Set up name. strcpy(fname, GAMEDAT); in.read(&fname[sizeof(GAMEDAT) - 1], 13); int namelen = strlen(fname); // Watch for names ending in '.'. if (fname[namelen - 1] == '.') fname[namelen - 1] = 0; if (!strcmp (fname, GSCRNSHOT)) { char *buf = new char[len]; in.read(buf, len); BufferDataSource ds(buf, len); map = new Shape_file(&ds); delete [] buf; } else if (!strcmp (fname, GSAVEINFO)) { read_saveinfo (&in, details, party); } } in_stream.close(); delete [] finfo; return true; } void Game_window::get_saveinfo(Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party) { try { ifstream in; U7open(in, GSAVEINFO); // Open file; throws an exception StreamDataSource ds(&in); read_saveinfo (&ds, details, party); in.close(); } catch(const file_exception & f) { details = NULL; party = NULL; } try { ifstream in; U7open(in, GSCRNSHOT); // Open file; throws an exception StreamDataSource ds(&in); map = new Shape_file(&ds); in.close(); } catch(const file_exception & f) { // yes, this is weird, but seems to work-around a compiler // problem... (gcc-2.95.2-12mdk) -wjp map = 0; map = 0; } } /* * Return string from IDENTITY in a savegame. * * Output: ->identity if found. * 0 if error (or may throw exception). * "*" if older savegame. */ char *Game_window::get_game_identity(const char *savename) { char *game_identity = 0; #ifdef HAVE_ZIP_SUPPORT game_identity = get_game_identity_zip(savename); if (game_identity) return game_identity; #endif ifstream in_stream; try { U7open(in_stream, savename); // Open file. } catch (const exult_exception &e) { if (Game::is_editing()) { // Okay if creating a new game. std::string titlestr = Game::get_gametitle(); return newstrdup(titlestr.c_str()); } throw e; } StreamDataSource in(&in_stream); in.seek(0x54); // Get to where file count sits. int numfiles = in.read4(); in.seek(0x80); // Get to file info. // Read pos., length of each file. sint32 *finfo = new sint32[2*numfiles]; int i; for (i = 0; i < numfiles; i++) { finfo[2*i] = in.read4(); // The position, then the length. finfo[2*i + 1] = in.read4(); } for (i = 0; i < numfiles; i++) // Now read each file. { // Get file length. int len = finfo[2*i + 1] - 13; if (len <= 0) continue; in.seek(finfo[2*i]); // Get to it. char fname[50]; // Set up name. in.read(fname, 13); if (!strcmp("identity",fname)) { game_identity = new char[len]; in.read(game_identity, len); // Truncate identity char *ptr = game_identity; for(; (*ptr!=0x1a && *ptr!=0x0d); ptr++) ; *ptr = 0; break; } } delete [] finfo; return game_identity; } // Zip file support #ifdef HAVE_ZIP_SUPPORT #include "files/zip/unzip.h" #include "files/zip/zip.h" static const char *remove_dir(const char *fname) { const char *base = strchr(fname, '/');// Want the base name. if (!base) base = strchr(fname, '\\'); if (base) return base+1; return fname; } bool Game_window::get_saveinfo_zip(const char *fname, char *&name, Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party) { // If a flex, so can't read it if (Flex::is_flex(fname)) return false; std::string filestr = get_system_path(fname); unzFile unzipfile = unzOpen(filestr.c_str()); if (!unzipfile) return false; // Name comes from comment char namebuf[0x50]; if (unzGetGlobalComment(unzipfile, namebuf, 0x50) <= 0) strncpy (namebuf, "UNNAMED", 0x50); name = new char [strlen (namebuf)+1]; strcpy (name, namebuf); // Things we need unz_file_info file_info; char *buf = 0; // Get the screenshot first if (unzLocateFile(unzipfile, remove_dir(GSCRNSHOT), 2) == UNZ_OK) { unzGetCurrentFileInfo(unzipfile, &file_info, NULL, 0, NULL, 0, NULL, 0); buf = new char[file_info.uncompressed_size]; unzOpenCurrentFile(unzipfile); unzReadCurrentFile(unzipfile, buf, file_info.uncompressed_size); if (unzCloseCurrentFile(unzipfile) == UNZ_OK) { BufferDataSource ds(buf, file_info.uncompressed_size); map = new Shape_file(&ds); } delete [] buf; } // Now saveinfo if (unzLocateFile(unzipfile, remove_dir(GSAVEINFO), 2) == UNZ_OK) { unzGetCurrentFileInfo(unzipfile, &file_info, NULL, 0, NULL, 0, NULL, 0); buf = new char[file_info.uncompressed_size]; unzOpenCurrentFile(unzipfile); unzReadCurrentFile(unzipfile, buf, file_info.uncompressed_size); if (unzCloseCurrentFile(unzipfile) == UNZ_OK) { BufferDataSource ds(buf, file_info.uncompressed_size); read_saveinfo (&ds, details, party); } delete [] buf; } unzClose (unzipfile); return true; } // Level 2 Compression bool Game_window::Restore_level2 (void *uzf) { unzFile unzipfile = static_cast(uzf); char oname[50]; // Set up name. char *oname2 = oname+sizeof(GAMEDAT) - 1; // Set up name. char size_buffer[4]; int size; strcpy(oname, GAMEDAT); if (unzOpenCurrentFile(unzipfile) != UNZ_OK) { std::cerr << "Couldn't open current file" << std::endl; return false; } while (!unzeof(unzipfile)) { // Read Filename oname2[12] = 0; if (unzReadCurrentFile(unzipfile, oname2, 12) != 12) { std::cerr << "Couldn't read for filename" << std::endl; return false; } // Check to see if was are at the end of the list if (*oname2 == 0) break; // Get file length. if (unzReadCurrentFile(unzipfile, size_buffer, 4) != 4) { std::cerr << "Couldn't read for size" << std::endl; return false; } BufferDataSource ds(size_buffer, 4); size = ds.read4(); if (size) { // Watch for names ending in '.'. int namelen = strlen(oname); if (oname[namelen - 1] == '.') oname[namelen - 1] = 0; // Now read the file. char *buf = new char[size]; if (unzReadCurrentFile(unzipfile, buf, size) != size) { delete [] buf; std::cerr << "Couldn't read for buf" << std::endl; return false; } // Then write it out. ofstream out; U7open(out, oname); out.write(buf, size); delete [] buf; if (!out.good()) { std::cerr << "out was bad" << std::endl; return false; } out.close(); CYCLE_RED_PLASMA(); } } return unzCloseCurrentFile(unzipfile) == UNZ_OK; } /* * Write out the gamedat directory from a saved game. * * Output: Aborts if error. */ bool Game_window::restore_gamedat_zip ( const char *fname // Name of savegame file. ) { // If a flex, so can't read it try { if (Flex::is_flex(fname)) return false; } catch(const file_exception & f) { return false; // Ignore if not found. } #ifdef RED_PLASMA // Display red plasma during load... setup_load_palette(); #endif std::string filestr = get_system_path(fname); unzFile unzipfile = unzOpen(filestr.c_str()); if (!unzipfile) return false; U7mkdir("", 0755); // Create dir. if not already there. Don't // use GAMEDAT define cause that's got a // trailing slash U7remove (USEDAT); U7remove (USEVARS); U7remove (U7NBUF_DAT); U7remove (NPC_DAT); U7remove (MONSNPCS); U7remove (FLAGINIT); U7remove (GWINDAT); U7remove (IDENTITY); U7remove (GSCHEDULE); U7remove ("/flags.flg"); U7remove (GSCRNSHOT); U7remove (GSAVEINFO); U7remove (GNEWGAMEVER); U7remove (GEXULTVER); U7remove (KEYRINGDAT); cout.flush(); unz_global_info global; unzGetGlobalInfo(unzipfile, &global); // Now read each file. char oname[50]; // Set up name. char *oname2 = oname + sizeof(GAMEDAT) - 1; strcpy(oname, GAMEDAT); do { unz_file_info file_info; unzGetCurrentFileInfo(unzipfile, &file_info, oname2, 13, NULL, 0, NULL, 0); // Get file length. int len = file_info.uncompressed_size; if (len <= 0) continue; // Level 2 compression handling if (!std::strcmp("GAMEDAT", oname2)) { if (Restore_level2(unzipfile) == false) abort("Error reading level2 from zip '%s'.", fname); continue; } // Watch for names ending in '.'. int namelen = strlen(oname); if (oname[namelen - 1] == '.') oname[namelen - 1] = 0; // Open the file in the zip if (unzOpenCurrentFile(unzipfile) != UNZ_OK) abort("Error opening current from zipfile '%s'.", fname); // Now read the file. char *buf = new char[len]; if (unzReadCurrentFile(unzipfile, buf, len) != len) abort("Error reading current from zip '%s'.", fname); // now write it out. ofstream out; U7open(out, oname); out.write(buf, len); if (!out.good()) abort("Error writing to '%s'.", oname); out.close(); // Close the file in the zip if (unzCloseCurrentFile(unzipfile) != UNZ_OK) abort("Error closing current in zip '%s'.", fname); delete [] buf; CYCLE_RED_PLASMA(); } while (unzGoToNextFile(unzipfile) == UNZ_OK); unzClose(unzipfile); cout.flush(); #ifdef RED_PLASMA load_palette_timer = 0; #endif return true; } // Level 1 Compression static bool Save_level1 (zipFile zipfile, const char *fname) { ifstream in; try { U7open (in, fname); } catch (exult_exception& e) { if (Game::is_editing()) return false; // Newly developed game. throw e; } StreamDataSource ds(&in); unsigned int size = ds.getSize(); char *buf = new char[size]; ds.read(buf, size); zipOpenNewFileInZip (zipfile, remove_dir(fname), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION); zipWriteInFileInZip (zipfile, buf, size); delete [] buf; return zipCloseFileInZip (zipfile) == ZIP_OK; } // Level 2 Compression static bool Begin_level2 (zipFile zipfile) { return zipOpenNewFileInZip (zipfile, "GAMEDAT", NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) == ZIP_OK; } static bool Save_level2 (zipFile zipfile, const char *fname) { ifstream in; try { U7open (in, fname); } catch (exult_exception& e) { if (Game::is_editing()) return false; // Newly developed game. throw e; } StreamDataSource ds(&in); uint32 size = ds.getSize(); char *buf = new char[size<13?13:size]; // We want at least 13 bytes // Filename first memset (buf, 0, 13); strncpy (buf, remove_dir(fname), 13); int err = zipWriteInFileInZip (zipfile, buf, 12); // Size of the file if (err == ZIP_OK) { // Must be platform independant BufferDataSource bds(buf, 4); bds.write4(size); err = zipWriteInFileInZip (zipfile, buf, 4); } // Now the actual file if (err == ZIP_OK) { ds.read(buf, size); err = zipWriteInFileInZip (zipfile, buf, size); } delete [] buf; return err == ZIP_OK; } static bool End_level2 (zipFile zipfile) { uint32 zeros = 0; // Write a terminator (12 zeros) int err = zipWriteInFileInZip (zipfile, &zeros, 4); if (err == ZIP_OK) err = zipWriteInFileInZip (zipfile, &zeros, 4); if (err == ZIP_OK) err = zipWriteInFileInZip (zipfile, &zeros, 4); return zipCloseFileInZip (zipfile) == ZIP_OK; } bool Game_window::save_gamedat_zip ( const char *fname, // File to create. const char *savename // User's savegame name. ) { // If no compression return if (save_compression < 1) return false; // setup correct file list int numsavefiles = (Game::get_game_type() == BLACK_GATE) ? bgnumsavefiles : sinumsavefiles; const char **savefiles = (Game::get_game_type() == BLACK_GATE) ? bgsavefiles : sisavefiles; // Name { ofstream out; char title[0x50]; memset (title, 0, 0x50); std::strncpy (title, savename, 0x50); U7open(out, fname); out.write(title, 0x50); out.close(); } std::string filestr = get_system_path(fname); zipFile zipfile = zipOpen(filestr.c_str(), 1); // Level 1 Compression if (save_compression != 2) { for (int i = 0; i < numsavefiles; i++) Save_level1(zipfile, savefiles[i]); // Now the Ireg's. for (int schunk = 0; schunk < 12*12; schunk++) { char iname[80]; Save_level1(zipfile, map->get_schunk_file_name(U7IREG, schunk, iname)); } } // Level 2 Compression else { // Keep saveinfo, screenshot, identity using normal compression // There are always files 0 - 2 Save_level1(zipfile, GSCRNSHOT); Save_level1(zipfile, GSAVEINFO); Save_level1(zipfile, IDENTITY); Begin_level2(zipfile); for (int i = 3; i < numsavefiles; i++) Save_level2(zipfile, savefiles[i]); // Now the Ireg's. for (int schunk = 0; schunk < 12*12; schunk++) { char iname[80]; Save_level2(zipfile, map->get_schunk_file_name( U7IREG, schunk, iname)); } End_level2(zipfile); } // ++++Better error system needed?? if (zipClose(zipfile, savename) != ZIP_OK) throw file_write_exception(fname); return true; } /* * Return string from IDENTITY in a savegame. * * Output: ->identity string. * 0 if error. * "*" if not found. */ char *Game_window::get_game_identity_zip ( const char *savename ) { // If a flex, so can't read it try { if (Flex::is_flex(savename)) return 0; } catch(const file_exception & f) { return 0; // Ignore if not found. } unzFile unzipfile = unzOpen(get_system_path(savename).c_str()); if (!unzipfile) return 0; // Find IDENTITY, ignoring case. if (unzLocateFile(unzipfile, "identity", 2) != UNZ_OK) { unzClose(unzipfile); return "*"; // Old game. Return wildcard. } // Open the file in the zip if (unzOpenCurrentFile(unzipfile) != UNZ_OK) { unzClose(unzipfile); throw file_read_exception(savename); } // Now read the file. char buf[256]; int cnt = unzReadCurrentFile(unzipfile, buf, sizeof(buf) - 1); if (cnt <= 0) { unzCloseCurrentFile(unzipfile); unzClose(unzipfile); throw file_read_exception(savename); } buf[cnt] = 0; // 0-delimit. unzCloseCurrentFile(unzipfile); unzClose(unzipfile); char *ptr = buf; for(; (*ptr != 0 && *ptr!=0x1a && *ptr!=0x0d); ptr++) ; *ptr = 0; return newstrdup(buf); } #endif exult-1.2/server/0000777000175000001440000000000010062225334007561 5exult-1.2/server/server.cc0000644000175000001440000003227607762470521011341 /** ** Server.cc - Server functions for Exult (NOT ExultStudio). ** ** Written: 5/2/2001 - JSF **/ /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include // All the ifdefs aren't useful if we don't do this #endif // only if compiled with "exult studio support" #ifdef USE_EXULTSTUDIO #include #include #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_TIME_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #include #ifdef _AIX #include #endif #if HAVE_NETDB_H #include #endif #ifndef WIN32 #include #endif #include "server.h" #include "servemsg.h" #include "utils.h" #include "egg.h" #include "actors.h" #include "gamewin.h" #include "gamemap.h" #include "chunkter.h" #include "cheat.h" #include "objserial.h" #include "effects.h" #ifdef USECODE_DEBUGGER #include "debugserver.h" #endif #ifdef WIN32 #include "servewin32.h" #include "cheat.h" #endif using std::cout; using std::cerr; using std::endl; /* * Sockets, etc. */ extern int xfd; // X-windows fd. int listen_socket = -1; // Listen here for map-editor. int client_socket = -1; // Socket to the map-editor. int highest_fd = -1; // Largest fd + 1. #ifdef __sun__ // Solaris doesn't know PF_LOCAL #define PF_LOCAL PF_UNIX #endif /* * Set the 'highest_fd' value to 1 + . */ inline void Set_highest_fd ( ) { highest_fd = xfd; // Figure highest to listen to. if (listen_socket > highest_fd) highest_fd = listen_socket; if (client_socket > highest_fd) highest_fd = client_socket; highest_fd++; // Select wants 1+highest. } /* * Initialize server for map-editing. Call this AFTER xfd has been set. */ void Server_init ( ) { #ifndef WIN32 // Get location of socket file. std::string servename(""); char *home = getenv("HOME"); if (home) // Use $HOME/.exult/exultserver { // if possible. servename = home; servename += "/.exult"; if (U7exists(servename.c_str())) servename += "/exultserver"; else servename = ""; } if (servename == "") servename = get_system_path("/exultserver"); // Make sure it isn't there. unlink(servename.c_str()); #if HAVE_GETADDRINFOX // Don't use the old deprecated network API int r; struct addrinfo hints,*ai; memset(&hints,0,sizeof(hints)); hints.ai_flags=AI_PASSIVE; r=getaddrinfo( 0, servename.c_str(), &hints, &ai); if(r!=0) { cerr << "getaddrinfo(): "<ai_family, ai->ai_socktype, ai->ai_protocol); #else // Deprecated listen_socket = socket(PF_LOCAL, SOCK_STREAM, 0); #endif if (listen_socket < 0) perror("Failed to open map-editor socket"); else { #if HAVE_GETADDRINFOX if(bind(listen_socket,ai->ai_addr,ai->ai_addrlen) == -1 || listen(listen_socket,1) == -1) #else struct sockaddr_un addr; addr.sun_family = AF_UNIX; strcpy(addr.sun_path, servename.c_str()); if (bind(listen_socket, (struct sockaddr *) &addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) == -1 || listen(listen_socket, 1) == -1) #endif { perror("Bind or listen on socket failed"); close(listen_socket); listen_socket = -1; } else // Set to be non-blocking. { cout << "Listening on socket " << listen_socket << endl; fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL) | O_NONBLOCK); } #if HAVE_GETADDRINFOX freeaddrinfo(ai); #endif } Set_highest_fd(); #else listen_socket = client_socket = -1; std::string servename = get_system_path(""); if (Exult_server::create_pipe(servename.c_str())) listen_socket = 1; #endif } /* * Close the server. */ void Server_close ( ) { #ifdef WIN32 Exult_server::close_pipe(); listen_socket = client_socket = -1; #else // unlink socket file+++++++ #endif } /* * A message from a client is available, so handle it. */ static void Handle_client_message ( int& fd // Socket to client. May be closed. ) { unsigned char data[Exult_server::maxlength]; Exult_server::Msg_type id; int datalen = Exult_server::Receive_data(fd, id, data, sizeof(data)); if (datalen < 0) return; unsigned char *ptr = &data[0]; Game_window *gwin = Game_window::get_instance(); switch (id) { case Exult_server::obj: Game_object::update_from_studio(&data[0], datalen); break; case Exult_server::egg: Egg_object::update_from_studio(&data[0], datalen); break; case Exult_server::npc: Actor::update_from_studio(&data[0], datalen); break; case Exult_server::info: { unsigned char data[Exult_server::maxlength]; unsigned char *ptr = &data[0]; Game_info_out(client_socket, Exult_server::version, cheat.get_edit_lift(), gwin->skip_lift, cheat.in_map_editor(), cheat.show_tile_grid(), gwin->get_map()->was_map_modified(), (int) cheat.get_edit_mode()); break; } case Exult_server::write_map: gwin->write_map(); // Send feedback?+++++ break; case Exult_server::read_map: gwin->read_map(); break; case Exult_server::map_editing_mode: { int onoff = Read2(ptr); if ((onoff != 0) != cheat.in_map_editor()) cheat.toggle_map_editor(); break; } case Exult_server::tile_grid: { int onoff = Read2(ptr); if ((onoff != 0) != cheat.show_tile_grid()) cheat.toggle_tile_grid(); break; } case Exult_server::edit_lift: { int lift = Read2(ptr); cheat.set_edit_lift(lift); break; } case Exult_server::reload_usecode: gwin->reload_usecode(); break; case Exult_server::locate_terrain: { int tnum = Read2(ptr); int cx = (short) Read2(ptr); int cy = (short) Read2(ptr); bool up = *ptr++ ? true : false; bool okay = gwin->get_map()->locate_terrain(tnum, cx, cy, up); ptr = &data[2]; // Set back reply. Write2(ptr, cx); Write2(ptr, cy); ptr++; // Skip 'up' flag. *ptr++ = okay ? 1 : 0; Exult_server::Send_data(client_socket, Exult_server::locate_terrain, data, ptr - data); break; } case Exult_server::swap_terrain: { int tnum = Read2(ptr); bool okay = gwin->get_map()->swap_terrains(tnum); *ptr++ = okay ? 1 : 0; Exult_server::Send_data(client_socket, Exult_server::swap_terrain, data, ptr - data); break; } case Exult_server::insert_terrain: { int tnum = (short) Read2(ptr); bool dup = *ptr++ ? true : false; bool okay = gwin->get_map()->insert_terrain(tnum, dup); *ptr++ = okay ? 1 : 0; Exult_server::Send_data(client_socket, Exult_server::insert_terrain, data, ptr - data); break; } case Exult_server::delete_terrain: { int tnum = (short) Read2(ptr); bool okay = gwin->get_map()->delete_terrain(tnum); *ptr++ = okay ? 1 : 0; Exult_server::Send_data(client_socket, Exult_server::delete_terrain, data, ptr - data); break; } case Exult_server::send_terrain: { // Send back #, total, 512-bytes data. int tnum = (short) Read2(ptr); Write2(ptr, gwin->get_map()->get_num_chunk_terrains()); Chunk_terrain *ter = gwin->get_map()->get_terrain(tnum); ter->write_flats(ptr); // Serialize it. ptr += 512; // I just happen to know the length... Exult_server::Send_data(client_socket, Exult_server::send_terrain, data, ptr - data); break; } case Exult_server::terrain_editing_mode: { // 1=on, 0=off, -1=undo. int onoff = (short) Read2(ptr); // skip_lift==0 <==> terrain-editing. gwin->skip_lift = onoff == 1 ? 0 : 16; static char *msgs[3] = {"Terrain-Editing Aborted", "Terrain-Editing Done", "Terrain-Editing Enabled"}; if (onoff == 0) // End/commit. gwin->get_map()->commit_terrain_edits(); else if (onoff == -1) gwin->get_map()->abort_terrain_edits(); if (onoff >= -1 && onoff <= 1) gwin->get_effects()->center_text(msgs[onoff + 1]); gwin->set_all_dirty(); break; } case Exult_server::set_edit_shape: { int shnum = (short) Read2(ptr); int frnum = (short) Read2(ptr); cheat.set_edit_shape(shnum, frnum); break; } case Exult_server::view_pos: { int tx = Read4(ptr); if (tx == -1) // This is a query? { gwin->send_location(); break; } int ty = Read4(ptr); // +++Later int txs = Read4(ptr); // int tys = Read4(ptr); // int scale = Read4(ptr); // Only set if chunk changed. if (tx/c_tiles_per_chunk != gwin->get_scrolltx()/c_tiles_per_chunk || ty/c_tiles_per_chunk != gwin->get_scrollty()/c_tiles_per_chunk) { gwin->set_scrolls(tx, ty); gwin->set_all_dirty(); } break; } case Exult_server::set_edit_mode: { int md = Read2(ptr); if (md >= 0 && md <= 3) cheat.set_edit_mode((Cheat::Map_editor_mode) md); break; } case Exult_server::hide_lift: { int lift = Read2(ptr); gwin->skip_lift = lift; gwin->set_all_dirty(); break; } case Exult_server::reload_shapes: Shape_manager::get_instance()->reload_shapes(Read2(ptr)); break; case Exult_server::unused_shapes: { // Send back shapes not used in game. unsigned char data[Exult_server::maxlength]; int sz = 1024/8; // Gets bits for unused shapes. sz = sz > sizeof(data) ? sizeof(data) : sz; gwin->get_map()->find_unused_shapes(data, sz); Exult_server::Send_data(client_socket, Exult_server::unused_shapes, data, sz); break; } case Exult_server::locate_shape: { int shnum = Read2(ptr); bool up = *ptr++ ? true : false; bool okay = gwin->locate_shape(shnum, up); ptr = &data[2]; // Send back reply. ptr++; // Skip 'up' flag. *ptr++ = okay ? 1 : 0; Exult_server::Send_data(client_socket, Exult_server::locate_shape, data, ptr - data); break; } case Exult_server::cut: // Cut/copy. cheat.cut(*ptr != 0); break; case Exult_server::paste: cheat.paste(); break; case Exult_server::npc_info: Write2(ptr, gwin->get_num_npcs()); Write2(ptr, gwin->get_unused_npc()); Exult_server::Send_data(client_socket, Exult_server::npc_info, data, ptr - data); break; case Exult_server::edit_selected: { unsigned char basic = *ptr; const Game_object_vector& sel = cheat.get_selected(); if (!sel.empty()) if (basic) // Basic obj. props? sel.back()->Game_object::edit(); else sel.back()->edit(); break; } case Exult_server::set_edit_chunknum: cheat.set_edit_chunknum((short) Read2(ptr)); break; case Exult_server::game_pos: { Tile_coord pos = gwin->get_main_actor()->get_tile(); Write2(ptr, pos.tx); Write2(ptr, pos.ty); Write2(ptr, pos.tz); Exult_server::Send_data(client_socket, Exult_server::game_pos, data, ptr - data); break; } #ifdef USECODE_DEBUGGER case Exult_server::usecode_debugging: Handle_debug_message(&data[0], datalen); break; #endif } } /* * Delay for a fraction of a second, or until there's data available. * If a server request comes, it's handled here. */ void Server_delay ( Message_handler handle_message ) { #ifndef WIN32 extern int xfd; fd_set rfds; struct timeval timer; timer.tv_sec = 0; timer.tv_usec = 50000; // Try 1/50 second. FD_ZERO(&rfds); FD_SET(xfd, &rfds); if (listen_socket >= 0) FD_SET(listen_socket, &rfds); if (client_socket >= 0) FD_SET(client_socket, &rfds); // Wait for timeout or event. if (select(highest_fd, &rfds, 0, 0, &timer) > 0) { // Something's come in. if (listen_socket >= 0 && FD_ISSET(listen_socket, &rfds)) { // New client connection. // For now, just one at a time. if (client_socket >= 0) close(client_socket); client_socket = accept(listen_socket, 0, 0); cout << "Accept returned client_socket = " << client_socket << endl; // Non-blocking. fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL) | O_NONBLOCK); Set_highest_fd(); } if (client_socket >= 0 && FD_ISSET(client_socket, &rfds)) { handle_message(client_socket); // Client gone? if (client_socket == -1) Set_highest_fd(); } } #else if (listen_socket == -1) return; if (Exult_server::is_broken()) { std::cout << "Client disconnected." << endl; Exult_server::disconnect_from_client(); Exult_server::setup_connect(); client_socket = -1; } SleepEx(20, TRUE); if (client_socket == -1) { // Only do this in map edit mode if (!cheat.in_map_editor()) return; std::string servename = get_system_path(""); if (!Exult_server::try_connect_to_client(servename.c_str())) return; else client_socket = 1; std::cout << "Connected to client" << endl; } if (Exult_server::peek_pipe() > 0) handle_message(client_socket); if (Exult_server::is_broken()) { if (Exult_server::notify_connection_lost()) std::cout << "Client disconnected." << endl; Exult_server::disconnect_from_client(); Exult_server::setup_connect(); client_socket = -1; } #endif } void Server_delay() { Server_delay(Handle_client_message); } #endif exult-1.2/server/servewin32.h0000644000175000001440000000263407424024620011665 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Win32 Only file #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include namespace Exult_server { // Hack functions int write(int file, const void *v, unsigned int len); int read(int file, void *v, unsigned int len); int close(int file); // Server Functions bool create_pipe (const char *static_path); void setup_connect(); bool try_connect_to_client(const char *static_path); void disconnect_from_client(); void close_pipe(); // Client Functions int try_connect_to_server (const char *static_path); void disconnect_from_server(); // General Functions int peek_pipe(); bool is_broken(); bool notify_connection_lost(); bool is_win9x(); }; #endif exult-1.2/server/servemsg.cc0000644000175000001440000000627307477466424011676 /** ** Servemsg.cc - Server msgs. ** NOTE: This is for inclusion by both client and server. ** ** Written: 5/28/2001 - JSF **/ /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include /* For debugging msgs. */ #include "servemsg.h" #ifndef ALPHA_LINUX_CXX #include #endif #ifdef WIN32 #include "servewin32.h" #endif using std::cout; using std::cerr; using std::endl; namespace Exult_server { /* * Send data. * * Output: -1 if error. */ int Send_data ( int socket, Msg_type id, unsigned char *data, int datalen ) { #ifdef USE_EXULTSTUDIO unsigned char buf[maxlength + hdrlength]; buf[0] = magic&0xff; // Store magic (low-byte first). buf[1] = (magic>>8)&0xff; buf[2] = datalen&0xff; // Data length. buf[3] = (datalen>>8)&0xff; buf[4] = id; if (datalen > 0) std::memcpy(&buf[5], data, datalen); // The data itself. int len = datalen + hdrlength; return (write(socket, buf, len) == len ? 0 : -1); #else /* USE_EXULTSTUDIO */ return -1; #endif /* USE_EXULTSTUDIO */ } /* * Read message from client. * * Output: Length of data, else -1. */ int Receive_data ( int& socket, // Closed, set to -1 if disconnected. Msg_type& id, // ID returned. unsigned char *data, int datalen ) { #ifdef USE_EXULTSTUDIO unsigned char buf[hdrlength]; int len = read(socket, buf, 2); // Get magic. if (!len) // Closed? { close(socket); socket = -1; return -1; } if (len == -1) // Nothing available? return -1; int magic = buf[0] + (buf[1]<<8); if (magic != Exult_server::magic) { cout << "Bad magic read" << endl; return -1; } if (read(socket, buf, 3) != 3) { cout << "Couldn't read length+type" << endl; return -1; } int dlen = buf[0] | (buf[1]<<8); // Message type. id = (Exult_server::Msg_type) buf[2]; if (dlen > Exult_server::maxlength || dlen > datalen) { cout << "Length " << datalen << " exceeds max" << endl; //+++++++++Eat the chars. return -1; } datalen = read(socket, data, dlen); // Read data. if (datalen < dlen) { cout << "Failed to read all " << dlen << " bytes" << endl; return -1; } return datalen; #else /* USE_EXULTSTUDIO */ return -1; #endif /* USE_EXULTSTUDIO */ } bool wait_for_response(int socket, int ms) { #if defined(WIN32) && defined(USE_EXULTSTUDIO) int ticks = GetTickCount(); while(GetTickCount() < ticks+ms) { if (peek_pipe() > 0) return true; SleepEx(1, TRUE); } if (peek_pipe() > 0) return true; return false; #endif return true; } } exult-1.2/server/objserial.h0000644000175000001440000001214707501001231011615 /** ** Objserial.h - Object serialization. ** ** Written: 5/25/2001 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OBJSERIAL_H #define OBJSERIAL_H 1 #include #include "utils.h" #include "servemsg.h" class Serial_out { unsigned char *& buf; public: Serial_out(unsigned char *& b) : buf(b) { } Serial_out& operator<<(int v) { Write4(buf, v); return *this; } Serial_out& operator<<(unsigned long v) { Write4(buf, v); return *this; } Serial_out& operator<<(short v) { Write2(buf, v); return *this; } Serial_out& operator<<(bool v) { *buf++ = (v ? 1 : 0); return *this; } Serial_out& operator<<(unsigned char c) { *buf++ = c; return *this; } Serial_out& operator<<(std::string& s); }; /* * Decode. */ class Serial_in { unsigned char *& buf; public: Serial_in(unsigned char *& b) : buf(b) { } Serial_in& operator<<(int& v) { v = Read4(buf); return *this; } Serial_in& operator<<(unsigned long& v) { v = Read4(buf); return *this; } Serial_in& operator<<(short& v) { v = Read2(buf); return *this; } Serial_in& operator<<(bool &v) { v = *buf++ ? true : false; return *this; } Serial_in& operator<<(unsigned char &c) { c = *buf++; return *this; } Serial_in& operator<<(std::string& s); }; extern int Object_out ( int fd, // Socket. Exult_server::Msg_type id, // Message id. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int quality, std::string name ); extern int Object_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& quality, std::string& name ); extern int Egg_object_out ( int fd, // Socket. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int type, int criteria, int probability, int distance, bool nocturnal, bool once, bool hatched, bool auto_reset, int data1, int data2 ); extern int Egg_object_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& type, int& criteria, int& probability, int& distance, bool& nocturnal, bool& once, bool& hatched, bool& auto_reset, int& data1, int& data2 ); struct Serial_schedule // For passing a schedule change. { short time; // 0-7 (3-hour period). short type; // Schedule type (mostly 0-31). int tx, ty; // Tile to go to. }; int Npc_actor_out ( int fd, // Socket. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int face, std::string name, short npc_num, short ident, int usecode, int *properties, // 12 entries. short attack_mode, short alignment, unsigned long oflags, // Object flags. unsigned long siflags, // Extra flags for SI. unsigned long type_flags, // Movement flags. short num_schedules, // # of schedule changes. Serial_schedule *schedules // Schedule changes. ); int Npc_actor_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& face, std::string& name, short& npc_num, short& ident, int& usecode, int *properties, // Must have room for 12. short& attack_mode, short& alignment, unsigned long& oflags, // Object flags. unsigned long& siflags, // Extra flags for SI. unsigned long& type_flags, // Movement flags. short& num_schedules, // # of schedule changes. Serial_schedule *schedules // Schedule changes. Room for 8. ); extern int Game_info_out ( int fd, // Socket. int version, // Server/client version. int edit_lift, // Lift being edited. int hide_lift, // Lift being hidden. bool map_editing, // In 'map-editing' mode. bool tile_grid, // Showing tile grid. bool map_modified, // Map was changed. int edit_mode // Mode we're in. ); extern int Game_info_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. int& version, // Server/client version. int& edit_lift, // Lift being edited. int& hide_lift, // Lift being hidden. bool& map_editing, // In 'map-editing' mode. bool& tile_grid, // Showing tile grid. bool& map_modified, // Map was changed. int& edit_mode // Mode we're in. ); #endif exult-1.2/server/Makefile.am0000644000175000001440000000064507500166354011547 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files \ -I$(srcdir)/../objs -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../usecode \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libserver.la libserver_la_SOURCES = \ objserial.cc \ objserial.h \ servemsg.cc \ servemsg.h \ server.cc \ server.h \ servewin32.cc \ servewin32.h CLEANFILES = *~ exult-1.2/server/Makefile.in0000644000175000001440000002427010061527066011555 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files \ -I$(srcdir)/../objs -I$(srcdir)/../imagewin -I$(srcdir)/../shapes \ -I$(srcdir)/../usecode \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libserver.la libserver_la_SOURCES = \ objserial.cc \ objserial.h \ servemsg.cc \ servemsg.h \ server.cc \ server.h \ servewin32.cc \ servewin32.h CLEANFILES = *~ subdir = server mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libserver_la_LDFLAGS = libserver_la_LIBADD = am_libserver_la_OBJECTS = objserial.lo servemsg.lo server.lo \ servewin32.lo libserver_la_OBJECTS = $(am_libserver_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/objserial.Plo $(DEPDIR)/servemsg.Plo \ @AMDEP_TRUE@ $(DEPDIR)/server.Plo $(DEPDIR)/servewin32.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libserver_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libserver_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu server/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libserver.la: $(libserver_la_OBJECTS) $(libserver_la_DEPENDENCIES) $(CXXLINK) $(libserver_la_LDFLAGS) $(libserver_la_OBJECTS) $(libserver_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/objserial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/servemsg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/servewin32.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/server/servemsg.h0000644000175000001440000000662107762470521011523 /** ** Servemsg.h - Server msgs. ** NOTE: This is for inclusion by both client and server. ** ** Written: 5/3/2001 - JSF **/ #ifndef INCL_SERVEMSG #define INCL_SERVEMSG 1 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * An entry sent between client and server will have the following format: * Bytes Description 0-1 Magic. 2-3 Length of the data, low-byte first. 4 Message type. Defined below. 5- Data. */ namespace Exult_server { const unsigned short magic = 0xf381; const int maxlength = 600; // Big enough to hold a 'terrain'. const int hdrlength = 5; const int version = 0; // Sent with 'info' message. enum Msg_type { say = 0, // For testing. Data is text. obj = 1, // Generic object. egg = 2, // Egg_object. npc = 3, // Editing an NPC. user_responded = 4, // User performed requested action. cancel = 5, // Cancel operation. info = 6, // Game info. request/response. See // Game_info_xxx in objserial.h. write_map = 7, // Save map. read_map = 8, // Read map. map_editing_mode = 9, // 1 to turn it on, 0 for off. tile_grid = 10, // 1 to show grid, 0 for off. edit_lift = 11, // Lift passed: 0-13. reload_usecode = 12, // Reload patched usecode. locate_terrain = 13, // Locate desired chunk terrain. swap_terrain = 14, // Swap two terrains. insert_terrain = 15, // Insert new chunk terrain. delete_terrain = 16, // Delete (unused) terrain. send_terrain = 17, // Send 512-byte terrain to client. terrain_editing_mode = 18, // 1 to turn on, 0 for off, -1 to undo. set_edit_shape = 19, // Set shape/frame to 'paint' with. view_pos = 20, // Tile loc., size, scale of what's // shown in gamewin. Sent both ways. set_edit_mode = 21, // Move(0), paint(1), select(2). combo_pick = 22, // Sending shape to add to combo. hide_lift = 23, // Lift passed: 1-16. reload_shapes = 24, // Reload a .vga file. unused_shapes = 25, // Find unused shapes in game. locate_shape = 26, // Find shape in world. cut = 27, // Cut/copy. paste = 28, // ... from clipboard. select_status = 29, // Flags: selection, clipboard avail. npc_info = 30, // Get #NPC's, first unused. edit_selected = 31, // Edit selected object. set_edit_chunknum = 32, // Set chunk# to paint with. game_pos = 33, // Returns tx, ty, tz of main char. usecode_debugging = 128 }; // I/O routines: int Send_data ( int socket, Msg_type id, unsigned char *data = 0, // For just sending id. int datalen = 0 ); int Receive_data ( int& socket, // Closed, set to -1 if disconnected. Msg_type& id, // ID returned. unsigned char *data, int datalen ); // Wait for given ms for a response. return false if no response bool wait_for_response(int socket, int ms); }// Exult_server namespace. #endif /* INCL_SERVEMSG */ exult-1.2/server/servewin32.cc0000644000175000001440000003564607710040236012033 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Win32 Only file #ifdef HAVE_CONFIG_H # include #endif #if defined(WIN32) && defined(USE_EXULTSTUDIO) #include /* For debugging msgs. */ #include /* For debugging msgs. */ #include "servemsg.h" #include "servewin32.h" using std::cout; using std::cerr; using std::endl; namespace Exult_server { static HANDLE hPipeRead = INVALID_HANDLE_VALUE; static HANDLE hPipeWrite = INVALID_HANDLE_VALUE; static OVERLAPPED oOverlap; // Overlap structure static LPOVERLAPPED lpOverlap = 0; // Pointer to overlap structure static OVERLAPPED oOverlapCon; // Overlap structure static LPOVERLAPPED lpOverlapCon = 0; // Pointer to overlap structure static BOOL bWinNT = FALSE; static BOOL bClient = FALSE; static BOOL bBroken = FALSE; static BOOL bNotifyDis = FALSE; static const char * const pipe_name = "\\\\.\\pipe\\exultserver-"; static const char * const mail_server = "\\\\.\\mailslot\\exultserver-"; static const char * const mail_client = "\\\\.\\mailslot\\exultclient-"; // static Functions static char *get_pipe_name(const char *static_path, const char * const pipe_name = Exult_server::pipe_name, bool ms = false) { // Check to make sure that the pipe name hasn't been passed to us if (!std::strncmp(static_path, "\\\\.\\pipe\\", std::strlen("\\\\.\\pipe\\"))) { char *path = new char[std::strlen(static_path)+1]; return std::strcpy(path, static_path); } // Check to make sure that the mailslot name hasn't been passed to us if (!std::strncmp(static_path, "\\\\.\\mailslot\\", std::strlen("\\\\.\\mailslot\\"))) { char *path = new char[std::strlen(static_path)+1]; return std::strcpy(path, static_path); } int num_chars = GetShortPathName(static_path, NULL, 0); int head_len = std::strlen(pipe_name); char *actual_path; if (num_chars) { char *temp = new char[num_chars+1]; GetShortPathName(static_path, temp, num_chars+1); num_chars = GetFullPathName(temp, 0, NULL, NULL); actual_path = new char[num_chars+head_len+1]; char *temp2; GetFullPathName(temp, num_chars+1, actual_path+head_len, &temp2); } else { cout << "Unable to find actual static path" << endl; return 0; } std::memcpy (actual_path, pipe_name,head_len); if (!ms){ for (char *temp = actual_path+head_len; *temp; temp++) if (*temp == '\\') *temp = '/'; } else { for (char *temp = actual_path+head_len; *temp; temp++) if (*temp == '/') *temp = '\\'; else if (*temp == ':') *temp = '_'; } if (std::strlen(actual_path) > 255)actual_path[255] = 0; while (actual_path[std::strlen(actual_path)-1] == '/') actual_path[std::strlen(actual_path)-1] = 0; while (actual_path[std::strlen(actual_path)-1] == '\\') actual_path[std::strlen(actual_path)-1] = 0; return actual_path; } static void detect_winnt() { OSVERSIONINFO info; info.dwOSVersionInfoSize = sizeof (info); GetVersionEx (&info); // Platform is NT if (info.dwPlatformId == 2 && (info.dwMajorVersion > 5 || (info.dwMajorVersion == 5 && info.dwMinorVersion >= 1))) bWinNT = TRUE; } static bool setup_overlap() { memset(&oOverlap,0, sizeof (oOverlap)); memset(&oOverlapCon,0, sizeof (oOverlapCon)); // Platform is NT if (bWinNT) { // Create the overlap event oOverlap.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL); lpOverlap = &oOverlap; oOverlapCon.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL); lpOverlapCon = &oOverlapCon; return true; } return false; } static void free_overlap() { if (oOverlap.hEvent) CloseHandle(oOverlap.hEvent); oOverlap.hEvent = 0; lpOverlap = 0; if (oOverlapCon.hEvent) CloseHandle(oOverlapCon.hEvent); oOverlapCon.hEvent = 0; lpOverlapCon = 0; } // This sets up mailslots for the interprocess coms on Win9x static bool setup_server_mailslots(const char *static_path, bool both) { // Create read frst if (hPipeRead == INVALID_HANDLE_VALUE) { char *server_name = Exult_server::get_pipe_name(static_path,mail_server, true); hPipeRead = CreateMailslot(server_name, 1024, 0, NULL); if (hPipeRead == INVALID_HANDLE_VALUE) { std::cout << "Unable to create mailslot : " << server_name << " Code " << GetLastError() << std::endl; delete [] server_name ; return false; } //cout << "Created mailslot. Name " << server_name << std::endl; delete [] server_name ; if (!both) return true; } // Now attempt to create read if (hPipeWrite == INVALID_HANDLE_VALUE) { char *client_name = Exult_server::get_pipe_name(static_path,mail_client, true); hPipeWrite = CreateFile (client_name, // Pipe Name GENERIC_WRITE, // Desired Access FILE_SHARE_READ, // Share Mode NULL, // Security Att OPEN_EXISTING, // Creation Disposition FILE_ATTRIBUTE_NORMAL, // Flags and Attributes NULL); // TemplateFile if (hPipeWrite == INVALID_HANDLE_VALUE) { //std::cout << "Unable to connect to mailslot: " << client_name <<" Code " << GetLastError() << std::endl; delete [] client_name; return false; } //std::cout << "Connected to mailslot. Name " << client_name << std::endl; delete [] client_name ; } return true; } // This sets up mailslots for the interprocess coms on Win9x static bool setup_client_mailslots(const char *static_path) { // Create write frst if (hPipeWrite == INVALID_HANDLE_VALUE) { char *server_name = Exult_server::get_pipe_name(static_path,mail_server, true); hPipeWrite = CreateFile (server_name, // Pipe Name GENERIC_WRITE, // Desired Access FILE_SHARE_READ, // Share Mode NULL, // Security Att OPEN_EXISTING, // Creation Disposition FILE_ATTRIBUTE_NORMAL, // Flags and Attributes NULL); // TemplateFile if (hPipeWrite == INVALID_HANDLE_VALUE) { //std::cout << "Unable to connect to mailslot: " << server_name <<" Code " << GetLastError() << std::endl; delete [] server_name; return false; } //std::cout << "Connected to mailslot. Name " << server_name << std::endl; delete [] server_name ; } // Now attempt to create read if (hPipeRead == INVALID_HANDLE_VALUE) { char *client_name = Exult_server::get_pipe_name(static_path,mail_client, true); hPipeRead = CreateMailslot(client_name, 1024, 0, NULL); if (hPipeRead == INVALID_HANDLE_VALUE) { std::cout << "Unable to create mailslot : " << client_name << " Code " << GetLastError() << std::endl; delete [] client_name ; CloseHandle(hPipeWrite); hPipeWrite = INVALID_HANDLE_VALUE; return false; } //std::cout << "Created mailslot. Name " << client_name << std::endl; delete [] client_name ; } return true; } // Hack functions int write(int file, const void *v, unsigned int len) { DWORD num_written; BOOL failed = !WriteFile(hPipeWrite, v, len, &num_written, lpOverlap); const unsigned char *data = (unsigned char *)v; //cout << "write = " << len << endl; //for (int q = 0 ; q < len; q++) cout << ((int) data [q]) << " "; //cout << endl; if ((!bWinNT && failed) || GetLastError() == ERROR_BROKEN_PIPE) { std::cout << "Broken!" << std::endl; bBroken = TRUE; return 0; } if (num_written == 0) return -1; return num_written; } static unsigned char buf[2048]; static unsigned int offset = 2048; static unsigned int num_left = 0; int read_win9x(int file, unsigned char *v, unsigned int len) { DWORD num_read; //std::cout << "The Num wanted is " << len << std::endl; // Buffer is empty, fill it if (num_left == 0) { int total = peek_pipe(); if (total >= 2048) { std::cerr << "Buffer too small. Read failed" << std::endl; return 0; } else if (total == 0) { return 0; } else if (total == -1) { return -1; } ReadFile(hPipeRead, buf, total, &num_read, NULL); offset = 0; num_left = total; //std::cout << "Read " << num_read << " bytes from mailslot" << std::endl; } // Now copy the amount of bytes, if we can, if we can't call the func recursively num_read = 0; // Buffer contains enough if (num_left >= len) { std::memcpy (v, buf+offset, len); num_left -= len; num_read = len; offset += len; } // Uh oh, the buffer doesn't contain enough else { std::memcpy (v, buf+offset, num_left); len -= num_left; num_read += num_left; offset += num_left; num_left = 0; num_left += read_win9x(file, v+num_read, len); } //std::cout << "The Num read is " << num_read << std::endl; //std::cout << num_left << " byte left in buffer with offset " << offset<< std::endl; bNotifyDis = TRUE; return num_read; } int read(int file, void *v, unsigned int len) { if (!bWinNT) return read_win9x(file, (unsigned char*) v, len); DWORD num_read; int total = peek_pipe(); if (total == -1) return 0; else if (len == 0) return 0; else if (total == 0) return -1; else if (total < len) len = total; ReadFile(hPipeRead, v, len, &num_read, NULL); const unsigned char *data = (unsigned char *)v; //cout << "read = " << num_read << endl; //for (int q = 0 ; q < num_read; q++) cout << ((int) data[q]) << " "; //cout << endl; if (GetLastError() == ERROR_BROKEN_PIPE) { bBroken = TRUE; return 0; } return num_read; } int close(int file) { return 0; } // Server Functions bool create_pipe (const char *static_path) { bBroken = FALSE; detect_winnt(); if (!bWinNT) { std::cout << "Using mailslots" << std::endl; hPipeRead = hPipeWrite= INVALID_HANDLE_VALUE; return setup_server_mailslots(static_path, false); } char *pipe_name = Exult_server::get_pipe_name(static_path); // Must have overlap for now DWORD oflag = FILE_FLAG_OVERLAPPED; if(!setup_overlap()) { cerr << "Pipe Server not supported on Win9x." << endl; return true; } //cout << "Exult Server pipe name: " << pipe_name << endl; // Create the Win32 Named pipe hPipeRead = hPipeWrite = CreateNamedPipe(pipe_name, // pipe name PIPE_ACCESS_DUPLEX|oflag, // pipe open mode PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, // pipe-specific modes 1, // maximum number of instances 32768, // output buffer size 32768, // input buffer size 0, // time-out interval NULL); // Security Descriptor delete [] pipe_name; if (hPipeWrite == INVALID_HANDLE_VALUE) { cerr << "Unable to create pipe. Reason: " << GetLastError() << endl; free_overlap(); return false; } cout << "Created Pipe for Exult Server" << endl; setup_connect(); return true; } void setup_connect() { bBroken = FALSE; if (!bWinNT) return; // Attempt to connect to the pipe BOOL fConnected = ConnectNamedPipe(hPipeWrite, lpOverlapCon) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); // If it's connected, signal the event if (fConnected) SetEvent(oOverlapCon.hEvent); } bool try_connect_to_client(const char *static_path) { bBroken = FALSE; if (bWinNT) { DWORD num_bytes; BOOL fConnected = GetOverlappedResult (hPipeWrite, lpOverlapCon, &num_bytes, FALSE); if (!fConnected) return false; } else { return setup_server_mailslots(static_path, true); } return true; } void disconnect_from_client() { bBroken = FALSE; if (bWinNT) { FlushFileBuffers (hPipeWrite); DisconnectNamedPipe(hPipeWrite); } else { if (hPipeWrite != INVALID_HANDLE_VALUE) { FlushFileBuffers (hPipeWrite); CloseHandle(hPipeWrite); } if (hPipeRead != INVALID_HANDLE_VALUE) { CloseHandle(hPipeRead); } hPipeRead = hPipeWrite= INVALID_HANDLE_VALUE; } } void close_pipe() { bBroken = FALSE; if (bWinNT) { if (hPipeWrite != INVALID_HANDLE_VALUE) { disconnect_from_client(); free_overlap(); CloseHandle(hPipeWrite); hPipeRead = hPipeWrite = INVALID_HANDLE_VALUE; } } else { disconnect_from_client(); } } // Client Functions int try_connect_to_server (const char *static_path) { bBroken = FALSE; detect_winnt(); if (!bWinNT) { hPipeRead = hPipeWrite= INVALID_HANDLE_VALUE; return setup_client_mailslots(static_path); } char *pipe_name = Exult_server::get_pipe_name(static_path); // No server if (!WaitNamedPipe(pipe_name, 0)) return 0; // Must have overlap DWORD oflag = FILE_FLAG_OVERLAPPED; if(!setup_overlap()) { cerr << "Pipe Client not supported on Win9x." << endl; return -1; } //cout << "Attempting to connect to server: " << pipe_name << endl; hPipeRead = hPipeWrite = CreateFile (pipe_name, // Pipe Name GENERIC_READ|GENERIC_WRITE, // Desired Access 0, // Share Mode NULL, // Security Att OPEN_EXISTING, // Creation Disposition oflag, // Flags and Attributes NULL); // TemplateFile if (hPipeWrite == INVALID_HANDLE_VALUE) { ERROR_ALREADY_EXISTS; cout << "Pipe handle was invalid! : " << GetLastError () << endl; free_overlap(); return 0; } bClient = TRUE; return 1; } void disconnect_from_server() { //CreateMailslot bBroken = FALSE; if (bWinNT) { if (hPipeWrite != INVALID_HANDLE_VALUE) { FlushFileBuffers (hPipeWrite); free_overlap(); CloseHandle(hPipeWrite); hPipeRead = hPipeWrite= INVALID_HANDLE_VALUE; } } else { if (hPipeWrite != INVALID_HANDLE_VALUE) { FlushFileBuffers (hPipeWrite); CloseHandle(hPipeWrite); } if (hPipeRead != INVALID_HANDLE_VALUE) { CloseHandle(hPipeRead); } hPipeRead = hPipeWrite= INVALID_HANDLE_VALUE; } } #define WIN9X_KEEPALIVE_SIZE 1 int peek_pipe() { if (bBroken) return -1; DWORD to_get; if (bWinNT) { PeekNamedPipe(hPipeRead, 0, 0, 0, &to_get, 0); if (GetLastError() == ERROR_BROKEN_PIPE) { std::cout << "Broken!" << std::endl; bBroken = TRUE; return -1; } } else { DWORD num_read; static DWORD last_time = 0; // This is a keep alive. It doesn't send anything, // But, if the mailslot closes, this will fail. // That is the theory, but win9x doesn't quite // work that way #ifdef USE_WIN9X_KEEPALIVE if (last_time < GetTickCount()) { last_time = GetTickCount() + 5000; char buf[WIN9X_KEEPALIVE_SIZE]; if (!WriteFile(hPipeWrite, buf, WIN9X_KEEPALIVE_SIZE, &num_read, 0)) { std::cout << "Broken!" << std::endl; bBroken = TRUE; return -1; } } #endif GetMailslotInfo(hPipeRead, NULL, &to_get, NULL, NULL); #ifdef USE_WIN9X_KEEPALIVE while (to_get <= WIN9X_KEEPALIVE_SIZE) { char buf[WIN9X_KEEPALIVE_SIZE]; ReadFile(hPipeRead, buf, to_get, &num_read, 0); GetMailslotInfo(hPipeRead, NULL, &to_get, NULL, NULL); } #endif if (to_get == MAILSLOT_NO_MESSAGE) return 0; } return to_get; } bool is_broken() { return bBroken != FALSE; } bool notify_connection_lost() { if (bNotifyDis == TRUE) { bNotifyDis = FALSE; return true; } return bWinNT != FALSE; } bool is_win9x() { return bWinNT == FALSE; } } #endif exult-1.2/server/objserial.cc0000644000175000001440000002416307501001231011754 /** ** Objserial.cc - Object serialization. ** ** Written: 5/25/2001 - JSF **/ /* Copyright (C) 2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "utils.h" #include "objserial.h" #include "servemsg.h" #include using std::cout; using std::endl; /* * Write out a string. */ Serial_out& Serial_out::operator<< ( std::string& s ) { const char *str = s.c_str(); int len = std::strlen(str); // Get length. *this << len; // First the length. std::memcpy(buf, str, len); // Then the bytes. buf += len; return *this; } /* * Read in a string. */ Serial_in& Serial_in::operator<< ( std::string& s ) { int len; (*this) << len; // Get length. s.assign((char *) buf, len); // Set string. buf += len; return *this; } /* * Read/write out data common to all objects. * * Output: 1 if successful, else 0. */ template void Common_obj_io ( Serial& io, unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame ) { io << addr << tx << ty << tz << shape << frame; } /* * Low-level serialization for use both by Exult and ExultStudio (so * don't put in anything that will pull in all of Exult). * * Output: 1 if successful, else 0. */ template void Object_io ( Serial &io, // Where to store data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& quality, std::string& name ) { Common_obj_io(io, addr, tx, ty, tz, shape, frame); io << quality << name; } /* * Low-level serialization for use both by Exult and ExultStudio (so * don't put in anything that will pull in all of Exult). * * Output: 1 if successful, else 0. */ template void Egg_object_io ( Serial &io, // Where to store data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& type, int& criteria, int& probability, int& distance, bool& nocturnal, bool& once, bool& hatched, bool& auto_reset, int& data1, int& data2 ) { Common_obj_io(io, addr, tx, ty, tz, shape, frame); io << type << criteria << probability << distance << nocturnal << once << hatched << auto_reset << data1 << data2; } /* * Low-level serialization for use both by Exult and ExultStudio (so * don't put in anything that will pull in all of Exult). * * Output: 1 if successful, else 0. */ template static void Npc_actor_io ( Serial &io, // Where to store data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& face, std::string& name, short& npc_num, short& ident, int& usecode, int *properties, // Must have room for 12. short& attack_mode, short& alignment, unsigned long& oflags, // Object flags. unsigned long& siflags, // Extra flags for SI. unsigned long& type_flags, // Movement flags. short& num_schedules, // # of schedule changes. Serial_schedule *schedules // Schedule changes. Room for 8. ) { Common_obj_io(io, addr, tx, ty, tz, shape, frame); io << face << name << npc_num << ident << usecode; int i; for (i = 0; i < 12; i++) io << properties[i]; io << attack_mode << alignment << oflags << siflags << type_flags; io << num_schedules; for (i = 0; i < num_schedules; i++) io << schedules[i].time << schedules[i].type << schedules[i].tx << schedules[i].ty; } /* * Send out an object. * * Output: -1 if unsuccessful. 0 if okay. */ int Object_out ( int fd, // Socket. Exult_server::Msg_type id, // Message id. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int quality, std::string name ) { static unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Serial_out io(ptr); Object_io(io, addr, tx, ty, tz, shape, frame, quality, name); return Exult_server::Send_data(fd, id, buf, ptr - buf); } /* * Decode an object. * * Output: 0 if unsuccessful. */ int Object_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& quality, std::string& name ) { unsigned char *ptr = data; Serial_in io(ptr); Object_io(io, addr, tx, ty, tz, shape, frame, quality, name); return (ptr - data) == datalen; } /* * Send out an egg object. * * Output: -1 if unsuccessful. 0 if okay. */ int Egg_object_out ( int fd, // Socket. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int type, int criteria, int probability, int distance, bool nocturnal, bool once, bool hatched, bool auto_reset, int data1, int data2 ) { static unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Serial_out io(ptr); Egg_object_io(io, addr, tx, ty, tz, shape, frame, type, criteria, probability, distance, nocturnal, once, hatched, auto_reset, data1, data2); return Exult_server::Send_data(fd, Exult_server::egg, buf, ptr - buf); } /* * Decode an egg object. * * Output: 0 if unsuccessful. */ int Egg_object_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& type, int& criteria, int& probability, int& distance, bool& nocturnal, bool& once, bool& hatched, bool& auto_reset, int& data1, int& data2 ) { unsigned char *ptr = data; Serial_in io(ptr); Egg_object_io(io, addr, tx, ty, tz, shape, frame, type, criteria, probability, distance, nocturnal, once, hatched, auto_reset, data1, data2); return (ptr - data) == datalen; } /* * Send out an npc object. * * Output: -1 if unsuccessful. 0 if okay. */ int Npc_actor_out ( int fd, // Socket. unsigned long addr, // Address. int tx, int ty, int tz, // Absolute tile coords. int shape, int frame, int face, std::string name, short npc_num, short ident, int usecode, int properties[12], short attack_mode, short alignment, unsigned long oflags, // Object flags. unsigned long siflags, // Extra flags for SI. unsigned long type_flags, // Movement flags. short num_schedules, // # of schedule changes. Serial_schedule *schedules // Schedule changes. ) { static unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Serial_out io(ptr); Npc_actor_io(io, addr, tx, ty, tz, shape, frame, face, name, npc_num, ident, usecode, properties, attack_mode, alignment, oflags, siflags, type_flags, num_schedules, schedules); return Exult_server::Send_data(fd, Exult_server::npc, buf, ptr - buf); } /* * Decode an npc object. * * Output: 0 if unsuccessful. */ int Npc_actor_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. unsigned long& addr, // Address. int& tx, int& ty, int& tz, // Absolute tile coords. int& shape, int& frame, int& face, std::string& name, short& npc_num, short& ident, int& usecode, int properties[12], short& attack_mode, short& alignment, unsigned long& oflags, // Object flags. unsigned long& siflags, // Extra flags for SI. unsigned long& type_flags, // Movement flags. short& num_schedules, // # of schedule changes. Serial_schedule *schedules // Schedule changes. Room for 8. ) { unsigned char *ptr = data; Serial_in io(ptr); Npc_actor_io(io, addr, tx, ty, tz, shape, frame, face, name, npc_num, ident, usecode, properties, attack_mode, alignment, oflags, siflags, type_flags, num_schedules, schedules); return (ptr - data) == datalen; } /* * Game info. IO. */ template void Game_info_io ( Serial &io, // Where to store data. int& version, // Server/client version. int& edit_lift, // Lift being edited. int& hide_lift, // Lift being hidden. bool& map_editing, // In 'map-editing' mode. bool& tile_grid, // Showing tile grid. bool& map_modified, // Map was changed. int& edit_mode // Mode we're in. ) { io << version << edit_lift << hide_lift << map_editing << tile_grid << map_modified << edit_mode; } /* * Send out game info. * * Output: -1 if unsuccessful. 0 if okay. */ int Game_info_out ( int fd, // Socket. int version, // Server/client version. int edit_lift, // Lift being edited. int hide_lift, // Lift being hidden. bool map_editing, // In 'map-editing' mode. bool tile_grid, // Showing tile grid. bool map_modified, // Map was changed. int edit_mode // Mode we're in. ) { static unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Serial_out io(ptr); Game_info_io(io, version, edit_lift, hide_lift, map_editing, tile_grid, map_modified, edit_mode); return Exult_server::Send_data(fd, Exult_server::info, buf, ptr - buf); } /* * Decode game info. * * Output: 0 if unsuccessful. */ int Game_info_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. int& version, // Server/client version. int& edit_lift, // Lift being edited. int& hide_lift, // Lift being hidden. bool& map_editing, // In 'map-editing' mode. bool& tile_grid, // Showing tile grid. bool& map_modified, // Map was changed. int& edit_mode // Mode we're in. ) { unsigned char *ptr = data; Serial_in io(ptr); Game_info_io(io, version, edit_lift, hide_lift, map_editing, tile_grid, map_modified, edit_mode); return (ptr - data) == datalen; } exult-1.2/server/server.h0000644000175000001440000000221607451120614011160 /** ** Server.h - Server functions. ** ** Written: 5/3/2001 - JSF **/ #ifndef INCL_SERVER #define INCL_SERVER 1 /* Copyright (C) 2000-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * For the time being, we'll only inflict this on X users. */ #ifdef USE_EXULTSTUDIO typedef void(*Message_handler)(int&); extern int client_socket; extern void Server_init(); extern void Server_delay(Message_handler handle_message); extern void Server_delay(); #endif /* USE_EXULTSTUDIO */ #endif /* INCL_SERVER */ exult-1.2/shapes/0000777000175000001440000000000010062225325007536 5exult-1.2/shapes/u7drag.h0000644000175000001440000000550507521670654011040 /** ** U7drag.h - Common defines for drag-and-drop of U7 shapes. ** ** Written: 12/13/00 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_U7DRAG #define INCL_U7DRAG 1 // Target information for dragging a shape: #define U7_TARGET_SHAPEID_NAME "U7SHAPEID" #define U7_TARGET_SHAPEID 137 // Shape files: #define U7_SHAPE_UNK -1 /* Unknown. */ #define U7_SHAPE_SHAPES 0 /* shapes.vga */ #define U7_SHAPE_GUMPS 1 /* gumps.vga */ #define U7_SHAPE_FONTS 2 /* fonts.vga */ #define U7_SHAPE_FACES 3 /* faces.vga */ #define U7_SHAPE_SPRITES 4 /* sprites.vga */ #define U7_SHAPE_PAPERDOL 5 /* paperdol.vga */ // Store/get shapeid. int Store_u7_shapeid(unsigned char *data, int file, int shape, int frame); void Get_u7_shapeid(unsigned char *data, int& file, int& shape, int& frame); // Target information for dragging a chunk: #define U7_TARGET_CHUNKID_NAME "U7CHUNKID" #define U7_TARGET_CHUNKID 138 // Store/get chunk #. int Store_u7_chunkid(unsigned char *data, int cnum); void Get_u7_chunkid(unsigned char *data, int& cnum); // Target information for dragging a 'combo' (group of shapes): #define U7_TARGET_COMBOID_NAME "U7COMBOID" #define U7_TARGET_COMBOID 139 // Store/get combo and its elements: typedef struct U7_combo_data { int tx, ty, tz, shape, frame; } U7_combo_data; int Store_u7_comboid(unsigned char *data, int xtiles, int ytiles, int tiles_right, int tiles_below, int cnt, U7_combo_data *ents); void Get_u7_comboid(unsigned char *data, int& xtiles, int& ytiles, int& tiles_right, int& tiles_below, int& cnt, U7_combo_data *& ents); // Put these here since they are shared between XWin and Win32 typedef void (*Move_shape_handler_fun)(int shape, int frame, int x, int y, int prevx, int prevy, bool show); typedef void (*Move_combo_handler_fun)(int xtiles, int ytiles, int tiles_right, int tiles_below, int x, int y, int prevx, int prevy, bool show); typedef void (*Drop_shape_handler_fun)(int shape, int frame, int x, int y, void *data); typedef void (*Drop_chunk_handler_fun)(int chunk, int x, int y, void *data); typedef void (*Drop_combo_handler_fun)(int cnt, struct U7_combo_data *combo, int x, int y, void *data); #endif exult-1.2/shapes/pngio.cc0000644000175000001440000002364507456734423011130 /** ** Import/export .PNG files. ** ** Written: 6/9/99 - JSF **/ /* Copyright (C) 2002 The Exult Team Copyright (C) 1999 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_PNG_H #include #include /* * Read in an 8-bit .png file. Each pixel returned is one byte, * an offset into the palette (also returned). * * Output: 0 if failed. */ int Import_png8 ( const char *pngname, int transp_index, // If 0-255, replace any transp. color // with this. int& width, int& height, // Image dimensions returned. int& rowbytes, // # bytes/row returned. (Should be // width.) int& xoff, int& yoff, // (X,Y) offsets from top-left of // image returned. (0,0) if not // specified in file. unsigned char *& pixels, // ->(allocated) pixels returned. unsigned char *& palette, // ->(allocated) palette returned, // each entry 3 bytes (RGB). int& pal_size // # entries in palette returned. ) { pixels = 0; // In case we fail. // Open file. FILE *fp = fopen(pngname, "rb"); if (!fp) return (0); unsigned char sigbuf[4]; // Make sure it's a .png. if (fread(sigbuf, 1, sizeof(sigbuf), fp) != sizeof(sigbuf) || png_sig_cmp(sigbuf, 0, sizeof(sigbuf))) { fclose(fp); return (0); } // Initialize. png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png) { fclose(fp); return (0); } // Allocate info. structure. png_infop info = png_create_info_struct(png); if (setjmp(png->jmpbuf)) // Handle errors. { png_destroy_read_struct(&png, &info, 0); fclose(fp); return (0); } png_init_io(png, fp); // Init. for reading. // Indicate we already read something. png_set_sig_bytes(png, sizeof(sigbuf)); png_read_info(png, info); // Read in image info. unsigned long w, h; int depth, color, interlace; png_get_IHDR(png, info, &w, &h, &depth, &color, &interlace, 0, 0); width = (int) w; height = (int) h; if (color != PNG_COLOR_TYPE_PALETTE) { png_destroy_read_struct(&png, &info, 0); fclose(fp); return (0); } if (depth < 8) png_set_packing(png); png_colorp pngpal; // Get palette. if (png_get_PLTE(png, info, &pngpal, &pal_size) != 0) palette = new unsigned char[3*pal_size]; else // No palette?? { pal_size = 0; palette = 0; } int i; for (i = 0; i < pal_size; i++) { palette[3*i] = pngpal[i].red; palette[3*i + 1] = pngpal[i].green; palette[3*i + 2] = pngpal[i].blue; } png_int_32 pngxoff, pngyoff; // Get offsets. int utype; if (png_get_oFFs(png, info, &pngxoff, &pngyoff, &utype) && utype == PNG_OFFSET_PIXEL) { xoff = pngxoff; yoff = pngyoff; } else xoff = yoff = 0; png_bytep trans; // Get transparency info. int num_trans; png_color_16p trans_values; if (transp_index < 0 || transp_index > 255 || pal_size == 0 || !png_get_tRNS(png, info, &trans, &num_trans, &trans_values)) num_trans = 0; // Get updated info. png_read_update_info(png, info); // Allocate pixel buffer. rowbytes = png_get_rowbytes(png, info); png_bytep image = new png_byte[height*rowbytes]; pixels = image; // Return ->. png_bytep rowptr; // Read in rows. int r; for (r = 0, rowptr = image; r < height; r++, rowptr += rowbytes) png_read_rows(png, &rowptr, 0, 1); png_read_end(png, info); // Get the rest. // Point past end of data. unsigned char *endptr = pixels + height*rowbytes; for (i = 0; i < num_trans; i++) // Convert transparent pixels. { if (trans[i] != 0) // Only accept fully transparent ones. continue; // Update data. for (unsigned char *ptr = pixels; ptr != endptr; ptr++) if (*ptr == i) *ptr = transp_index; // We'll remove i from the palette. else if (*ptr > i) *ptr = *ptr - 1; if (i < pal_size - 1) // Remove trans. color from palette. memmove(palette + 3*i, palette + 3*(i + 1), 3*pal_size - 3*(i + 1)); pal_size--; } // Clean up. png_destroy_read_struct(&png, &info, 0); fclose(fp); return (1); } /* * Write out an 8-bit .png file. * * Output: 0 if failed. */ int Export_png8 ( const char *pngname, int transp_index, // If 0-255, this is the transp. index. int width, int height, // Image dimensions. int rowbytes, // # bytes/row. (Should be // width.) int xoff, int yoff, // (X,Y) offsets from top-left of // image. unsigned char *pixels, // ->pixels to write. unsigned char *palette, // ->palette, // each entry 3 bytes (RGB). int pal_size, // # entries in palette, bool transp_to_0 // If true, rotate palette so the // transparent index is 0. This // fixes a bug in the Gimp. ) { // Open file. FILE *fp = fopen(pngname, "wb"); if (!fp) return (0); // Initialize. png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png) { fclose(fp); return (0); } // Allocate info. structure. png_infop info = png_create_info_struct(png); if (setjmp(png->jmpbuf)) // Handle errors. { png_destroy_write_struct(&png, &info); fclose(fp); return (0); } png_init_io(png, fp); // Init. for reading. png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (transp_index == 0) transp_to_0 = false; // Don't need to rotate if already 0. png_color pngpal[256]; // Set palette. int rot = transp_to_0 ? (pal_size - transp_index) : 0; for (int i = 0; i < pal_size; i++) { int desti = (i + rot)%pal_size; pngpal[desti].red = palette[3*i]; pngpal[desti].green = palette[3*i + 1]; pngpal[desti].blue = palette[3*i + 2]; } png_set_PLTE(png, info, &pngpal[0], pal_size); png_set_oFFs(png, info, xoff, yoff, PNG_OFFSET_PIXEL); if (transp_index >= 0 && transp_index < 256) { int tindex = transp_to_0 ? 0 : transp_index; png_byte trans[256]; // Only desired index is transparent. memset(&trans[0], 255, tindex); trans[(png_byte) tindex] = 0; png_set_tRNS(png, info, &trans[0], tindex + 1, 0); } // Write out info. png_write_info(png, info); png_bytep rowptr; // Write out rows. int r; for (r = 0, rowptr = pixels; r < height; r++, rowptr += rowbytes) { if (!transp_to_0) // Normal? png_write_row(png, rowptr); else { unsigned char *tbuf = new unsigned char[rowbytes]; for (int i = 0; i < rowbytes; i++) tbuf[i] = (rowptr[i] + rot)%pal_size; png_write_row(png, &tbuf[0]); delete [] tbuf; } } png_write_end(png, 0); // Done. // Clean up. png_destroy_write_struct(&png, &info); fclose(fp); return (1); } /* * Read in a .png file. Each pixel returned is 4 bytes: RGBA, * where A is the alpha channel (0 = transparent, 255 = opaque). * * Output: 0 if failed. */ int Import_png32 ( const char *pngname, int& width, int& height, // Image dimensions returned. int& rowbytes, // # bytes/row returned. (Should be // 4*width.) int& xoff, int& yoff, // (X,Y) offsets from top-left of // image returned. (0,0) if not // specified in file. unsigned char *& pixels, // ->(allocated) pixels returned. bool bottom_first // Return last row first. Useful for // OpenGL textures. ) { pixels = 0; // In case we fail. // Open file. FILE *fp = fopen(pngname, "rb"); if (!fp) return (0); unsigned char sigbuf[4]; // Make sure it's a .png. if (fread(sigbuf, 1, sizeof(sigbuf), fp) != sizeof(sigbuf) || png_sig_cmp(sigbuf, 0, sizeof(sigbuf))) { fclose(fp); return (0); } // Initialize. png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png) { fclose(fp); return (0); } // Allocate info. structure. png_infop info = png_create_info_struct(png); if (setjmp(png->jmpbuf)) // Handle errors. { png_destroy_read_struct(&png, &info, 0); fclose(fp); return (0); } png_init_io(png, fp); // Init. for reading. // Indicate we already read something. png_set_sig_bytes(png, sizeof(sigbuf)); png_read_info(png, info); // Read in image info. unsigned long w, h; int depth, color, interlace; png_get_IHDR(png, info, &w, &h, &depth, &color, &interlace, 0, 0); width = (int) w; height = (int) h; png_int_32 pngxoff, pngyoff; // Get offsets. int utype; if (png_get_oFFs(png, info, &pngxoff, &pngyoff, &utype) && utype == PNG_OFFSET_PIXEL) { xoff = pngxoff; yoff = pngyoff; } else xoff = yoff = 0; png_set_strip_16(png); // Want 8 bits/color. if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); // Expand if paletted. if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_expand(png); // Want an alpha byte. else if (depth == 8 && color == PNG_COLOR_TYPE_RGB) png_set_filler(png, 0xff, PNG_FILLER_AFTER); // Get updated info. png_read_update_info(png, info); // Allocate pixel buffer. rowbytes = png_get_rowbytes(png, info); png_bytep image = new png_byte[height*rowbytes]; pixels = image; // Return ->. png_bytep rowptr = image; // Read in rows. int r; int stride; // Distance to next row. if (bottom_first) { stride = -rowbytes; rowptr += (height - 1)*rowbytes; } else stride = rowbytes; for (int r = 0; r < height; r++, rowptr += stride) png_read_row(png, rowptr, 0); png_read_end(png, info); // Get the rest. // Clean up. png_destroy_read_struct(&png, &info, 0); fclose(fp); return (1); } #endif /* HAVE_PNG_H */ exult-1.2/shapes/fontgen.h0000644000175000001440000000210710054043356011266 /** ** Create RLE font shapes from a given font. ** ** Written: 4/8/2002 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_FONTGEN #define INCL_FONTGEN #ifdef HAVE_FREETYPE2 class Shape; bool Gen_font_shape(Shape *shape, const char *fontfile, int nframes, int pixels_ht, unsigned char fg, unsigned char bg, int shadow = -1); #endif /* HAVE_FREETYPE2 */ #endif /* INCL_FONTGEN */ exult-1.2/shapes/fontvga.h0000644000175000001440000000426107354365165011313 /** ** Fontvga.h - Handle the 'fonts.vga' file and text rendering. ** ** Written: 4/29/99 - JSF **/ #ifndef INCL_FONTVGA #define INCL_FONTVGA 1 /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "font.h" #include "vgafile.h" /* * The "fonts.vga" file: */ class Fonts_vga_file : public Vga_file { Font fonts[11]; // Fonts from fonts.vga file. public: Fonts_vga_file() { } void init(); // Text rendering: int paint_text_box(Image_buffer8 *win, int fontnum, const char *text, int x, int y, int w, int h, int vert_lead = 0, int pbreak = 0) { return fonts[fontnum].paint_text_box(win, text, x, y, w, h, vert_lead, pbreak); } int paint_text(Image_buffer8 *win, int fontnum, const char *text, int xoff, int yoff) { return fonts[fontnum].paint_text(win, text, xoff, yoff); } int paint_text(Image_buffer8 *win, int fontnum, const char *text, int textlen, int xoff, int yoff) { return fonts[fontnum].paint_text(win, text, textlen, xoff, yoff); } // Get text width. int get_text_width(int fontnum, const char *text) { return fonts[fontnum].get_text_width(text); } int get_text_width(int fontnum, const char *text, int textlen) { return fonts[fontnum].get_text_width(text, textlen); } // Get text height, baseline. int get_text_height(int fontnum) { return fonts[fontnum].get_text_height(); } int get_text_baseline(int fontnum) { return fonts[fontnum].get_text_baseline(); } Font *get_font(int fontnum) { return fontnum>=0&&fontnum<8?fonts+fontnum:NULL; }; }; #endif exult-1.2/shapes/shapeinf.h0000644000175000001440000003023107714030633011425 /** ** Shapeinf.h: Info. about shapes read from various 'static' data files. ** ** Written: 4/29/99 - JSF **/ #ifndef INCL_SHAPEINF #define INCL_SHAPEINF 1 /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ class Monster_info; #include /* * Specific information about weapons from 'weapons.dat': * MAYBE: Move this and ammo. to separate source file(s). */ class Weapon_info { char damage; // Damage points (positive). public: enum Powers // Special weapon powers. { // Guesses from printout: sleep = 1, charm = 2, curse = 4, poison = 8, paralyze = 16, magebane = 32 // Takes away mana. }; enum Damage_type // Type of damage. These also are the // bit #'s in Monster_info's // immune and vulerable fields. { normal_damage = 0, fire_damage = 1, magic_damage = 2, poison_damage = 3 // Not sure about rest. }; enum Actor_frames // Actor frames to show when using: { raise = 1, reach = 2 }; private: unsigned char powers; // Poison, sleep, charm. flags. unsigned char damage_type; // See Damage_type above. unsigned char actor_frames; // Frames for NPC when using (from // Actor_frames above). Low 2 bits // are for 'strike', next 2 are for // shooting/throwing. short ammo; // Shape # of ammo. consumed, or // -1 = ?? (swords, also sling). // -2 = ?? wands? // -3 = throw weapon itself. short projectile; // Projectile shape, or 0. bool m_explodes; // Projectile explodes on impact. bool m_returns; // Boomerang, magic axe. bool m_no_blocking; // Can move through walls. short usecode; // Usecode function, or 0. unsigned char uses; // 0 = hand-hand, 1,2 = throwable, // 3 = missile-firing. unsigned char range; // Distance weapon can be used. short sfx, hitsfx; // Sound when using/hit, or -1. public: friend class Shape_info; Weapon_info() { } int read(std::istream& mfile, bool bg); // Read in from file. // Write out. void write(int shapenum, std::ostream& mfile, bool bg); int get_damage() const { return damage; } int get_damage_type() const { return damage_type; } void set_damage(int dmg, int dmgtype) { damage = dmg; damage_type = dmgtype; } unsigned char get_powers() const { return powers; } void set_powers(unsigned char p) { powers = p; } unsigned char get_actor_frames(bool projectile) const { return !projectile ? (actor_frames&3) : (actor_frames>>2); } void set_actor_frames(unsigned char f) { actor_frames = f; } int get_ammo_consumed() { return ammo > 0 ? ammo : 0; } void set_ammo(int a) // Raw value, for map-editor. { ammo = a; } bool uses_charges() { return ammo == -2; } bool is_thrown() const { return uses == 1 || uses == 2 || m_returns; } bool returns() const { return m_returns; } void set_returns(bool tf) { m_returns = tf; } bool explodes() const { return m_explodes; } void set_explodes(bool tf) { m_explodes = tf; } bool no_blocking() const { return m_no_blocking; } void set_no_blocking(bool tf) { m_no_blocking = tf; } unsigned char get_uses() const { return uses; } void set_uses(unsigned char u) { uses = u; } int get_range() // Raw # (for map-editor). { return range; } void set_range(int r) { range = r; } int get_striking_range() // Guessing about div. by 2. { return uses < 3 ? range/2 : 0; } int get_projectile_range() // +++Guess for thrown weapons. { return uses == 3 ? range : is_thrown() ? 20 : 0; } int get_projectile() { return projectile; } void set_projectile(int p) { projectile = p; } int get_usecode() { return usecode; } void set_usecode(int u) { usecode = u; } int get_sfx() // Return sound-effects #, or -1. { return sfx; } int get_hitsfx() { return hitsfx; } void set_sfxs(int s, int hits) { sfx = s; hitsfx = hits; } }; /* * Info. from 'ammo.dat': */ class Ammo_info { int family_shape; // I.e., burst-arrow's is 'arrow'. unsigned short type2; // ?? A shape. unsigned char damage; // Extra damage points. unsigned char powers; // Same as for weapons. unsigned char damage_type; // Same as for weapons. bool m_no_blocking; // Can move through walls. public: friend class Shapes_vga_file; Ammo_info() { } int read(std::istream& mfile); // Read in from file. // Write out. void write(int shapenum, std::ostream& mfile); int get_family_shape() { return family_shape; } void set_family_shape(int f) { family_shape = f; } int get_damage() { return damage; } int get_damage_type() const { return damage_type; } void set_damage(int dmg, int dtype) { damage = dmg; damage_type = dtype; } unsigned char get_powers() const { return powers; } void set_powers(unsigned char p) { powers = p; } bool no_blocking() const { return m_no_blocking; } void set_no_blocking(bool tf) { m_no_blocking = tf; } }; /* * Armor: */ class Armor_info { unsigned char prot; // Protection value. unsigned char immune; // Weapon_info::damage_type bits. public: friend class Shape_info; Armor_info() { } int read(std::istream& mfile); // Read in from file. // Write out. void write(int shapenum, std::ostream& mfile); unsigned char get_prot() const { return prot; } void set_prot(unsigned char p) { prot = p; } unsigned char get_immune() const { return immune; } void set_immune(unsigned char i) { immune = i; } }; /* * This class contains information only about shapes from "shapes.vga". */ class Shape_info { unsigned char tfa[3]; // From "tfa.dat".+++++Keep for // debugging, for now. // 3D dimensions in tiles: unsigned char dims[3]; // (x, y, z) unsigned char weight, volume; // From "wgtvol.dat". unsigned char shpdims[2]; // From "shpdims.dat". unsigned char ready_type; // From "ready.dat": where item can // be worn. bool occludes_flag; // Flagged in 'occlude.dat'. Roof. unsigned char *weapon_offsets; // From "wihh.dat": pixel offsets // for drawing weapon in hand Armor_info *armor; // From armor.dat. Weapon_info *weapon; // From weapon.dat, if a weapon. Ammo_info *ammo; // From ammo.dat, if ammo. Monster_info *monstinf; // From monster.dat. void set_tfa_data() // Set fields from tfa. { dims[0] = 1 + (tfa[2]&7); dims[1] = 1 + ((tfa[2]>>3)&7); dims[2] = (tfa[0] >> 5); } // Set/clear tfa bit. void set_tfa(int i, int bit, bool tf) { tfa[i] = tf ? (tfa[i]|(1<prot : 0; } Weapon_info *get_weapon_info() { return weapon; } Weapon_info *set_weapon_info(bool tf); Ammo_info *get_ammo_info() { return ammo; } Ammo_info *set_ammo_info(bool tf); Armor_info *get_armor_info() { return armor; } Armor_info *set_armor_info(bool tf); Monster_info *get_monster_info() { return monstinf; } Monster_info *set_monster_info(bool tf); // Get tile dims., flipped for // reflected (bit 5) frames. int get_3d_xtiles(unsigned int framenum = 0) { return dims[(framenum >> 5)&1]; } int get_3d_ytiles(unsigned int framenum = 0) { return dims[1 ^ ((framenum >> 5)&1)]; } int get_3d_height() // Height (in lifts?). { return dims[2]; } void set_3d(int xt, int yt, int zt); unsigned char get_tfa(int i) // For debugging: { return tfa[i]; } int has_sfx() // Has a sound effect (guessing). { return (tfa[0] & (1<<0)) != 0; } void set_sfx(bool tf) { set_tfa(0, 0, tf); } int has_strange_movement() // Slimes, sea monsters. { return (tfa[0] & (1<<1)) != 0; } void set_strange_movement(bool tf) { set_tfa(0, 1, tf); } int is_animated() { return (tfa[0] & (1<<2)) != 0; } void set_animated(bool tf) { set_tfa(0, 2, tf); } int is_solid() // Guessing. Means can't walk through. { return (tfa[0] & (1<<3)) != 0; } void set_solid(bool tf) { set_tfa(0, 3, tf); } int is_water() // Guessing. { return (tfa[0] & (1<<4)) != 0; } void set_water(bool tf) { set_tfa(0, 4, tf); } int is_poisonous() // Swamps. Applies to tiles. { return (tfa[1] & (1<<4)) != 0; } int is_field() // Applies to Game_objects?? { return (tfa[1] & (1<<4)) != 0; } void set_field(bool tf) { set_tfa(1, 4, tf); } int is_door() { return (tfa[1] & (1<<5)) != 0; } void set_door(bool tf) { set_tfa(1, 5, tf); } int is_barge_part() { return (tfa[1] & (1<<6)) != 0; } void set_barge_part(bool tf) { set_tfa(1, 6, tf); } int is_transparent() // ?? { return (tfa[1] & (1<<7)) != 0; } void set_transparent(bool tf) { set_tfa(1, 7, tf); } int is_light_source() { return (tfa[2] & (1<<6)) != 0; } void set_light_source(bool tf) { set_tfa(2, 6, tf); } int has_translucency() { return (tfa[2] & (1<<7)) != 0; } void set_translucency(bool tf) { set_tfa(2, 7, tf); } int is_xobstacle() // Obstacle in x-dir.??? { return (shpdims[1] & 1) != 0; } int is_yobstacle() // Obstacle in y-dir.??? { return (shpdims[0] & 1) != 0; } void set_obstacle(bool x, bool y) { shpdims[1] = x ? (shpdims[1]|1) : (shpdims[1]&~1); shpdims[0] = y ? (shpdims[0]|1) : (shpdims[0]&~1); } /* * TFA[1][b0-b3] seems to indicate object types: */ enum Shape_class { unusable = 0, // Trees. quality = 2, quantity = 3, // Can have more than 1: coins, arrs. has_hp = 4, // Breakable items (if hp != 0, that is) quality_flags = 5, // Item quality is set of flags: // Bit 3 = okay-to-take. container = 6, hatchable = 7, // Eggs, traps, moongates. spellbook = 8, barge = 9, virtue_stone = 11, monster = 12, // Non-human's. human = 13, // Human NPC's. building = 14 // Roof, window, mountain. }; Shape_class get_shape_class() { return (Shape_class) (tfa[1]&15); } void set_shape_class(Shape_class c) { tfa[1] = (tfa[1]&~15)|(int) c; } bool is_npc() { Shape_class c = get_shape_class(); return c == human || c == monster; } bool has_quantity() { return get_shape_class() == quantity; } bool has_quality_flags() // Might be more... { return get_shape_class() == quality_flags; } bool has_quality() { #if 0 static bool qual[16] = // Ugly, but quick. // quality { false, false, true, false, false, false, // ctainer egg virtue stone true, true, false, false, false, true, // monst human true, true, false, false }; #endif Shape_class c = get_shape_class(); return (c == 2 || c == 6 || c == 7 || c == 11 || c == 12 || c == 13); // return qual[(int) c]; } bool occludes() const { return occludes_flag; } void set_occludes(bool tf) { occludes_flag = tf; } unsigned char get_ready_type() { return ready_type; } void set_ready_type(unsigned char t) { ready_type = t; } // Sets x to 255 if there is no weapon offset void get_weapon_offset(int frame, unsigned char& x, unsigned char& y) { if(!weapon_offsets) x = 255; else { // x could be 255 (see read_info()) x = weapon_offsets[frame * 2]; y = weapon_offsets[frame * 2 + 1]; } } void set_weapon_offset(int frame, unsigned char x, unsigned char y); }; #endif exult-1.2/shapes/shapevga.h0000644000175000001440000000363207724430453011440 /* * shapevga.h - Handle the 'shapes.vga' file and associated info. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_SHAPEVGA #define INCL_SHAPEVGA 1 #include #include #ifdef MACOS #include #endif #include "autoarray.h" #include "fnames.h" #include "imagebuf.h" #include "vgafile.h" #include "shapeinf.h" /* * The "shapes.vga" file: */ class Shapes_vga_file : public Vga_file { autoarray info; // Extra info. about each shape. Shape_info zinfo; // A fake one (all 0's). bool info_read; // True when info is set. public: Shapes_vga_file() : info(), info_read(false) { } Shapes_vga_file(const char *nm, int u7drag = -1, const char *nm2 = 0); void init(); virtual ~Shapes_vga_file(); // Read additional data files. void read_info(bool bg, bool editing = false); void write_info(bool bg); // Write them back out. Shape_info& get_info(int shapenum) { // Shapes 1024 -> 1035 in SI are alternative player chars. // Odd are female, even are male. return shapenum>=1024&&shapenum<=1035&&shapenum%2 ? info[989]: shapenum>=1024&&shapenum<=1035 ? info[721]: info[shapenum]; } }; #endif exult-1.2/shapes/fontgen.cc0000644000175000001440000000766310054044603011434 /** ** Create RLE font shapes from a given font. ** ** Written: 4/8/2002 - JSF **/ /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #if defined(HAVE_FREETYPE2) && !defined(__zaurus__) #include #include FT_FREETYPE_H #include #include "vgafile.h" /* * Generate a shadow around a character. */ static void Gen_shadow ( unsigned char *pixels, int w, int h, // Dimensions. unsigned char fg, // Foreground color index. unsigned char shadow // Shadow color index ) { int r, c; for (r = 0; r < h; r++) for (c = 0; c < w; c++) { if (pixels[r*w+c] != fg) continue; int rr, cc; // Fill surrounding pixels; for (rr = r - 1; rr <= r + 1; rr++) { if (rr < 0 || rr >= h) continue; for (cc = c - 1; cc <= c + 1; cc++) if (cc >= 0 && cc < w && pixels[rr*w+cc] != fg) pixels[rr*w+cc] = shadow; } } } /* * Fill a shape with each frame containing the glyph for its ASCII * code. The shape has 128 frames. * * Output: True if successful, false if error. */ bool Gen_font_shape ( Shape *shape, // Shape to set frames. const char *fontfile, // Filename of font. int nframes, // # frames to generate, starting at 0. int pixels_ht, // Desired height in pixels. unsigned char fg, // Foreground color index. unsigned char bg, // Background color index. int shadow // Shadow color, or -1 ) { FT_Library library; // Initialize. int error = FT_Init_FreeType(&library); if (error) return false; FT_Face face; // Gets the font. error = FT_New_Face(library, fontfile, 0, &face); if (error) return false; error = FT_Set_Pixel_Sizes(face, 0, pixels_ht); // Glyphs are rendered here: FT_GlyphSlot glyph = face->glyph; if (error) return false; shape->resize(nframes); // Make it big enough. for (int chr = 0; chr < nframes; chr++) { // Get each glyph. error = FT_Load_Char(face, chr, FT_LOAD_RENDER|FT_LOAD_MONOCHROME); if (error) { //+++++Do we need to store an empty frame? continue; } int w = glyph->bitmap.width, h = glyph->bitmap.rows; int sw = w, sh = h; // Shape width/height. int offset = 0; // Starting row, col. if (!sw) // 0 width (like for a space)? sw = glyph->metrics.horiAdvance/64; // Guessin... if (!sh) sh = glyph->metrics.vertAdvance/64; if (shadow != -1) // Make room for shadow. { sw += 2; sh += 2; offset = 1; } // Allocate our buffer. int cnt = sw*sh; // Total #pixels. unsigned char *pixels = new unsigned char[cnt]; memset(pixels, bg, cnt);// Fill with background. // I believe this is 1 bit/pixel: unsigned char *src = glyph->bitmap.buffer; unsigned char *dest = pixels + offset*sw; for (int row = 0; row < h; row++) { for (int b = 0; b < w; b++) if (src[b/8]&(0x80>>(b%8))) dest[offset + b] = fg; dest += sw; // Advance to next row. src += glyph->bitmap.pitch; } if (shadow >= 0) Gen_shadow(pixels, sw, sh, fg, (unsigned char) shadow); // Not sure about dims here+++++ Shape_frame *frame = new Shape_frame(pixels, sw, sh, glyph->bitmap_left + offset, glyph->bitmap_top + offset, true); delete pixels; shape->set_frame(frame, chr); } FT_Done_FreeType(library); return true; } #endif /* HAVE_FREETYPE2 */ exult-1.2/shapes/bodies.cc0000644000175000001440000003345607724430453011254 /* * bodies.cc - Associate bodies with 'live' shapes. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "bodies.h" #include "hash_utils.h" #include "game.h" using std::size_t; /* * Each triple here is , , . */ short Body_lookup::bg_table[] = { // BLACK GATE. /* Artaxerxes Hi, here is the newest (Oct 4 2000 11am EST) bodies.cc file hope it helps */ 154, 762, 22, // x mage 155, 762, 2, // X Ferryman 226, 892, 29, // X flying gargoyle 227, 400, 5, // X monk male 228, 414, 28, // X naked man 229, 414, 27, // X naked woman 230, 762, 0, // x ethereal monster -- there should // not be a body.. just blood 247, 762, 23, // x paladin 259, 400, 20, // x fighter 265, 400, 27, // X townsman 274, 414, 2, // X gargoyle -- Healer (?) 299, 762, 0, // x ghost 304, 400, 28, // X forger 317, 762, 0, // x ghost 318, 400, 5, // x monk 319, 400, 9, // x male peasant 337, 762, 0, // x ghost (invisible) 354, 762, 8, // x liche 375, 778, 2, // X unicorn 380, 778, 4, // X cyclop 381, 778, 3, // x three headed hydra 382, 414, 7, // x Kissme 394, 892, 10, // x guard 401, 762, 25, // x pirate 401, 400, 16, // x pirate. 403, 414, 16, // x Batlin 445, 400, 3, // X mage male 446, 400, 4, // X mage female 447, 892, 11, // x wounded man 448, 400, 6, // X monk female 449, 400, 7, // X beggar 450, 400, 8, // X beggar 451, 400, 13, // x male noble. 452, 400, 10, // x female peasant. 454, 400, 12, // x female shopkeeper. 455, 400, 11, // x male shopkeeper. 456, 400, 14, // x female noble. 457, 400, 15, // x male gypsy 458, 400, 16, // x pirate. 459, 400, 17, // x female gypsy 460, 400, 18, // x male ranger 461, 400, 19, // x female ranger 462, 400, 20, // x male fighter. 463, 400, 21, // x female fighter. 464, 400, 22, // X paladin 465, 414, 18, // x Iolo. 466, 414, 13, // x Lord British 467, 400, 24, // X chuck jester 468, 400, 25, // x male entertainer. 469, 400, 26, // x female entertainer. 471, 400, 30, // X kid 472, 400, 31, // X noble Kid 473, 414, 1, // X noble Gargoyle 475, 892, 4, // X Gargoyle -- Forksis (?) 476, 778, 1, // X Smith (?) -- Iolo's Horse 477, 414, 6, // X Honest fox 478, 414, 10, // X Sherry 479, 414, 11, // X emp 480, 414, 14, // X noble Gargoyle 482, 414, 16, // x Batlin 485, 414, 17, // X thief -- Isle of the Avatar 487, 414, 19, // X Shamino 488, 414, 20, // X Dupre 489, 414, 21, // x Spark. 490, 414, 22, // X Jaana 491, 892, 12, // x acid slug 492, 892, 13, // x alligator 493, 762, 0, // x bat -- there is no body for // bat... just blood 494, 892, 15, // x bee 495, 892, 18, // x cat 496, 892, 24, // x dog 498, 892, 20, // x chicken 499, 892, 21, // x corpser 500, 778, 11, // x cow 501, 778, 6, // x cyclops 502, 778, 12, // x deer 504, 778, 7, // x dragon 505, 778, 8, // x drake 506, 892, 19, // x Hook. 509, 892, 26, // x fish 510, 892, 27, // x fox 511, 762, 2, // x gazer 513, 762, 4, // x gremlin 514, 762, 6, // x headless 517, 762, 7, // X insects 519, 762, 8, // X black shadow dead 521, 762, 10, // x mouse 523, 762, 11, // x rat 524, 762, 12, // x reaper 525, 762, 13, // X sea serpent -- should disappear 528, 762, 16, // x skeleton 529, 762, 17, // X slime 530, 762, 18, // x snake 532, 762, 5, // x harpie 533, 778, 5, // x troll 534, 762, 0, // x wisp 536, 762, 0, // x tentacles (invisible). 537, 762, 21, // x wolf 617, 414, 23, // X Time Lord (live shape = 617:16) 661, 762, 9, // x mongbat 706, 762, 26, // x scorpion 716, 892, 16, // x bird 720, 400, 23, // x Guard 721, 400, 1, // X Avatar male 727, 778, 9, // x horse 753, 762, 20, // x stone harpie 784, 892, 25, // x emp 805, 892, 4, // x Forksis 806, 892, 7, // x guard 811, 892, 17, // x rabbit 861, 778, 5, // X troll 864, 400, 29, // X Baby 865, 762, 19, // x spider 881, 892, 2, // x Elizabeth 882, 892, 1, // x Abraham 883, 762, 1, // x wingless Gargoyle 884, 892, 5, // x Fellowship member 929, 400, 10, // x Fellowship member 946, 892, 8, // x guard 952, 762, 2, // X Skara Brae Liche 957, 400, 11, // X shopkeeper 965, 400, 30, // X little boy 970, 762, 14, // x sheep 989, 400, 2, // X avatar female 1015, 414, 4 // x Stone Golem }; short Body_lookup::si_table[] = { // SERPENT_ISLE. /* Artaxerxes Hi, here again another set of body frame numbers for Exult. Took me a few hours but now it's done... Hope that helps. */ /* the dead shapes */ //0, 400, 0, // dead bodies //0, 402, 0, // more dead bodies //0, 414, 0, // more more dead bodies //0, 762, 0, // dead bodies //0, 778, 0, // more dead bodies //0, 892, 0, // more dead bodies /* living shapes, dead shape, frame number */ 179, 402, 23, // black robe mage no face 214, 402, 3, // male gwani 226, 414, 10, // old red robe mage 228, 402, 11, // pikeman 229, 414, 8, // naked white man brown hair 230, 414, 27, // naked white woman blonde hair 247, 400, 24, // jester 250, 414, 23, // xenka monk (male?) no face gold belt 259, 402, 12, // male ranger (winemaker) with mask 265, 400, 27, // male shopkeeper (red outfit) 274, 414, 15, // female noble (green dress) wth green crown 298, 892, 16, // pinguin (Linux?) 299, 414, 21, // Cantra (little girl from Monitor) 302, 762, 3, // grizzly bear (brown) 304, 400, 28, // male forger 312, 892, 19, // kid goblins 317, 402, 13, // possessed Shamino 318, 414, 16, // Batlin 319, 400, 9, // male peasant (brown outfit) 329, 892, 25, // boar 334, 762, 22, // green monster with long neck 337, 762, 15, // phantom 354, 762, 11, // Gurnodir (king Goblin) 363, 892, 14, // magic gremlins 372, 778, 1, // ice troll 373, 402, 31, // skeletton with ripped robe 375, 778, 2, // unicorn 381, 414, 17, // male thief (black band on eyes) 382, 762, 10, // ratman 401, 402, 15, // male noble-mage with orange-red coat and blue undies 446, 400, 4, // old female wild mage 447, 402, 18, // red eye wolf 449, 762, 29, // polar bear (white) 451, 400, 13, // male mayor (blue outfit) 454, 400, 12, // female citizen (orange outfit) 455, 400, 11, // male citizen (orange outfit) 457, 400, 15, // male gypsy 458, 400, 16, // male pirate 460, 778, 7, // skeletal dragon 461, 400, 19, // female ranger (no mask) 462, 400, 20, // male fighter (mail arms and legs) 464, 400, 22, // paladin (square helm) 465, 414, 18, // Iolo 468, 400, 25, // male shopkeeper (beige outfit) 469, 400, 26, // female gypsie 472, 892, 29, // noble little boy 478, 414, 4, // male goblins 480, 414, 1, // noble winged gargoyle 487, 414, 19, // Shamino 488, 414, 20, // Dupre 491, 892, 12, // acid slug 492, 762, 1, // alligator 493, 892, 9, // bat 494, 402, 19, // Goul (?) 495, 892, 18, // cat 496, 892, 24, // dog 498, 892, 11, // chicken 499, 892, 13, // corpser 500, 778, 11, // cow 501, 778, 4, // cyclop 502, 778, 12, // deer 509, 892, 26, // trout 510, 892, 27, // fox 511, 892, 1, // gazer 512, 400, 0, // red worm/snake (whack-a-snake) 514, 762, 6, // headless 517, 892, 2, // insect 521, 400, 0, // flying serpent/dragon (dreamland) 523, 892, 4, // rat 524, 762, 12, // reaper 528, 762, 16, // skelet 529, 892, 8, // slime 530, 892, 6, // serpent 532, 762, 5, // harpie 533, 778, 5, // Troll 536, 400, 0, // sea tentacle 537, 892, 7, // wolf (normal) 550, 762, 7, // brass automaton 560, 400, 3, // female beauty priestess 565, 400, 6, // Caladin 581, 400, 7, // old male mage with cane (green outfit) 588, 762, 8, // male vampire (very blue outfit) 647, 400, 5, // female fighter 652, 400, 17, // female mayor (blue outfit) 658, 400, 30, // Petra 660, 400, 10, // no skin gwani (?) 661, 762, 9, // Mongbat 665, 402, 22, // female mage (black outfit, red belt) 669, 400, 8, // trapper (Gwenno) 691, 414, 4, // male goblins 702, 892, 20, // phoenix 703, 400, 0, // ice corpser 706, 762, 26, // scorpio 716, 892, 10, // bird 720, 400, 23, // male guard (purple/red outfit + chain helm) 721, 400, 1, // male bonde avatar 725, 414, 4, // male goblins 734, 402, 21, // gold automaton 742, 400, 21, // female worker (black top, white skirt) 744, 414, 5, // female goblins 747, 762, 27, // iron automaton 753, 762, 20, // stone harpie 754, 762, 2, // snow leopard 763, 892, 28, // ice snake 766, 402, 2, // female spanish dancer 772, 892, 31, // parrot 798, 402, 16, // small ice dragon 805, 402, 4, // black male fighter 809, 414, 2, // young male mage (dark blue coat + gold trim) 811, 892, 17, // rabbit 814, 402, 5, // male artist (blue outfit) 815, 402, 6, // tall male individual (ripped clothes) 816, 402, 7, // male fighter (orange outfit + chain mail) 817, 402, 14, // young male mage (brown coat + grey undies) 818, 402, 9, // Zulith (?) 830, 402, 8, // Chancellor (Monitor) 832, 778, 8, // ice sea serpent 846, 762, 24, // snake woman 855, 414, 6, // Great Captain 861, 762, 23, // fire elemental 862, 414, 7, // male gwani 865, 762, 19, // spider 867, 892, 30, // baby gwani 874, 762, 17, // St-Bernard (Hound) 877, 778, 6, // Big ice dragon 880, 762, 18, // possessed Iolo 882, 892, 21, // flying red snake 883, 414, 3, // wingless gargoyle 885, 778, 3, // magic black horse 888, 414, 11, // female spanish dancer 906, 762, 21, // possessed Dupre 915, 400, 0, // brown tentacle 916, 414, 12, // male artist (purple coat + blue undies) 917, 402, 10, // male trapper (?) 945, 402, 29, // dressed iron automaton 946, 402, 27, // male mage (very blue outfit) 947, 402, 28, // gold male fighter (Silver Seed) 957, 402, 30, // catman creature (SS) 968, 402, 17, // ice golem 970, 892, 5, // sheep 975, 400, 20, // male fighter (brown outfit + chain mail) 978, 778, 9, // green dragon 979, 778, 10, // man spider 981, 402, 25, // liche 989, 400, 2, // white female avatar 1015, 402, 26, // female citizen (blue dress + green sleeves) 1024, 414, 28, // black male avatar 1025, 414, 29, // black female avatar 1026, 414, 30, // brown male avatar 1027, 414, 31, // brown female avatar 1028, 400, 1, // blonde male avatar 1029, 400, 2 // blonde female avatar /* the missing shapes */ //392, 0, 0, // old female mage with gold belt //482, 0, 0, // insivible woman //793, 0, 0, // Lord British //853, 0, 0, // invisible man //891, 0, 0, // naked male brown avatar //893, 0, 0, // naked male black avatar //921, 0, 0, // naked male blonde avatar //930, 0, 0, // naked female bonde avatar //933, 0, 0, // naked female black avatar //938, 0, 0, // naked female brown avatar //1030, 0, 0, // naked black male avatar //1031, 0, 0, // naked black female avatar //1032, 0, 0, // naked brown male avatar //1033, 0, 0, // naked brown female avatar //1034, 0, 0, // naked blonde male avatar //1035, 0, 0, // naked blonde female avatar }; #ifndef DONT_HAVE_HASH_SET /* * Hash function for triples in table: */ class Hash_shapes { public: // Return 'live' shape. size_t operator() (const short *t) const { return t[0]; } }; /* * For testing if two triples match. */ class Equal_shapes { public: bool operator() (const short *a, const short *b) const { return a[0] == b[0]; } }; #else /* * For testing whether one shape is less than another */ class Less_shapes { public: bool operator() (const short *a, const short *b) const { return a[0] < b[0]; } }; #endif /* * Lookup a shape's body. * * Output: 0 if not found. */ int Body_lookup::find ( int liveshape, // Live actor's shape. int& deadshape, // Dead shape returned. int& deadframe // Dead frame returned. ) { #ifndef DONT_HAVE_HASH_SET static hash_set *htable = 0; #else static std::set *htable = 0; #endif if (!htable) // First time? { #ifndef DONT_HAVE_HASH_SET htable = new hash_set(300); #else htable = new std::set(); #endif short *ptr; int cnt; if (Game::get_game_type() == BLACK_GATE) { cnt = sizeof(bg_table)/(3*sizeof(bg_table[0])); ptr = &bg_table[0]; } else { cnt = sizeof(si_table)/(3*sizeof(si_table[0])); ptr = &si_table[0]; } while (cnt--) // Add values. { htable->insert(ptr); ptr += 3; } } short key = (short) liveshape; #ifndef DONT_HAVE_HASH_SET hash_set::iterator it = htable->find(&key); #else std::set::iterator it = htable->find(&key); #endif if (it != htable->end()) { short *triple = *it; deadshape = triple[1]; deadframe = triple[2]; return 1; } else return 0; } /* * Recognize dead body shapes. +++++++Hopefully, there's a better way. */ int Is_body ( int shapeid ) { switch (shapeid) { case 400: case 414: case 762: case 778: case 892: return 1; case 402: return Game::get_game_type() == SERPENT_ISLE; default: return 0; } } exult-1.2/shapes/shapewrite.cc0000644000175000001440000001604307724430453012153 /* * shapewrite.cc - Write out the shape 'info' files. * * Note: Currently only used by ExultStudio. * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "shapevga.h" #include "shapeinf.h" #include "monstinf.h" #include "utils.h" #include "exceptions.h" using std::ifstream; using std::ios; using std::ofstream; /* * Write out data files about shapes. */ void Shapes_vga_file::write_info ( bool bg // True if BlackGate. ) { int i, cnt; bool have_patch_path = is_system_path_defined(""); assert(have_patch_path); // ShapeDims // Starts at 0x96'th shape. ofstream shpdims; U7open(shpdims, PATCH_SHPDIMS); for (i = 0x96; i < num_shapes; i++) { shpdims.put((char&) info[i].shpdims[0]); shpdims.put((char&) info[i].shpdims[1]); } // WGTVOL ofstream wgtvol; U7open(wgtvol, PATCH_WGTVOL); for (i = 0; i < num_shapes; i++) { wgtvol.put((char&) info[i].weight); wgtvol.put((char&) info[i].volume); } // TFA ofstream tfa; U7open(tfa, PATCH_TFA); for (i = 0; i < num_shapes; i++) tfa.write((char*)&info[i].tfa[0], 3); ofstream ready; U7open(ready, PATCH_READY); cnt = 0; for (i = 0; i < num_shapes; i++) if (info[i].ready_type != 255) cnt++; //++++Got to init ready_type to 255!!!!! ready.put(cnt); for (i = 0; i < num_shapes; i++) if (info[i].ready_type != 255) { Write2(ready, i); // Shape #. ready.put(info[i].ready_type); for (int j = 0; j < 6; j++) ready.put(0); // 6 0's. } ready.close(); ofstream armor; U7open(armor, PATCH_ARMOR); cnt = 0; for (i = 0; i < num_shapes; i++) if (info[i].armor != 0) cnt++; armor.put(cnt); for (i = 0; i < num_shapes; i++) if (info[i].armor != 0) info[i].armor->write(i, armor); armor.close(); ofstream weapon; U7open(weapon, PATCH_WEAPONS); cnt = 0; for (i = 0; i < num_shapes; i++) if (info[i].weapon) cnt++; weapon.put(cnt); for (i = 0; i < num_shapes; i++) if (info[i].weapon) info[i].weapon->write(i, weapon, bg); weapon.close(); ofstream ammo; U7open(ammo, PATCH_AMMO); cnt = 0; for (i = 0; i < num_shapes; i++) if (info[i].ammo) cnt++; ammo.put(cnt); for (i = 0; i < num_shapes; i++) if (info[i].ammo) info[i].ammo->write(i, ammo); ammo.close(); // Write data about drawing the weapon in an actor's hand ofstream wihh; U7open(wihh, PATCH_WIHH); cnt = 0; // Keep track of actual entries. for (i = 0; i < num_shapes; i++) if (info[i].weapon_offsets == 0) Write2(wihh, 0);// None for this shape. else // Write where it will go. Write2(wihh, 2*1024 + 64*(cnt++)); for (i = 0; i < num_shapes; i++) if (info[i].weapon_offsets) // There are two bytes per frame: 64 total wihh.write((char *)(info[i].weapon_offsets), 64); wihh.close(); ofstream mfile; // Now get monster info. U7open(mfile, PATCH_MONSTERS); cnt = 0; for (i = 0; i < num_shapes; i++) if (info[i].monstinf) cnt++; mfile.put(cnt); for (i = 0; i < num_shapes; i++) if (info[i].monstinf) info[i].monstinf->write(i, mfile); mfile.close(); U7open(mfile, PATCH_EQUIP); // Write 'equip.dat'. cnt = Monster_info::get_equip_cnt(); mfile.put(cnt); for (i = 0; i < cnt; i++) { Equip_record& rec = Monster_info::get_equip(i); // 10 elements/record. for (int e = 0; e < 10; e++) { Equip_element& elem = rec.get(e); Write2(mfile, elem.get_shapenum()); mfile.put(elem.get_probability()); mfile.put(elem.get_quantity()); Write2(mfile, 0); } } mfile.close(); ofstream(occ); // Write occlude.dat. U7open(occ, PATCH_OCCLUDE); unsigned char occbits[128]; // 1024 bit flags. // +++++This could be rewritten better! memset(&occbits[0], 0, sizeof(occbits)); for (i = 0; i < sizeof(occbits); i++) { unsigned char bits = 0; int shnum = i*8; // Check each bit. for (int b = 0; b < 8; b++) if (shnum + b >= num_shapes) break; else if (info[shnum + b].occludes_flag) bits |= (1< #endif #include #include #ifdef MACOS #include #endif #include "fontvga.h" #include "fnames.h" #ifndef ALPHA_LINUX_CXX # include #endif #include "utils.h" using std::cout; using std::endl; // using std::string; /* * Fonts in 'fonts.vga': * * 0 = Normal yellow. * 1 = Large runes. * 2 = small black (as in zstats). * 3 = runes. * 4 = tiny black, used in books. * 5 = little white, glowing, for spellbooks. * 6 = runes. * 7 = normal red. * 8 = Serpentine (books) * 9 = Serpentine (signs) * 10 = Serpentine (gold signs) */ /* * Horizontal leads, by fontnum: * * This must include the Endgame fonts (currently 32-35)!! * And the MAINSHP font (36) * However, their values are set elsewhere */ //static int hlead[NUM_FONTS] = {-1, 0, 1, 0, 1, 0, 0, -1, 0, 0}; // For scrolls (12/6/00): static int hlead[NUM_FONTS] = {-2, -1, 0, -1, 0, 0, -1, -2, -1, -1, 0, 0}; /* * Initialize. */ void Fonts_vga_file::init ( ) { int cnt = sizeof(fonts)/sizeof(fonts[0]); const char *fname = U7exists(PATCH_FONTS) ? PATCH_FONTS : FONTS_VGA; for (int i = 0; i < cnt; i++) fonts[i].load(fname, i, hlead[i], 0); } exult-1.2/shapes/vgafile.h0000644000175000001440000002134207724430453011255 /* * vgafile.h - Handle access to one of the xxx.vga files. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef VGAFILE_H #define VGAFILE_H 1 #include #include #include #include "exult_types.h" #include "imagebuf.h" class DataSource; class StreamDataSource; class Shape; class Image_buffer8; class GL_texshape; class GL_manager; #ifdef HAVE_OPENGL #include "glshape.h" #define GLRENDER if (glman) glman->paint(this, px, py); else #define GLRENDERTRANS if (glman) glman->paint(this, px, py, xforms, xfcnt); \ else #define GLOUTLINE if (glman) ; else #else #define GLRENDER #define GLRENDERTRANS #define GLOUTLINE #endif /* * A shape from "shapes.vga": */ class Shape_frame { bool rle; // Run-length encoded. unsigned char *data; // The actual data. int datalen; short xleft; // Extent to left of origin. short xright; // Extent to right. short yabove; // Extent above origin. short ybelow; // Extent below origin. #ifdef HAVE_OPENGL GL_texshape *glshape; // OpenGL texture for painting this. #endif static GL_manager *glman; // One to rule them all. static Image_buffer8 *scrwin; // Screen window to render to. Shape_frame *reflect(); // Create new frame, reflected. // Create RLE data & store in frame. void create_rle(unsigned char *pixels, int w, int h); // Create from RLE entry. void get_rle_shape(DataSource* shapes, long filepos, long len); public: friend class Game_window; friend class Shape_manager; friend class Shape; friend class Shape_file; friend class GL_texshape; friend class GL_manager; Shape_frame() : data(0), datalen(0) #ifdef HAVE_OPENGL , glshape(0) #endif { } // Create frame from data. Shape_frame(unsigned char *pixels, int w, int h, int xoff, int yoff, bool setrle); static void set_to_render(Image_buffer8 *w, GL_manager *gl = 0) { scrwin = w; glman = gl; } unsigned char *get_data() { return data; } bool is_rle() const { return rle; } // Convert raw image to RLE. static unsigned char *encode_rle(unsigned char *pixels, int w, int h, int xoff, int yoff, int& datalen); // Read in shape/frame. unsigned char read(DataSource* shapes, uint32 shapeoff, uint32 shapelen, int frnum); // Paint into given buffer. void paint_rle(Image_buffer8 *win, int px, int py); void paint(Image_buffer8 *win, int px, int py); void paint_rle_translucent(Image_buffer8 *win, int px, int py, Xform_palette *xforms, int xfcnt); void paint_rle_transformed(Image_buffer8 *win, int px, int py, Xform_palette& xform); void paint_rle_outline(Image_buffer8 *win, int px, int py, unsigned char color); // Paint to screen. void paint_rle(int px, int py) { GLRENDER paint_rle(scrwin, px, py); } void paint(int px, int py) { GLRENDER paint(scrwin, px, py); } // ++++++GL versions of these needed: void paint_rle_translucent(int px, int py, Xform_palette *xforms, int xfcnt) { GLRENDERTRANS paint_rle_translucent( scrwin, px, py, xforms, xfcnt); } void paint_rle_transformed(int px, int py, Xform_palette& xform) { GLRENDER paint_rle_transformed(scrwin, px, py, xform); } void paint_rle_outline(int px, int py, unsigned char color) { GLOUTLINE paint_rle_outline(scrwin, px, py, color); } int has_point(int x, int y); // Is a point within the shape? int get_width() const // Get dimensions. { return xleft + xright + 1; } int get_height() const { return yabove + ybelow + 1; } int get_xleft() { return xleft; } int get_xright() { return xright; } int get_yabove() { return yabove; } int get_ybelow() { return ybelow; } void set_offset(int new_xright, int new_ybelow); int get_size() { return datalen; } int is_empty() { return data[0] == 0 && data[1] == 0; } virtual ~Shape_frame() { delete [] data; } }; /* * A shape from a .vga file consists of one of more frames. */ class Shape { protected: Shape_frame **frames; // List of ->'s to frames. unsigned char frames_size; // Size of 'frames' (incl. reflects). unsigned char num_frames; // # of frames (not counting reflects). // Create reflected frame. Shape_frame *reflect(DataSource* shapes, int shnum, int frnum); void enlarge(int newsize); // Increase 'frames'. void create_frames_list(int nframes); // Read in shape/frame. Shape_frame *read(DataSource* shapes, int shnum, int frnum, DataSource *shapes2 = 0, int count1 = -1, int count2 = -1); // Store shape that was read. Shape_frame *store_frame(Shape_frame *frame, int framenum); public: friend class Vga_file; Shape() : frames(0), frames_size(0), num_frames(0) { } Shape(Shape_frame* fr); Shape(int n); // Create with given #frames. virtual ~Shape(); void reset(); void take(Shape *s2); // Take frames from another shape. void load(DataSource* shape_source); void write(std::ostream& out); // Write out. Shape_frame *get(DataSource* shapes, int shnum, int frnum, DataSource *shapes2 = 0, int count1 = -1, int count2 = -1) { return (frames && frnum < frames_size && frames[frnum]) ? frames[frnum] : read(shapes, shnum, frnum, shapes2, count1, count2); } int get_num_frames() { return num_frames; } Shape_frame *get_frame(int framenum) { return 0 <= framenum && framenum < frames_size ? frames[framenum] : 0L; } void resize(int newsize); // Modify #frames. // Set frame. void set_frame(Shape_frame *f, int framenum); // Add/insert frame. void add_frame(Shape_frame *f, int framenum); void del_frame(int framenum); }; /* * A shape file just has one shape with multiple frames. They're all * read in during construction. */ class Shape_file : public Shape { public: Shape_file(const char *nm); Shape_file(Shape_frame *fr): Shape(fr) {} Shape_file(DataSource* shape_source); Shape_file(); virtual ~Shape_file() {} void load(const char *nm); void load(DataSource* shape_source) { Shape::load(shape_source); } int get_size(); void save(DataSource* shape_source); }; /* * A class for accessing any .vga file: */ class Vga_file { std::ifstream file; DataSource *shape_source; std::ifstream file2; DataSource *shape_source2; int u7drag_type; // # from u7drag.h, or -1. bool flex; // This is the normal case (all .vga // files). If false, file is a // single shape, like 'pointers.shp'. // In this case, all frames are pre- // loaded. protected: int num_shapes; // Total # of shapes. int num_shapes1; // Total # of shapes in file 1. int num_shapes2; // Total # of shapes in file 2. Shape *shapes; // List of ->'s to shapes' lists public: Vga_file(const char *nm, int u7drag = -1, const char *nm2 = 0); Vga_file(); int get_u7drag_type() const { return u7drag_type; } void load(const char *nm, const char *nm2 = 0); void reset(); virtual ~Vga_file(); int get_num_shapes() const { return num_shapes>num_shapes2?num_shapes:num_shapes2; } int is_good() const { return shapes != 0; } bool is_flex() const { return flex; } // Get shape. Shape_frame *get_shape(int shapenum, int framenum = 0) { assert(shapes!=0); // Because if shapes is NULL // here, we won't die on the deref // but we will return rubbish. // I've put this assert in _before_ you know... // So this isn't the first time we've had trouble here Shape_frame *r=(shapes[shapenum].get(shape_source, shapenum, framenum, shape_source2, num_shapes1, num_shapes2)); #if 0 /* Occurs normally in ExultStudio. */ if(!r) { #ifdef DEBUG std::cerr << "get_shape(" << shapenum << "," << framenum << ") -> NULL" << std::endl; #endif } #endif return r; } Shape *extract_shape(int shapenum) { assert(shapes!=0); // Load all frames into memory int count = get_num_frames(shapenum); for(int i=1; i #endif #include "U7file.h" #include "databuf.h" #include "font.h" #include "ibuf8.h" #include "vgafile.h" #include "exceptions.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::size_t; using std::string; using std::strncmp; #endif FontManager fontManager; // Want a more restrictive test for space. inline bool Is_space(char c) { return c == ' ' || c == '\n' || c == '\t'; } /* * Pass space. */ static const char *Pass_space ( const char *text ) { while (Is_space(*text)) text++; return (text); } /* * Pass a word. */ static const char *Pass_word ( const char *text ) { while (*text && (!Is_space(*text) || (*text == '\f') || (*text == '\v'))) text++; return (text); } /* * Draw text within a rectangular area. * Special characters handled are: * \n New line. * space Word break. * tab Treated like a space for now. * * Output: If out of room, -offset of end of text painted. * Else height of text painted. */ int Font::paint_text_box ( Image_buffer8 *win, // Buffer to paint in. const char *text, int x, int y, // Top-left corner of box. int w, int h, // Dimensions. int vert_lead, // Extra spacing between lines. int pbreak // End at punctuation. ) { const char *start = text; // Remember the start. win->set_clip(x, y, w, h); int endx = x + w; // Figure where to stop. int curx = x, cury = y; int height = get_text_height() + vert_lead + ver_lead; int space_width = get_text_width(" ", 1); int max_lines = h/height; // # lines that can be shown. string *lines = new string[max_lines + 1]; int cur_line = 0; const char *last_punct_end = 0;// ->last period, qmark, etc. // Last punct in 'lines': int last_punct_line = -1, last_punct_offset = -1; while (*text) { switch (*text) // Special cases. { case '\n': // Next line. curx = x; text++; cur_line++; if (cur_line >= max_lines) break; // No more room. continue; case '\r': //?? text++; continue; case ' ': // Space. case '\t': { // Pass space. const char *wrd = Pass_space(text); if (wrd != text) { int w = get_text_width(text, wrd - text); if (w <= 0) w = space_width; int nsp = w/space_width; lines[cur_line].append(nsp, ' '); curx += nsp*space_width; } text = wrd; break; } } if (cur_line >= max_lines) break; // Pass word & get its width. const char *ewrd = Pass_word(text); int width = get_text_width(text, ewrd - text); if (curx + width - hor_lead > endx) { // Word-wrap. curx = x; cur_line++; if (cur_line >= max_lines) break; // No more room. } // Store word. lines[cur_line].append(text, ewrd - text); curx += width; text = ewrd; // Continue past the word. // Keep loc. of punct. endings. if (text[-1] == '.' || text[-1] == '?' || text[-1] == '!' || text[-1] == ',') { last_punct_end = text; last_punct_line = cur_line; last_punct_offset = lines[cur_line].length(); } } if (*text && // Out of room? // Break off at end of punct. pbreak && last_punct_end) text = Pass_space(last_punct_end); else last_punct_line = -1; // Render text. for (int i = 0; i <= cur_line; i++) { const char *str = lines[i].data(); int len = lines[i].length(); if (i == last_punct_line) len = last_punct_offset; paint_text(win, str, len, x, cury); cury += height; if (i == last_punct_line) break; } win->clear_clip(); delete [] lines; if (*text) // Out of room? return -(text - start); // Return -offset of end. else // Else return height. return (cury - y); } /* * Draw text at a given location (which is the upper-left corner of the * place to draw. * * Output: Width in pixels of what was drawn. */ int Font::paint_text ( Image_buffer8 *win, // Buffer to paint in. const char *text, // What to draw, 0-delimited. int xoff, int yoff // Upper-left corner of where to start. ) { int x = xoff; int chr; yoff += get_text_baseline(); if (font_shapes) while ((chr = *text++) != 0) { Shape_frame *shape = font_shapes->get_frame((unsigned char)chr); if (!shape) continue; shape->paint_rle(x, yoff); x += shape->get_width() + hor_lead; } return (x - xoff); } /* * Paint text using font from "fonts.vga". * * Output: Width in pixels of what was painted. */ int Font::paint_text ( Image_buffer8 *win, // Buffer to paint in. const char *text, // What to draw. int textlen, // Length of text. int xoff, int yoff // Upper-left corner of where to start. ) { int x = xoff; yoff += get_text_baseline(); if (font_shapes) while (textlen--) { Shape_frame *shape= font_shapes->get_frame((unsigned char)*text++); if (!shape) continue; shape->paint_rle(x, yoff); x += shape->get_width() + hor_lead; } return (x - xoff); } /* * * FIXED WIDTH RENDERING * */ /* * Draw text within a rectangular area. * Special characters handled are: * \n New line. * space Word break. * tab Treated like a space for now. * * Output: If out of room, -offset of end of text painted. * Else height of text painted. */ int Font::paint_text_box_fixedwidth ( Image_buffer8 *win, // Buffer to paint in. const char *text, int x, int y, // Top-left corner of box. int w, int h, // Dimensions. int char_width, // Width of each character int vert_lead, // Extra spacing between lines. int pbreak // End at punctuation. ) { const char *start = text; // Remember the start. win->set_clip(x, y, w, h); int endx = x + w; // Figure where to stop. int curx = x, cury = y; int height = get_text_height() + vert_lead + ver_lead; int max_lines = h/height; // # lines that can be shown. string *lines = new string[max_lines + 1]; int cur_line = 0; const char *last_punct_end = 0;// ->last period, qmark, etc. // Last punct in 'lines': int last_punct_line = -1, last_punct_offset = -1; while (*text) { switch (*text) // Special cases. { case '\n': // Next line. curx = x; text++; cur_line++; if (cur_line >= max_lines) break; // No more room. continue; case ' ': // Space. case '\t': { // Pass space. const char *wrd = Pass_space(text); if (wrd != text) { int w = (wrd - text) * char_width; if (!w) w = char_width; int nsp = w/char_width; lines[cur_line].append(nsp, ' '); curx += nsp*char_width; } text = wrd; break; } } if (cur_line >= max_lines) break; // Pass word & get its width. const char *ewrd = Pass_word(text); int width = (ewrd - text) * char_width; if (curx + width - hor_lead > endx) { // Word-wrap. curx = x; cur_line++; if (cur_line >= max_lines) break; // No more room. } // Store word. lines[cur_line].append(text, ewrd - text); curx += width; text = ewrd; // Continue past the word. // Keep loc. of punct. endings. if (text[-1] == '.' || text[-1] == '?' || text[-1] == '!' || text[-1] == ',') { last_punct_end = text; last_punct_line = cur_line; last_punct_offset = lines[cur_line].length(); } } if (*text && // Out of room? // Break off at end of punct. pbreak && last_punct_end) text = Pass_space(last_punct_end); else last_punct_line = -1; // Render text. for (int i = 0; i <= cur_line; i++) { const char *str = lines[i].data(); int len = lines[i].length(); if (i == last_punct_line) len = last_punct_offset; paint_text_fixedwidth(win, str, len, x, cury, char_width); cury += height; if (i == last_punct_line) break; } win->clear_clip(); delete [] lines; if (*text) // Out of room? return -(text - start); // Return -offset of end. else // Else return height. return (cury - y); } /* * Draw text at a given location (which is the upper-left corner of the * place to draw. Text will be drawn with the fixed width specified. * * Output: Width in pixels of what was drawn. */ int Font::paint_text_fixedwidth ( Image_buffer8 *win, // Buffer to paint in. const char *text, // What to draw, 0-delimited. int xoff, int yoff, // Upper-left corner of where to start. int width // Width of each character ) { int x = xoff; int w; int chr; yoff += get_text_baseline(); while ((chr = *text++) != 0) { Shape_frame *shape = font_shapes->get_frame((unsigned char)chr); if (!shape) continue; x += w = (width - shape->get_width()) / 2; shape->paint_rle(x, yoff); x += width - w; } return (x - xoff); } /* * Draw text at a given location (which is the upper-left corner of the * place to draw. Text will be drawn with the fixed width specified. * * Output: Width in pixels of what was drawn. */ int Font::paint_text_fixedwidth ( Image_buffer8 *win, // Buffer to paint in. const char *text, // What to draw. int textlen, // Length of text. int xoff, int yoff, // Upper-left corner of where to start. int width // Width of each character ) { int w; int x = xoff; yoff += get_text_baseline(); while (textlen--) { Shape_frame *shape = font_shapes->get_frame((unsigned char) *text++); if (!shape) continue; x += w = (width - shape->get_width()) / 2; shape->paint_rle(x, yoff); x += width - w; } return (x - xoff); } /* * Get the width in pixels of a 0-delimited string. */ int Font::get_text_width ( const char *text ) { int width = 0; short chr; if (font_shapes) while ((chr = *text++) != 0) { Shape_frame* shape = font_shapes->get_frame((unsigned char)chr); if (shape) width += shape->get_width() + hor_lead; } return (width); } /* * Get the width in pixels of a string given by length. */ int Font::get_text_width ( const char *text, int textlen // Length of text. ) { int width = 0; if (font_shapes) while (textlen--) { Shape_frame* shape =font_shapes->get_frame((unsigned char)*text++); if (shape) width += shape->get_width() + hor_lead; } return (width); } /* * Get font line-height. */ int Font::get_text_height ( ) { // Note, I wont assume the fonts exist //Shape_frame *A = font_shapes->get_frame('A'); //Shape_frame *y = font_shapes->get_frame('y'); return highest + lowest + 1; } /* * Get font baseline as the distance from the top. */ int Font::get_text_baseline ( ) { //Shape_frame *A = font_shapes->get_frame('A'); return highest; } Font::Font(): font_shapes(0), font_data(0), font_buf(0), orig_font_buf(0) { } Font::Font(const char *fname, int index, int hlead, int vlead): font_shapes(0), font_data(0), font_buf(0), orig_font_buf(0) { load(fname, index, hlead, vlead); } Font::~Font() { if(font_shapes) delete font_shapes; if(font_data) delete font_data; if(orig_font_buf) delete [] orig_font_buf; } int Font::load(const char *fname, int index, int hlead, int vlead) { if(font_shapes) delete font_shapes; if (font_data) delete font_data; if(orig_font_buf) delete [] orig_font_buf; font_shapes = 0; font_data = 0; orig_font_buf = 0; try { size_t len; U7object font_obj(fname, index); font_buf = font_obj.retrieve(len); if (!font_buf || !len) throw (exult_exception ("Unable to retrieve data")); orig_font_buf = font_buf; if(!strncmp(font_buf,"font",4)) // If it's an IFF archive... font_buf += 8; // Skip first 8 bytes font_data = new BufferDataSource(font_buf, len); font_shapes = new Shape_file(font_data); hor_lead = hlead; ver_lead = vlead; calc_highlow(); } catch (exult_exception &e) { font_data = 0; font_shapes = 0; hor_lead = 0; ver_lead = 0; orig_font_buf = 0; } return 0; } int Font::center_text(Image_buffer8 *win, int x, int y, const char *s) { return draw_text(win, x - get_text_width(s)/2, y, s); } void Font::calc_highlow() { bool unset = true; for (int i = 0; i < font_shapes->get_num_frames(); i++) { Shape_frame *f = font_shapes->get_frame(i); if (!f) continue; if (unset) { unset = false; highest = f->get_yabove(); lowest = f->get_ybelow(); continue; } if (f->get_yabove() > highest) highest = f->get_yabove(); if (f->get_ybelow() > lowest) lowest = f->get_ybelow(); } } FontManager::FontManager() { } FontManager::~FontManager() { fonts.clear(); } void FontManager::add_font(const char *name, const char *archive, int index, int hlead, int vlead) { remove_font(name); Font *font = new Font(archive, index, hlead, vlead); fonts[name] = font; } void FontManager::remove_font(const char *name) { if(fonts[name]!=0) { delete fonts[name]; fonts.erase(name); } } Font *FontManager::get_font(const char *name) { return fonts[name]; } void FontManager::reset() { #ifndef DONT_HAVE_HASH_MAP hash_map::iterator i; #else std::map::iterator i; #endif for (i=fonts.begin(); i != fonts.end(); ++i) { delete (*i).second; } fonts.clear(); } exult-1.2/shapes/font.h0000644000175000001440000000552607724430453010614 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef FONT_H #define FONT_H #include "hash_utils.h" class Image_buffer8; class Shape_file; class DataSource; /* * A single font: */ class Font { private: int hor_lead; int ver_lead; Shape_file *font_shapes; DataSource *font_data; char *font_buf; char *orig_font_buf; int highest, lowest; void calc_highlow(); public: Font(); Font(const char *fname, int index, int hlead=0, int vlead=1); ~Font(); int load(const char *fname, int index, int hlead=0, int vlead=1); // Text rendering: int paint_text_box(Image_buffer8 *win, const char *text, int x, int y, int w, int h, int vert_lead = 0, int pbreak = 0); int paint_text(Image_buffer8 *win, const char *text, int xoff, int yoff); int paint_text(Image_buffer8 *win, const char *text, int textlen, int xoff, int yoff); int paint_text_box_fixedwidth(Image_buffer8 *win, const char *text, int x, int y, int w, int h, int char_width, int vert_lead = 0, int pbreak = 0); int paint_text_fixedwidth(Image_buffer8 *win, const char *text, int xoff, int yoff, int width); int paint_text_fixedwidth(Image_buffer8 *win, const char *text, int textlen, int xoff, int yoff, int width); // Get text width. int get_text_width(const char *text); int get_text_width(const char *text, int textlen); // Get text height, baseline. int get_text_height(); int get_text_baseline(); int draw_text(Image_buffer8 *win, int x, int y, const char *s) { return paint_text(win, s, x, y); } int draw_text_box(Image_buffer8 *win, int x, int y, int w, int h, const char *s) { return paint_text_box(win, s, x, y, w, h, 0, 0); } int center_text(Image_buffer8 *iwin, int x, int y, const char *s); }; /* * Manage a list of fonts by name. */ class FontManager { private: #ifndef DONT_HAVE_HASH_MAP hash_map fonts; #else std::map fonts; #endif public: FontManager(); ~FontManager(); void add_font(const char *name, const char *archive, int index, int hlead=0, int vlead=1); void remove_font(const char *name); Font *get_font(const char *name); void reset(); }; extern FontManager fontManager; #endif exult-1.2/shapes/u7drag.cc0000644000175000001440000000660007466555712011200 /** ** U7drag.cc - Common defines for drag-and-drop of U7 shapes. ** ** Written: 12/13/00 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "u7drag.h" #include "utils.h" /* * Store in char array. * * Output: Length of what's stored. */ int Store_u7_shapeid ( unsigned char *data, // At least 4 bytes. int file, // 0-255. int shape, // 0-0xffff. int frame // 0-255. ) { unsigned char *ptr = data; *ptr++ = file; Write2(ptr, shape); *ptr++ = frame; return (ptr - data); } /* * Retrieve shapeid. */ void Get_u7_shapeid ( unsigned char *data, // At least 4 bytes. int& file, // 0-255. int& shape, // 0-0xffff. int& frame // 0-255. ) { unsigned char *ptr = data; file = *ptr++; shape = Read2(ptr); frame = *ptr; } /* * Store in char array. * * Output: Length of what's stored. */ int Store_u7_chunkid ( unsigned char *data, // At least 4 bytes. int cnum // Chunk #. ) { unsigned char *ptr = data; Write2(ptr, cnum); return (ptr - data); } /* * Retrieve cnum#. */ void Get_u7_chunkid ( unsigned char *data, // At least 4 bytes. int& cnum // 0-0xffff returned. ) { unsigned char *ptr = data; cnum = Read2(ptr); } /* * Store combo. * * Output: Length of data stored. */ int Store_u7_comboid ( unsigned char *data, int xtiles, int ytiles, // Footprint in tiles. int tiles_right, // Tiles to right of hot-spot. int tiles_below, // Tiles below hot-spot. int cnt, // # members. U7_combo_data *ents // The members, with locs. relative to // hot-spot. ) { unsigned char *ptr = data; Write2(ptr, xtiles); Write2(ptr, ytiles); Write2(ptr, tiles_right); Write2(ptr, tiles_below); Write2(ptr, cnt); for (int i = 0; i < cnt; i++) { Write2(ptr, ents[i].tx); Write2(ptr, ents[i].ty); Write2(ptr, ents[i].tz); Write2(ptr, ents[i].shape); *ptr++ = (unsigned char) ents[i].frame; } return (ptr - data); } /* * Retrieve a combo. * * Output: cnt = #elements. * ents = ALLOCATED array of shapes with offsets rel. to hot-spot. */ void Get_u7_comboid ( unsigned char *data, int& xtiles, int& ytiles, // Footprint in tiles. int& tiles_right, // Tiles to right of hot-spot. int& tiles_below, // Tiles below hot-spot. int& cnt, U7_combo_data *& ents ) { unsigned char *ptr = data; xtiles = Read2(ptr); ytiles = Read2(ptr); tiles_right = Read2(ptr); tiles_below = Read2(ptr); cnt = Read2(ptr); ents = new U7_combo_data[cnt]; for (int i = 0; i < cnt; i++) { // Tiles can be negative! ents[i].tx = (int) (short) Read2(ptr); ents[i].ty = (int) (short) Read2(ptr); ents[i].tz = (int) (short) Read2(ptr); ents[i].shape = Read2(ptr); ents[i].frame = *ptr++; } } exult-1.2/shapes/Makefile.am0000644000175000001440000000113007561255307011516 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ $(SDL_CFLAGS) $(FREETYPE2_INCLUDES) \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libshapes.la libshapes_la_SOURCES = \ bodies.cc \ bodies.h \ font.cc \ font.h \ fontgen.cc \ fontgen.h \ fontvga.cc \ fontvga.h \ glshape.cc \ glshape.h \ items.cc \ items.h \ monstinf.cc \ monstinf.h \ pngio.cc \ pngio.h \ shapeinf.cc \ shapeinf.h \ shapevga.cc \ shapevga.h \ shapewrite.cc \ u7drag.cc \ u7drag.h \ vgafile.cc \ vgafile.h CLEANFILES = *~ exult-1.2/shapes/Makefile.in0000644000175000001440000002650010061527050011521 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ $(SDL_CFLAGS) $(FREETYPE2_INCLUDES) \ $(INCDIRS) $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libshapes.la libshapes_la_SOURCES = \ bodies.cc \ bodies.h \ font.cc \ font.h \ fontgen.cc \ fontgen.h \ fontvga.cc \ fontvga.h \ glshape.cc \ glshape.h \ items.cc \ items.h \ monstinf.cc \ monstinf.h \ pngio.cc \ pngio.h \ shapeinf.cc \ shapeinf.h \ shapevga.cc \ shapevga.h \ shapewrite.cc \ u7drag.cc \ u7drag.h \ vgafile.cc \ vgafile.h CLEANFILES = *~ subdir = shapes mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libshapes_la_LDFLAGS = libshapes_la_LIBADD = am_libshapes_la_OBJECTS = bodies.lo font.lo fontgen.lo fontvga.lo \ glshape.lo items.lo monstinf.lo pngio.lo shapeinf.lo \ shapevga.lo shapewrite.lo u7drag.lo vgafile.lo libshapes_la_OBJECTS = $(am_libshapes_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/bodies.Plo $(DEPDIR)/font.Plo \ @AMDEP_TRUE@ $(DEPDIR)/fontgen.Plo $(DEPDIR)/fontvga.Plo \ @AMDEP_TRUE@ $(DEPDIR)/glshape.Plo $(DEPDIR)/items.Plo \ @AMDEP_TRUE@ $(DEPDIR)/monstinf.Plo $(DEPDIR)/pngio.Plo \ @AMDEP_TRUE@ $(DEPDIR)/shapeinf.Plo $(DEPDIR)/shapevga.Plo \ @AMDEP_TRUE@ $(DEPDIR)/shapewrite.Plo $(DEPDIR)/u7drag.Plo \ @AMDEP_TRUE@ $(DEPDIR)/vgafile.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libshapes_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libshapes_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu shapes/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libshapes.la: $(libshapes_la_OBJECTS) $(libshapes_la_DEPENDENCIES) $(CXXLINK) $(libshapes_la_LDFLAGS) $(libshapes_la_OBJECTS) $(libshapes_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bodies.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/font.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fontgen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fontvga.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/glshape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/items.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/monstinf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapeinf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapevga.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/shapewrite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/u7drag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/vgafile.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/shapes/monstinf.cc0000644000175000001440000000601407520504106011621 /** ** Monstinf.cc - Information (about NPC's, really) from 'monster.dat'. ** ** Written: 8/13/01 - JSF **/ /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "utils.h" #include "monstinf.h" // #include "items.h" using std::ios; using std::cout; using std::endl; using std::istream; Equip_record *Monster_info::equip = 0; int Monster_info::equip_cnt = 0; Monster_info Monster_info::default_info; /* * Read in monster info. from 'monsters.dat'. * * Output: Shape # this entry describes. */ int Monster_info::read ( istream& in // Read from here. ) { uint8 buf[25]; // Entry length. in.read((char *) buf, sizeof(buf)); uint8 *ptr = buf; int shapenum = Read2(ptr); // Bytes 0-1. strength = (*ptr++ >> 2) & 63; // Byte 2. dexterity = (*ptr++ >> 2) & 63; // Byte 3. m_poison_safe = (*ptr&1) != 0; // This looks reasonable, as it // includes automaton, slug, spider. // if (poison_safe) // cout << "Shape " << item_names[shapenum] << " is poison_safe"<< endl; intelligence = (*ptr++ >> 2) & 63; // Byte 4. alignment = *ptr & 3; // Byte 5. combat = (*ptr++ >> 2) & 63; m_splits = (*ptr & 1) != 0; // Byte 6 (slimes). m_cant_die = (*ptr & 2) != 0; armor = (*ptr++ >> 4) & 15; ptr++; // Unknown. reach = *ptr & 15; // Byte 8 - weapon reach. weapon = (*ptr++ >> 4) & 15; flags = *ptr++; // Byte 9. vulnerable = *ptr++; immune = *ptr++; m_cant_yell = (*ptr & (1<<5)) != 0; m_cant_bleed = (*ptr & (1<<6)) != 0; ptr++; ptr++; // Unknown. equip_offset = *ptr++; // Byte 13. return shapenum; } /* * Get a default block for generic NPC's. */ const Monster_info *Monster_info::get_default ( ) { if (!default_info.strength) // First time? { default_info.strength = default_info.dexterity = default_info.intelligence = default_info.combat = 4; default_info.alignment = 0; // Neutral. default_info.m_splits = default_info.m_cant_die = false; default_info.armor = default_info.weapon = default_info.reach = 0; default_info.flags = (1<<(int) walk); default_info.equip_offset = 0; } return &default_info; } /* * Set all the stats. */ void Monster_info::set_stats ( int str, int dex, int intel, int cmb, int armour, int wpn, int rch ) { strength = str; dexterity = dex; intelligence = intel; combat = cmb; armor = armour; weapon = wpn; reach = rch; } exult-1.2/shapes/items.cc0000644000175000001440000000441507676513266011133 /** ** Items.cc - Names of items. ** ** Written: 11/5/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif // #include /* Debugging */ #include #include #include "items.h" #include "utils.h" #include "msgfile.h" using std::ifstream; using std::cerr; using std::endl; using std::vector; char **item_names; // Names of U7 items. int num_item_names; /* * Set up names of items. * * Frame names start at entry 0x500 (reagents,medallions,food,etc.). */ void Setup_item_names (ifstream& items, ifstream& msgs) { vector msglist; int first_msg; // First in exultmsg.txt. Should // follow those in text.flx. items.seekg(0x54); int flxcnt = Read4(items); first_msg = num_item_names = flxcnt; if (msgs.good()) { // Exult msgs. too? first_msg = Read_text_msg_file(msgs, msglist); if (first_msg >= 0) { if (first_msg < num_item_names) { cerr << "Exult msg. # " << first_msg << " conflicts with 'text.flx'" << endl; first_msg = num_item_names; } num_item_names = msglist.size(); } else first_msg = num_item_names; } item_names = new char *[num_item_names]; int i; for(i=0; i < flxcnt; i++) { items.seekg(0x80+i*8); int itemoffs = Read4(items); if(!itemoffs) continue; int itemlen = Read4(items); items.seekg(itemoffs); item_names[i] = new char[itemlen]; items.read(item_names[i], itemlen); #if 0 cout << dec << i << " 0x" << hex << i << dec << "\t" << item_names[i] << endl; #endif } for (i = first_msg; i < num_item_names; i++) item_names[i] = msglist[i]; } exult-1.2/shapes/shapeinf.cc0000644000175000001440000001260110040666771011570 /** ** Shapeinf.cc: Info. about shapes read from various 'static' data files. ** ** Written: 4/29/99 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman Copyright (C) 1999-2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "shapeinf.h" #include "monstinf.h" #include "utils.h" #include /* Debugging */ using std::cout; using std::endl; /* * Read in a weapon-info entry from 'weapons.dat'. * * Output: Shape # this entry describes. */ int Weapon_info::read ( std::istream& in, // Read from here. bool bg ) { uint8 buf[21]; // Entry length. in.read((char *) buf, sizeof(buf)); uint8 *ptr = buf; int shapenum = Read2(ptr); // Bytes 0-1. ammo = Read2(ptr); // This is ammo family, or a neg. #. // Shape to strike with, or projectile // shape if shoot/throw. projectile = Read2(ptr); #if 0 extern char **item_names; cout << dec << "Weapon " // << item_names[shapenum] << '(' << shapenum << ')' << endl; #endif // +++++Wonder what strike < 0 means. if (projectile == shapenum || projectile < 0) projectile = 0; // Means no projectile thrown. damage = *ptr++; unsigned char flags0 = *ptr++; m_explodes = (flags0>>1)&1; m_no_blocking = (flags0>>2)&1; damage_type = (flags0>>4)&15; range = *ptr++; uses = (range>>1)&3; // Throwable, etc.: range = range>>3; unsigned char flags1 = *ptr++; m_returns = (flags1&1); #if 0 unsigned char unk1 = *ptr++; // Figured it out now... I think. cout << "Unk1 = " << hex << "0x" << setfill('0') << setw(2) <<(int)unk1 << endl; #endif actor_frames = (*ptr++)&15; powers = *ptr++; *ptr++; // Skip (0). usecode = Read2(ptr); // BG: Subtract 1 from each sfx. int sfx_delta = bg ? -1 : 0; sfx = Read2(ptr) + sfx_delta; hitsfx = Read2(ptr) + sfx_delta; if (hitsfx == 123 && !bg) // SerpentIsle: Does not sound right. hitsfx = 61; // Sounds more like a weapon. return shapenum; } /* * Read in an ammo-info entry from 'ammo.dat'. * * Output: Shape # this entry describes. */ int Ammo_info::read ( std::istream& in // Read from here. ) { uint8 buf[13]; // Entry length. in.read((char *) buf, sizeof(buf)); uint8 *ptr = buf; int shapenum = Read2(ptr); // Bytes 0-1. family_shape = Read2(ptr); type2 = Read2(ptr); // ??? damage = *ptr++; ptr += 2; // 2 unknown. unsigned char flags0 = *ptr++; m_no_blocking = (flags0>>3)&1; damage_type = (flags0>>4)&15; powers = *ptr++; // Last 2 unknown. return shapenum; } /* * Read in an armor-info entry from 'armor.dat'. * * Output: Shape # this entry describes. */ int Armor_info::read ( std::istream& in // Read from here. ) { uint8 buf[10]; // Entry length. in.read((char *) buf, sizeof(buf)); uint8 *ptr = buf; int shapenum = Read2(ptr); // Bytes 0-1. prot = *ptr++; // Protection value. ptr++; // Unknown. immune = *ptr++; // Immunity flags. // Last 5 are unknown/unused. return shapenum; } /* * Clean up. */ Shape_info::~Shape_info() { delete weapon; delete ammo; delete armor; if(weapon_offsets) delete [] weapon_offsets; delete monstinf; } /* * Create/delete 'info' for weapons, ammo, etc. * * Output: Possibly updated ->info . */ Weapon_info *Shape_info::set_weapon_info(bool tf) { if (!tf) { delete weapon; weapon = 0; } else { if (!weapon) weapon = new Weapon_info(); } return weapon; } Ammo_info *Shape_info::set_ammo_info(bool tf) { if (!tf) { delete ammo; ammo = 0; } else { if (!ammo) ammo = new Ammo_info(); } return ammo; } Armor_info *Shape_info::set_armor_info(bool tf) { if (!tf) { delete armor; armor = 0; } else { if (!armor) armor = new Armor_info(); } return armor; } Monster_info *Shape_info::set_monster_info(bool tf) { if (!tf) { delete monstinf; monstinf = 0; } else { if (!monstinf) monstinf = new Monster_info(); } return monstinf; } /* * Set 3D dimensions. */ void Shape_info::set_3d ( int xt, int yt, int zt // In tiles. ) { xt = (xt - 1) & 7; // Force legal values. yt = (yt - 1) & 7; zt &= 7; tfa[2] = (tfa[2]&~63)|xt|(yt<<3); tfa[0] = (tfa[0]&~(7<<5))|(zt<<5); dims[0] = xt + 1; dims[1] = yt + 1; dims[2] = zt; } /* * Set weapon offsets for given frame. */ void Shape_info::set_weapon_offset ( int frame, // 0-31. unsigned char x, unsigned char y// 255 means "dont' draw". ) { if (frame < 0 || frame > 31) return; if (x == 255 && y == 255) { if (weapon_offsets) // +++Could delete if all 255's now. weapon_offsets[frame*2] = weapon_offsets[frame*2 + 1] = 255; return; } if (!weapon_offsets) { weapon_offsets = new unsigned char[64]; std::memset(weapon_offsets, 255, sizeof(weapon_offsets)); } weapon_offsets[frame*2] = x; weapon_offsets[frame*2 + 1] = y; } exult-1.2/shapes/bodies.h0000644000175000001440000000233307724430453011104 /* * bodies.h - Associate bodies with 'live' shapes. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BODIES_H #define BODIES_H 1 /* * A class to get the dead-body shape/frame for a given 'live' shape. */ class Body_lookup { static short bg_table[]; // Tables of values. static short si_table[]; public: static int find(int liveshape, int& deadshape, int& deadframe); }; /* * Recognize dead body shapes. +++++++Hopefully, there's a better way. */ int Is_body ( int shapeid ); #endif exult-1.2/shapes/shapevga.cc0000644000175000001440000001517110026506347011572 /* * shapevga.cc - Handle the 'shapes.vga' file and associated info. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include /* For debugging only. */ #include "shapevga.h" #include "monstinf.h" #include "utils.h" #include "exceptions.h" using std::ifstream; using std::ios; // For convienience #define patch_exists(p) (have_patch_path && U7exists(p)) #define patch_name(p) (patch_exists(p) ? (p) : 0) /* * Open, but don't quit if editing. We first try the patch name if it's * given. */ static bool U7open2 ( ifstream& in, // Stream to open. const char *pname, // Patch name, or null. const char *fname, // File name. bool editing ) { if (pname) { U7open(in, pname); return true; } try { U7open(in, fname); } catch(const file_exception & f) { if (editing) return false; throw f; } return true; } /* * Read in data files about shapes. * * Output: 0 if error. */ void Shapes_vga_file::read_info ( bool bg, // True if BlackGate. bool editing // True to allow files to not exist. ) { if (info_read) return; info_read = true; int i, cnt; bool have_patch_path = is_system_path_defined(""); // ShapeDims // Starts at 0x96'th shape. ifstream shpdims; if (U7open2(shpdims, patch_name(PATCH_SHPDIMS), SHPDIMS, editing)) for (i = 0x96; i < num_shapes && !shpdims.eof(); i++) { shpdims.get((char&) info[i].shpdims[0]); shpdims.get((char&) info[i].shpdims[1]); } // WGTVOL ifstream wgtvol; if (U7open2(wgtvol, patch_name(PATCH_WGTVOL), WGTVOL, editing)) for (i = 0; i < num_shapes && !wgtvol.eof(); i++) { wgtvol.get((char&) info[i].weight); wgtvol.get((char&) info[i].volume); } // TFA ifstream tfa; if (U7open2(tfa, patch_name(PATCH_TFA), TFA, editing)) for (i = 0; i < num_shapes && !tfa.eof(); i++) { tfa.read((char*)&info[i].tfa[0], 3); info[i].set_tfa_data(); } ifstream ready; if (U7open2(ready, patch_name(PATCH_READY), READY, editing)) { cnt = Read1(ready); // Get # entries. for (i = 0; i < cnt; i++) { unsigned short shapenum = Read2(ready); unsigned char type = Read1(ready); info[shapenum].ready_type = type; ready.seekg(6, ios::cur);// Skip 9 bytes. } ready.close(); } ifstream armor; if (U7open2(armor, patch_name(PATCH_ARMOR), ARMOR, editing)) { cnt = Read1(armor); for (i = 0; i < cnt; i++) { Armor_info *ainf = new Armor_info(); unsigned short shapenum = ainf->read(armor); info[shapenum].armor = ainf; } armor.close(); } ifstream weapon; if (U7open2(weapon, patch_name(PATCH_WEAPONS), WEAPONS, editing)) { cnt = Read1(weapon); for (i = 0; i < cnt; i++) { Weapon_info *winf = new Weapon_info(); unsigned short shapenum = winf->read(weapon, bg); info[shapenum].weapon = winf; } weapon.close(); } ifstream ammo; if (U7open2(ammo, patch_name(PATCH_AMMO), AMMO, editing)) { cnt = Read1(ammo); for (i = 0; i < cnt; i++) { Ammo_info *ainf = new Ammo_info(); unsigned short shapenum = ainf->read(ammo); info[shapenum].ammo = ainf; } ammo.close(); } // Load data about drawing the weapon in an actor's hand ifstream wihh; unsigned short offsets[1024]; if (U7open2(wihh, patch_name(PATCH_WIHH), WIHH, editing)) cnt = num_shapes <= 1024 ? num_shapes : 1024; else cnt = 0; for (i = 0; i < cnt; i++) offsets[i] = Read2(wihh); for (i = 0; i < cnt; i++) // A zero offset means there is no record if(offsets[i] == 0) info[i].weapon_offsets = 0; else { wihh.seekg(offsets[i]); // There are two bytes per frame: 64 total info[i].weapon_offsets = new unsigned char[64]; for(int j = 0; j < 32; j++) { unsigned char x = Read1(wihh); unsigned char y = Read1(wihh); // Set x/y to 255 if weapon is not to be drawn // In the file x/y are either 64 or 255: // I am assuming that they mean the same if(x > 63 || y > 63) x = y = 255; info[i].weapon_offsets[j * 2] = x; info[i].weapon_offsets[j * 2 + 1] = y; } } if (cnt) wihh.close(); ifstream mfile; // Now get monster info. if (U7open2(mfile, patch_name(PATCH_MONSTERS), MONSTERS, editing)) { int num_monsters = Read1(mfile); for (i = 0; i < num_monsters; i++) { Monster_info *minf = new Monster_info(); int shnum = minf->read(mfile); info[shnum].monstinf = minf; } mfile.close(); } // Get 'equip.dat'. if (U7open2(mfile, patch_name(PATCH_EQUIP), EQUIP, editing)) { int num_recs = Read1(mfile); Equip_record *equip = new Equip_record[num_recs]; for (i = 0; i < num_recs; i++) { Equip_record& rec = equip[i]; // 10 elements/record. for (int elem = 0; elem < 10; elem++) { int shnum = Read2(mfile); unsigned prob = Read1(mfile); unsigned quant = Read1(mfile); Read2(mfile); rec.set(elem, shnum, prob, quant); } } // Monster_info owns this. Monster_info::set_equip(equip, num_recs); mfile.close(); } ifstream(occ); // Read flags from occlude.dat. if (U7open2(occ, patch_name(PATCH_OCCLUDE), OCCLUDE, editing)) { unsigned char occbits[128]; // 1024 bit flags. occ.read((char *)occbits, sizeof(occbits)); for (i = 0; i < sizeof(occbits); i++) { unsigned char bits = occbits[i]; int shnum = i*8; // Check each bit. for (int b = 0; bits; b++, bits = bits>>1) if (bits&1) { info[shnum + b].occludes_flag = true; } } } } /* * Open/close file. */ Shapes_vga_file::Shapes_vga_file ( const char *nm, // Path to file. int u7drag, // # from u7drag.h, or -1. const char *nm2 // Path to patch version, or 0. ) : Vga_file(nm, u7drag, nm2), info_read(false) { info.set_size(num_shapes); } Shapes_vga_file::~Shapes_vga_file() { } void Shapes_vga_file::init() { if (is_system_path_defined("") && U7exists(PATCH_SHAPES)) load(SHAPES_VGA, PATCH_SHAPES); else load(SHAPES_VGA); info.set_size(num_shapes); } exult-1.2/shapes/pngio.h0000644000175000001440000000266407456734423010770 /** ** Import/export .PNG files. ** ** Written: 6/9/99 - JSF **/ /* Copyright (C) 2002 The Exult Team Copyright (C) 1999 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_PNGIO #define INCL_PNGIO #ifdef HAVE_PNG_H int Import_png8(const char *pngname, int transp_index, int& width, int& height, int& rowbytes, int& xoff, int& yoff, unsigned char *& pixels, unsigned char *& palette, int& pal_size); int Export_png8(const char *pngname, int transp_index, int width, int height, int rowbytes, int xoff, int yoff, unsigned char * pixels, unsigned char * palette, int pal_size, bool transp_to_0 = false); int Import_png32(const char *pngname, int& width, int& height, int& rowbytes, int& xoff, int& yoff, unsigned char *& pixels, bool bottom_first = false); #endif #endif exult-1.2/shapes/vgafile.cc0000644000175000001440000007077210054030577011417 /* * vgafile.cc - Handle access to one of the xxx.vga files. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "utils.h" #include "rect.h" #include "ibuf8.h" #include "vgafile.h" #include "databuf.h" #include "Flex.h" #include "exceptions.h" #include #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::ifstream; using std::ios; using std::memcpy; using std::memset; using std::ostream; #endif GL_manager *Shape_frame::glman = 0; Image_buffer8 *Shape_frame::scrwin = 0; #if 1 /* For debugging. */ #include #include "items.h" #endif /* * +++++Debugging */ inline void Check_file ( ifstream& shapes ) { if (!shapes.good()) { cout << "VGA file is bad!" << endl; shapes.clear(); } } /* * Create a new frame by reflecting across a line running NW to SE. * * May return 0. */ Shape_frame *Shape_frame::reflect ( ) { if (!data) return 0; int w = get_width(), h = get_height(); if (w < h) w = h; else h = w; // Use max. dim. Shape_frame *reflected = new Shape_frame(); reflected->rle = true; // Set data. reflected->xleft = yabove; reflected->yabove = xleft; reflected->xright = ybelow; reflected->ybelow = xright; // Create drawing area. Image_buffer8 *ibuf = new Image_buffer8(h, w); ibuf->fill8(255); // Fill with 'transparent' pixel. // Figure origin. int xoff = reflected->xleft, yoff = reflected->yabove; uint8 *in = data; // Point to data, and draw. int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); short scany = Read2(in); if (!encoded) // Raw data? { ibuf->copy8(in, 1, scanlen, xoff + scany, yoff + scanx); in += scanlen; continue; } for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. if (repeat) { unsigned char pix = *in++; ibuf->fill8(pix, 1, bcnt, xoff + scany, yoff + scanx + b); } else // Get that # of bytes. { ibuf->copy8(in, 1, bcnt, xoff + scany, yoff + scanx + b); in += bcnt; } b += bcnt; } } reflected->create_rle(ibuf->get_bits(), w, h); delete ibuf; // Done with this. return (reflected); } /* * Skip transparent pixels. * * Output: Index of first non-transparent pixel (w if no more). * Pixels is incremented by (delta x). */ static int Skip_transparent ( unsigned char *& pixels, // 8-bit pixel scan line. int x, // X-coord. of pixel to start with. int w // Remaining width of pixels. ) { while (x < w && *pixels == 255) { x++; pixels++; } return (x); } /* * Split a line of pixels into runs, where a run * consists of different pixels, or a repeated pixel. * * Output: Index of end of scan line. */ static int Find_runs ( short *runs, // Each run's length is returned. // For each byte, bit0==repeat. // List ends with a 0. unsigned char *pixels, // Scan line (8-bit color). int x, // X-coord. of pixel to start with. int w // Remaining width of pixels. ) { int runcnt = 0; // Counts runs. while (x < w && *pixels != 255) // Stop at first transparent pixel. { int run = 0; // Look for repeat. while (x < w - 1 && pixels[0] == pixels[1]) { x++; pixels++; run++; } if (run) // Repeated? Count 1st, shift, flag. { run = ((run + 1)<<1)|1; x++; // Also pass the last one. pixels++; } else do // Pass non-repeated run of { // andy length. x++; pixels++; run += 2; // So we don't have to shift. } while (x < w && *pixels != 255 && (x == w - 1 || pixels[0] != pixels[1])); // Store run length. runs[runcnt++] = run; } runs[runcnt] = 0; // 0-delimit list. return (x); } /* * Encode an 8-bit image into an RLE frame. * * Output: Data is set to compressed image. */ void Shape_frame::create_rle ( unsigned char *pixels, // 8-bit uncompressed data. int w, int h // Width, height. ) { delete [] data; // Delete old data if there. data = encode_rle(pixels, w, h, xleft, yabove, datalen); } /* * Encode an 8-bit image into an RLE frame. * * Output: ->allocated RLE data. */ unsigned char *Shape_frame::encode_rle ( unsigned char *pixels, // 8-bit uncompressed data. int w, int h, // Width, height. int xoff, int yoff, // Origin (xleft, yabove). int& datalen // Length of RLE data returned. ) { // Create an oversized buffer. uint8 *buf = new uint8[w*h*2 + 16*h]; uint8 *out = buf; int newx; // Gets new x at end of a scan line. for (int y = 0; y < h; y++) // Go through rows. for (int x = 0; (x = Skip_transparent(pixels, x, w)) < w; x = newx) { short runs[100];// Get runs. newx = Find_runs(runs, pixels, x, w); // Just 1 non-repeated run? if (!runs[1] && !(runs[0]&1)) { int len = runs[0] >> 1; Write2(out, runs[0]); // Write position. Write2(out, x - xoff); Write2(out, y - yoff); memcpy(out, pixels, len); pixels += len; out += len; continue; } // Encoded, so write it with bit0==1. Write2(out, ((newx - x)<<1)|1); // Write position. Write2(out, x - xoff); Write2(out, y - yoff); // Go through runs. for (int i = 0; runs[i]; i++) { int len = runs[i]>>1; // Check for repeated run. if (runs[i]&1) { while (len) { int c = len > 127 ? 127 : len; *out++ = (c<<1)|1; *out++ = *pixels; pixels += c; len -= c; } } else while (len > 0) { int c = len > 127 ? 127 : len; *out++ = c<<1; memcpy(out, pixels, c); out += c; pixels += c; len -= c; } } } Write2(out, 0); // End with 0 length. datalen = out - buf; // Create buffer of correct size. #ifdef DEBUG if(datalen > w*h*2 + 16*h) cout << "create_rle: datalen: " << datalen << " w: " << w << " h: " << h << endl; #endif unsigned char *data = new unsigned char[datalen]; memcpy(data, buf, datalen); delete [] buf; return data; } /* * Create from data. */ Shape_frame::Shape_frame ( unsigned char *pixels, // (A copy is made.) int w, int h, // Dimensions. int xoff, int yoff, // Xleft, yabove. bool setrle // Run-length-encode. ) : xleft(xoff), yabove(yoff), xright(w - xoff - 1), ybelow(h - yoff - 1), rle(setrle) #ifdef HAVE_OPENGL , glshape(0) #endif { if (!rle) { assert(w == 8 && h == 8); datalen = 64; data = new unsigned char[64]; memcpy(data, pixels, 64); } else data = encode_rle(pixels, w, h, xleft, yabove, datalen); } /* * Read in a desired shape. * * Output: # of frames. */ unsigned char Shape_frame::read ( DataSource* shapes, // Shapes data source to read. uint32 shapeoff, // Offset of shape in file. uint32 shapelen, // Length expected for detecting RLE. int frnum // Frame #. ) { int framenum = frnum; rle = false; if (!shapelen && !shapeoff) return 0; // Get to actual shape. shapes->seek(shapeoff); uint32 dlen = shapes->read4(); uint32 hdrlen = shapes->read4(); if (dlen == shapelen) { rle = true; // It's run-length-encoded. // Figure # frames. int nframes = (hdrlen - 4)/4; if (framenum >= nframes)// Bug out if bad frame #. return (nframes); // Get frame offset, lengeth. uint32 frameoff, framelen; if (framenum == 0) { frameoff = hdrlen; framelen = nframes > 1 ? shapes->read4() - frameoff : dlen - frameoff; } else { shapes->skip((framenum - 1) * 4); frameoff = shapes->read4(); // Last frame? if (framenum == nframes - 1) framelen = dlen - frameoff; else framelen = shapes->read4() - frameoff; } // Get compressed data. get_rle_shape(shapes, shapeoff + frameoff, framelen); // Return # frames. return (nframes); } framenum &= 31; // !!!Guessing here. xleft = yabove = 8; // Just an 8x8 bitmap. xright= ybelow = -1; shapes->seek(shapeoff + framenum*64); data = new unsigned char[64]; // Read in 8x8 pixels. datalen = 64; shapes->read((char *) data, 64); return (shapelen/64); // That's how many frames. } /* * Read in a Run-Length_Encoded shape. */ void Shape_frame::get_rle_shape ( DataSource* shapes, // Shapes data source to read. long filepos, // Position in file. long len // Length of entire frame data. ) { shapes->seek(filepos); // Get to extents. xright = shapes->read2(); xleft = shapes->read2(); yabove = shapes->read2(); ybelow = shapes->read2(); len -= 8; // Subtract what we just read. data = new unsigned char[len + 2]; // Allocate and read data. datalen = len+2; shapes->read((char*)data, len); data[len] = 0; // 0-delimit. data[len + 1] = 0; rle = true; } /* * Show a Run-Length_Encoded shape. */ void Shape_frame::paint_rle ( Image_buffer8 *win, // Buffer to paint in. int xoff, int yoff // Where to show in iwin. ) { assert(rle); int w = get_width(), h = get_height(); if (w >= 8 || h >= 8) // Big enough to check? Off screen? if (!win->is_visible(xoff - xleft, yoff - yabove, w, h)) return; win->paint_rle (xoff, yoff, data); return; } /* * Paint either type of shape. */ void Shape_frame::paint ( Image_buffer8 *win, // Buffer to paint in. int xoff, int yoff // Where to show in iwin. ) { if (rle) paint_rle(win, xoff, yoff); else win->copy8(data, 8, 8, xoff - 8, yoff - 8); } /* * Show a Run-Length_Encoded shape with translucency. */ void Shape_frame::paint_rle_translucent ( Image_buffer8 *win, // Buffer to paint in. int xoff, int yoff, // Where to show in iwin. Xform_palette *xforms, // Transforms translucent colors int xfcnt // Number of xforms. ) { assert(rle); int w = get_width(), h = get_height(); if (w >= 8 || h >= 8) // Big enough to check? Off screen? if (!win->is_visible(xoff - xleft, yoff - yabove, w, h)) return; // First pix. value to transform. const int xfstart = 0xff - xfcnt; uint8 *in = data; int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); short scany = Read2(in); if (!encoded) // Raw data? { win->copy_line_translucent8(in, scanlen, xoff + scanx, yoff + scany, xfstart, 0xfe, xforms); in += scanlen; continue; } for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. if (repeat) { unsigned char pix = *in++; if (pix >= xfstart && pix <= 0xfe) win->fill_line_translucent8(pix, bcnt, xoff + scanx + b, yoff + scany, xforms[pix - xfstart]); else win->fill_line8(pix, bcnt, xoff + scanx + b, yoff + scany); } else // Get that # of bytes. { win->copy_line_translucent8(in, bcnt, xoff + scanx + b, yoff + scany, xfstart, 0xfe, xforms); in += bcnt; } b += bcnt; } } } /* * Paint a shape purely by translating the pixels it occupies. This is * used for invisible NPC's. */ void Shape_frame::paint_rle_transformed ( Image_buffer8 *win, // Buffer to paint in. int xoff, int yoff, // Where to show in iwin. Xform_palette& xform // Use to transform pixels. ) { assert(rle); int w = get_width(), h = get_height(); if (w >= 8 || h >= 8) // Big enough to check? Off screen? if (!win->is_visible(xoff - xleft, yoff - yabove, w, h)) return; uint8 * in = data; int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); short scany = Read2(in); if (!encoded) // Raw data? { // (Note: 1st parm is ignored). win->fill_line_translucent8(0, scanlen, xoff + scanx, yoff + scany, xform); in += scanlen; continue; } for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. in += repeat ? 1 : bcnt; win->fill_line_translucent8(0, bcnt, xoff + scanx + b, yoff + scany, xform); b += bcnt; } } } /* * Paint outline around a shape. */ void Shape_frame::paint_rle_outline ( Image_buffer8 *win, // Buffer to paint in. int xoff, int yoff, // Where to show in win. unsigned char color // Color to use. ) { assert(rle); int w = get_width(), h = get_height(); if (w >= 8 || h >= 8) // Big enough to check? Off screen? if (!win->is_visible(xoff - xleft, yoff - yabove, w, h)) return; int firsty = -10000; // Finds first line. int lasty; uint8 * in = data; int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); short scany = Read2(in); int x = xoff + scanx; int y = yoff + scany; if (firsty == -10000) { firsty = y; lasty = y + h - 1; } // Put pixel at both ends. win->put_pixel8(color, x, y); win->put_pixel8(color, x + scanlen - 1, y); if (!encoded) // Raw data? { if (y == firsty || // First line? y == lasty) // Last line? win->fill_line8(color, scanlen, x, y); in += scanlen; continue; } for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. if (repeat) // Pass repetition byte. in++; else // Skip that # of bytes. in += bcnt; if (y == firsty || // First line? y == lasty) // Last line? win->fill_line8(color, bcnt, x + b, y); b += bcnt; } } } /* * See if a point, relative to the shape's 'origin', actually within the * shape. */ int Shape_frame::has_point ( int x, int y // Relative to origin of shape. ) { if (!rle) // 8x8 flat? { return x >= -xleft && x < xright && y >= -yabove && y < ybelow; } uint8 *in = data; // Point to data. int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); short scany = Read2(in); // Be liberal by 1 pixel. if (y == scany && x >= scanx - 1 && x <= scanx + scanlen) return (1); if (!encoded) // Raw data? { in += scanlen; continue; } for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. if (repeat) in++; // Skip pixel to repeat. else // Skip that # of bytes. in += bcnt; b += bcnt; } } return (0); // Never found it. } /* * Set new offset, assuming dimensions are unchanged. */ void Shape_frame::set_offset ( int new_xright, int new_ybelow ) { if (!rle) return; // Can do it for 8x8 tiles. int w = get_width(), h = get_height(); if (new_xright > w) // Limit to left edge. new_xright = w; if (new_ybelow > h) new_ybelow = h; int deltax = new_xright - xright; // Get changes. int deltay = new_ybelow - ybelow; xright = new_xright; ybelow = new_ybelow; xleft = w - xright - 1; // Update other dims. yabove = h - ybelow - 1; uint8 *in = data; // Got to update all scan lines! int scanlen; while ((scanlen = Read2(in)) != 0) { // Get length of scan line. int encoded = scanlen&1;// Is it encoded? scanlen = scanlen>>1; short scanx = Read2(in); in -= 2; Write2(in, scanx + deltax); short scany = Read2(in); in -= 2; Write2(in, scany + deltay); // Just need to scan past EOL. if (!encoded) // Raw data? in += scanlen; else for (int b = 0; b < scanlen; ) { unsigned char bcnt = *in++; // Repeat next char. if odd. int repeat = bcnt&1; bcnt = bcnt>>1; // Get count. if (repeat) in++; // Skip pixel to repeat. else // Skip that # of bytes. in += bcnt; b += bcnt; } } } /* * Create the reflection of a shape. */ Shape_frame *Shape::reflect ( DataSource* shapes, // shapes data source to read. int shapenum, // Shape #. int framenum // Frame # without the 'reflect' bit. ) { // Get normal frame. Shape_frame *normal = get(shapes, shapenum, framenum); if (!normal) return (0); // Reflect it. Shape_frame *reflected = normal->reflect(); if (!reflected) return (0); framenum |= 32; // Put back 'reflect' flag. if (framenum >= frames_size - 1)// Expand list if necessary. enlarge(framenum + 1); frames[framenum] = reflected; // Store new frame. return reflected; } /* * Resize list upwards. */ void Shape::enlarge ( int newsize ) { Shape_frame **newframes = new Shape_frame *[newsize]; int i; for (i = 0; i < frames_size; i++) newframes[i] = frames[i]; frames_size = newsize; for ( ; i < frames_size; i++) newframes[i] = 0; delete [] frames; frames = newframes; } /* * Resize list. This is for outside clients, and it sets num_frames. */ void Shape::resize ( int newsize ) { if (newsize == frames_size) return; if (newsize > frames_size) enlarge(newsize); // Growing. else { // Shrinking. Shape_frame **newframes = new Shape_frame *[newsize]; int i; for (i = 0; i < newsize; i++) newframes[i] = frames[i]; // Delete past new end. for ( ; i < frames_size; i++) delete frames[i]; frames_size = newsize; delete [] frames; frames = newframes; } num_frames = newsize; } /* * Call this to set num_frames, frames_size and create 'frames' list. */ inline void Shape::create_frames_list ( int nframes ) { num_frames = frames_size = nframes; frames = new Shape_frame *[frames_size]; memset((char *) frames, 0, frames_size * sizeof(Shape_frame *)); } /* * Read in a frame, or convert an existing one if reflection is * desired. * * Output: ->frame, or 0 if failed. */ Shape_frame *Shape::read ( DataSource *shapes1, // Shapes data source to read. int shapenum, // Shape #. int framenum, // Frame # within shape. DataSource *shapes2, // Shapes data source to read (alternative). int count1, // Number of shapes in shapes int count2 // Number of shapes in shapes2 ) { DataSource *shapes = 0; Shape_frame *frame = new Shape_frame(); // Figure offset in "shapes.vga". uint32 shapeoff = 0x80 + shapenum*8; uint32 shapelen = 0; // If shapes2 exists and shapenum is valid for shapes2 if (shapes2 && (count2 == -1 || shapenum < count2)) { shapes2->seek(shapeoff); // Get location, length. int s = shapes2->read4(); shapelen = shapes2->read4(); if (s && shapelen) { shapeoff = s; shapes = shapes2; } } if (shapes == 0) { shapes = shapes1; if (count1 != -1 && shapenum >= count1) { std::cerr << "Shape num out of range: " << shapenum << std::endl; return 0; } shapes->seek(shapeoff); // Get location, length. shapeoff = shapes->read4(); shapelen = shapes->read4(); } if (!shapelen) return 0; // Empty shape. // Read it in and get frame count. int nframes = frame->read(shapes, shapeoff, shapelen, framenum); if (!num_frames) // 1st time? create_frames_list(nframes); if (!frame->rle) framenum &= 31; // !!Guessing. if (framenum >= nframes && // Compare against #frames in file. (framenum&32)) // Reflection desired? { delete frame; return (reflect(shapes, shapenum, framenum&0x1f)); } return store_frame(frame, framenum); } /* * Write a shape's frames as an entry in an Exult .vga file. Note that * a .vga file is a .FLX file with one shape/entry. * * NOTE: This should only be called if all frames have been read. */ void Shape::write ( ostream& out // What to write to. ) { int frnum; if (!num_frames) return; // Empty. assert(frames != 0 && *frames != 0); bool flat = !frames[0]->is_rle(); // Save starting position. unsigned long startpos = out.tellp(); if (!flat) { Write4(out, 0); // Place-holder for total length. // Also for frame locations. for (frnum = 0; frnum < num_frames; frnum++) Write4(out, 0); } for (frnum = 0; frnum < num_frames; frnum++) { Shape_frame *frame = frames[frnum]; assert(frame != 0); // Better all be the same type. assert(flat == !frame->is_rle()); if (frame->is_rle()) { // Get position of frame. unsigned long pos = out.tellp(); out.seekp(startpos + (frnum + 1)*4); Write4(out, pos - startpos); // Store pos. out.seekp(pos); // Get back. Write2(out, frame->xright); Write2(out, frame->xleft); Write2(out, frame->yabove); Write2(out, frame->ybelow); } out.write(reinterpret_cast(frame->data), frame->datalen); // The frame data. } if (!flat) { unsigned long pos = out.tellp();// Ending position. out.seekp(startpos); // Store total length. Write4(out, pos - startpos); out.seekp(pos); // And get back to end. } } /* * Store frame that was read. * * Output: ->frame, or 0 if not valid. */ Shape_frame *Shape::store_frame ( Shape_frame *frame, // Frame that was read. int framenum // It's frame #. ) { if (framenum >= frames_size) // Something fishy? { delete frame; cerr << "Shape::store_frame: framenum >= frames_size" << endl; return (0); } if (!frames) // First one? { frames = new Shape_frame *[num_frames]; memset((char *) frames, 0, num_frames * sizeof(Shape_frame *)); } frames[framenum] = frame; return (frame); } /* * Create with a single frame. */ Shape::Shape(Shape_frame* fr) { num_frames = frames_size = 1; frames = new Shape_frame*[1]; frames[0] = fr; } /* * Create with space for a given number of frames. */ Shape::Shape ( int n // # frames. ) { create_frames_list(n); } void Shape::reset() { if (frames) { for(int i = 0; i < frames_size; i++) delete frames[i]; delete [] frames; frames = 0; } else if (frames_size) cerr << "Shape::~Shape(): 'frames' is null, while frames_size=" << (int) frames_size << endl; } /* * Take frames from another shape and set that shape to empty. */ void Shape::take ( Shape *sh2 ) { reset(); // Clear ourself. frames = sh2->frames; sh2->frames = 0; frames_size = sh2->frames_size; num_frames = sh2->num_frames; sh2->num_frames = sh2->frames_size = 0; } /* * Load all frames for a single shape. (Assumes RLE-type shape.) */ void Shape::load ( DataSource* shape_source // datasource. ) { reset(); Shape_frame *frame = new Shape_frame(); uint32 shapelen = shape_source->read4(); // Read frame 0 & get frame count. create_frames_list(frame->read(shape_source, 0L, shapelen, 0)); store_frame(frame, 0); // Get the rest. for (int i = 1; i < num_frames; i++) { frame = new Shape_frame(); frame->read(shape_source, 0L, shapelen, i); store_frame(frame, i); } } Shape::~Shape() { reset(); } /* * Set desired frame. */ void Shape::set_frame ( Shape_frame *frame, // Must be allocated. int framenum ) { assert (framenum < num_frames); delete frames[framenum]; // Delete existing. frames[framenum] = frame; } /* * Add/insert a frame. */ void Shape::add_frame ( Shape_frame *frame, // Must be allocated. int framenum // Insert here. ) { assert (framenum <= num_frames);// Can append. enlarge(frames_size + 1); // Make room. for (int i = frames_size - 1; i > framenum; i--) frames[i] = frames[i - 1]; frames[framenum] = frame; num_frames++; } /* * Delete a frame. */ void Shape::del_frame ( int framenum ) { assert (framenum < num_frames); delete frames[framenum]; // Shift down. for (int i = framenum + 1; i < frames_size; i++) frames[i - 1] = frames[i]; frames[frames_size - 1] = 0; // Last spot is now free. num_frames--; } /* * Empty constructor */ Shape_file::Shape_file() : Shape() { // Nothing to see here } /* * Read in all shapes from a single-shape file. */ Shape_file::Shape_file ( const char *nm // Path to file. ) : Shape() { load(nm); } /* * Read in all shapes from a single-shape file. */ void Shape_file::load ( const char *nm // Path to file. ) { ifstream file; U7open(file, nm); StreamDataSource shape_source(&file); Shape::load(&shape_source); } /* * Read in all shapes from a single-shape file. */ Shape_file::Shape_file ( DataSource* shape_source // datasource. ) : Shape() { Shape::load(shape_source); } // NOTE: Only works on shapes other than the special 8x8 tile-shapes int Shape_file::get_size() { int size = 4; for (int i=0; iget_size() + 4 + 8; return size; } // NOTE: Only works on shapes other than the special 8x8 tile-shapes void Shape_file::save(DataSource* shape_source) { int* offsets = new int[num_frames]; int size; offsets[0] = 4 + num_frames * 4; int i; // Blame MSVC for (i=1; iget_size() + 8; size = offsets[num_frames-1] + frames[num_frames-1]->get_size() + 8; shape_source->write4(size); for (i=0; iwrite4(offsets[i]); for (i=0; iwrite2(frames[i]->xright); shape_source->write2(frames[i]->xleft); shape_source->write2(frames[i]->yabove); shape_source->write2(frames[i]->ybelow); shape_source->write((char*)(frames[i]->data), frames[i]->get_size()); } delete [] offsets; } /* * Open file. */ Vga_file::Vga_file ( const char *nm, // Path to file. int u7drag, // # from u7drag.h, or -1. const char *nm2 // Patch file, or null. ) : shape_source(0), shape_source2(0), num_shapes(0), num_shapes1(0), num_shapes2(0), shapes(0), u7drag_type(u7drag), flex(true) { load(nm, nm2); } Vga_file::Vga_file ( ) : shape_source(0), shape_source2(0), num_shapes(0), num_shapes1(0), num_shapes2(0), shapes(0), u7drag_type(-1), flex(true) { // Nothing to see here !!! } /* * Open file. */ void Vga_file::load ( const char *nm, // Path to file (required). const char *nm2 // Path to patch file (optional). ) { reset(); if (U7exists(nm)) { U7open(file, nm); shape_source = new StreamDataSource(&file); StreamDataSource ds(&file); flex = Flex::is_flex(&ds); } if (nm2 && U7exists(nm2)) { U7open(file2, nm2); // throws an error if it fails shape_source2 = new StreamDataSource(&file2); StreamDataSource ds(&file2); flex = Flex::is_flex(&ds); } if (!shape_source && !shape_source2) throw file_open_exception(get_system_path(nm)); if (!flex) // Just one shape, which we preload. { num_shapes = num_shapes1 = num_shapes2 = 1; shapes = new Shape[1]; shapes[0].load(shape_source2 ? shape_source2 : shape_source); return; } if (shape_source) { shape_source->seek(0x54); // Get # of shapes. num_shapes = num_shapes1 = shape_source->read4(); } if (shape_source2) { shape_source2->seek(0x54); // Get # of shapes. num_shapes2 = shape_source2->read4(); if (num_shapes2 > num_shapes) num_shapes = num_shapes2; } // Set up lists of pointers. shapes = new Shape[num_shapes]; } void Vga_file::reset() { if( shapes ) delete [] shapes; if( shape_source ) delete shape_source; file.close(); if( shape_source2 ) delete shape_source2; if (file2.is_open()) file2.close(); num_shapes = 0; num_shapes1 = 0; num_shapes2 = 0; shape_source = 0; shape_source2 = 0; shapes = 0; } Vga_file::~Vga_file() { reset(); } /* * Make a spot for a new shape, and delete frames in existing shape. * * Output: ->shape, or 0 if invalid shapenum. */ Shape *Vga_file::new_shape ( int shapenum ) { if (shapenum < 0 || shapenum >= 2048) // (2048 is really arbitrary.) return 0; if (shapenum < num_shapes) { shapes[shapenum].reset(); shapes[shapenum].num_frames = shapes[shapenum].frames_size = 0; } else // Enlarge list. { if (!flex) return 0; // 1-shape file. Shape *newshapes = new Shape[shapenum + 1]; for (int i = 0; i < num_shapes; i++) newshapes[i].take(&shapes[i]); delete [] shapes; shapes = newshapes; num_shapes = shapenum + 1; } return &shapes[shapenum]; } exult-1.2/shapes/monstinf.h0000644000175000001440000001235607520504107011472 /** ** Monstinf.h - Information (about NPC's, really) from 'monster.dat'. ** ** Written: 8/13/01 - JSF **/ #ifndef INCL_MONSTINF #define INCL_MONSTINF 1 /* Copyright (C) 2000-2001 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ALPHA_LINUX_CXX # include #endif #include /* * An element from 'equip.dat', describing a monster's equipment: */ class Equip_element { unsigned short shapenum; // What to create, or 0 for nothing. unsigned char probability; // 0-100: probabilit of creation. unsigned char quantity; // # to create. public: friend class Monster_info; friend class Monster_actor; Equip_element() { } void set(int shnum, int prob, int quant) { shapenum = shnum; probability = prob; quantity = quant; } int get_shapenum() const { return shapenum; } int get_probability() const { return probability; } int get_quantity() const { return quantity; } }; /* * A record from 'equip.dat' consists of 10 elements. */ class Equip_record { Equip_element elements[10]; public: friend class Monster_info; friend class Monster_actor; Equip_record() { } // Set i'th element. void set(int i, int shnum, int prob, int quant) { elements[i].set(shnum, prob, quant); } Equip_element& get(int i) { assert(i >= 0 && i < 10); return elements[i]; } }; /* * Monster info. from 'monsters.dat': */ class Monster_info { static Equip_record *equip; // ->equipment info. static int equip_cnt; // # entries in equip. static Monster_info default_info; // For shapes not found. unsigned char strength; // Attributes. unsigned char dexterity; unsigned char intelligence; unsigned char alignment; // Default alignment. unsigned char combat; unsigned char armor; // These are unarmed stats. unsigned char weapon; unsigned char reach; unsigned char flags; // Defined below. // The following are bits corresponding // to Weapon_info::Damage_type. unsigned char vulnerable, immune; unsigned char equip_offset; // Offset in 'equip.dat' (1 based; // if 0, there's none.) bool m_splits; // For slimes. bool m_cant_die; bool m_cant_yell; // Can't yell during combat. bool m_cant_bleed; bool m_poison_safe; // Can't be poisoned. public: friend class Monster_actor; Monster_info() { } int read(std::istream& mfile); // Read in from file. // Write out. void write(int shapenum, std::ostream& mfile); static const Monster_info *get_default(); // Done by Game_window: static void set_equip(Equip_record *eq, int cnt) { equip = eq; equip_cnt = cnt; } static int get_equip_cnt() { return equip_cnt; } static Equip_record& get_equip(int i) { assert(i >= 0 && i < equip_cnt); return equip[i]; } bool splits() const { return m_splits; } void set_splits(bool tf) { m_splits = tf; } bool cant_die() const { return m_cant_die; } void set_cant_die(bool tf) { m_cant_die = tf; } bool cant_yell() const { return m_cant_yell; } void set_cant_yell(bool tf) { m_cant_yell = tf; } bool cant_bleed() const { return m_cant_bleed; } void set_cant_bleed(bool tf) { m_cant_bleed = tf; } bool poison_safe() const { return m_poison_safe; } void set_poison_safe(bool tf) { m_poison_safe = tf; } // Get bits indicating // Weapon_info::damage_type: unsigned char get_vulnerable() const { return vulnerable; } void set_vulnerable(unsigned char v) { vulnerable = v; } unsigned char get_immune() const { return immune; } void set_immune(unsigned char v) { immune = v; } enum Flags { fly = 0, swim = 1, walk = 2, ethereal = 3, // Can walk through walls. no_body = 4 // Don't create body. // 5: gazer, hook only. //Don't think so magic_only = 7, // Can only be hurt by magic weapons. // 8: bat only. // slow = 9 // E.g., slime, corpser. // 10: skeleton only. }; unsigned char get_flags() const // Get above set of flags. { return flags; } void set_flags(unsigned char f) { flags = f; } bool has_no_body() const // No dead body? { return (flags>>no_body)&1; } int get_strength() const { return strength; } int get_dexterity() const { return dexterity; } int get_intelligence() const { return intelligence; } int get_alignment() const { return alignment; } void set_alignment(int a) { alignment = a; } int get_combat() const { return combat; } int get_armor() const { return armor; } int get_weapon() const { return weapon; } int get_reach() const { return reach; } void set_stats(int str, int dex, int intel, int cmb, int armour, int wpn, int rch); int get_equip_offset() const { return equip_offset; } void set_equip_offset(int o) { equip_offset = o; } }; #endif exult-1.2/shapes/items.h0000644000175000001440000000572707752371316010775 /** ** Items.h - Names of items. ** ** Written: 12/3/98 - JSF **/ /* Copyright (C) 1998 Jeffrey S. Freedman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_ITEMS #define INCL_ITEMS 1 #ifndef ALPHA_LINUX_CXX # include #endif extern char **item_names; // The game items' names. extern int num_item_names; void Setup_item_names (std::ifstream& items, std::ifstream& msgs); /* * Some offsets in text.flx and exultmsg.txt: */ const int first_move_aside = 0x400; // For guards when blocked. const int last_move_aside = 0x402; const int first_preach = 0x403, last_preach = 0x407; const int first_preach2 = 0x408, last_preach2 = 0x40b; const int first_amen = 0x40c, last_amen = 0x40f; const int first_waiter_ask = 0x41b, last_waiter_ask = 0x41f; const int first_more_food = 0x420, last_more_food = 0x424; const int first_munch = 0x425, last_munch = 0x428; const int first_ouch = 0x429; const int last_ouch = 0x42c; const int first_need_help = 0x430; const int last_need_help = 0x433; const int first_will_help = 0x434; const int last_will_help = 0x436; const int first_to_battle = 0x439; const int last_to_battle = 0x43b; const int first_farmer = 0x43f, last_farmer = 0x441; const int first_miner = 0x442, last_miner = 0x444; const int first_flee = 0x448; const int last_flee = 0x44e; const int first_lamp_on = 0x463; const int last_lamp_on = 0x466; const int lamp_off = 0x467; const int first_call_police = 0x469; const int last_call_police = 0x46d; const int first_call_guards = 0x46c; const int last_call_guards = 0x46d; const int first_theft = 0x46e; // Warnings. const int last_theft = 0x470; const int first_close_shutters = 0x471; const int last_close_shutters = 0x473; const int first_open_shutters = 0x474; const int last_open_shutters = 0x476; const int first_hunger = 0x477; // A little hungry. (3 of each). const int first_needfood = 0x47a; // Must have food. const int first_starving = 0x47b; // Starving. const int heard_something = 0x495; const int first_awakened = 0x495; const int last_awakened = 0x49a; // Messages in exultmsg.txt: const int first_chair_thief = 2800, last_chair_thief = 2804; const int first_waiter_banter = 2805, last_waiter_banter = 2807; const int first_waiter_serve = 2808, last_waiter_serve = 2809; const int first_bed_occupied = 2810, num_bed_occupied = 3; const int first_catchup = 2813, last_catchup = 2815; #endif exult-1.2/shapes/glshape.cc0000644000175000001440000002160407724430453011422 /* * glshape.cc - Paint 2D shapes in OpenGL * * Written: 7/16/02 - JSF * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_OPENGL #include #include "glshape.h" #include "vgafile.h" #include "utils.h" #include "exult_constants.h" #include "ibuf8.h" GL_manager *GL_manager::instance = 0; const unsigned char transp = 255; // Transparent pixel. /* * Create from a given source. Assumes src is square, with texsize * already set to length. */ void GL_texshape::create ( Image_buffer8 *src, // Source image. unsigned char *pal, // 3*256 bytes (rgb). Xform_palette *xforms, // Transforms translucent colors if !0. int xfcnt // Number of xforms. ) { assert(pal != 0); const int xfstart = 0xff - xfcnt; // Convert to rgba. unsigned char *pixels = xforms ? src->rgba(pal, transp, xfstart, 0xfe, xforms) : src->rgba(pal, transp); GLuint tex; glGenTextures(1, &tex); // Generate (empty) texture. texture = tex; glBindTexture(GL_TEXTURE_2D, texture); // +++++Might want GL_RGBA, depending // on video card. // Need translucency? GLint iformat = xforms ? GL_RGBA4 : GL_RGB5_A1; // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texsize, texsize, 0, GL_RGBA, glTexImage2D(GL_TEXTURE_2D, 0, iformat, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); delete pixels; // Linear filtering. #if 0 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); #else /* This looks less blurry, and helps get rid of the lines. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); #endif // Enable texture clamping. This will get rid of all the lines everywhere // -Colourless glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP); } /* * Create for a given frame. */ GL_texshape::GL_texshape ( Shape_frame *f, unsigned char *pal, // 3*256 bytes (rgb). Xform_palette *xforms, // Transforms translucent colors if !0. int xfcnt // Number of xforms. ) : frame(f), lru_next(0), lru_prev(0) { int w = frame->get_width(), h = frame->get_height(); // Figure texture size as 2^n, rounding // up. int logw = Log2(2*w - 1), logh = Log2(2*h - 1); texsize = 1<<(logw > logh ? logw : logh); // Render frame. Image_buffer8 buf8(texsize, texsize); buf8.fill8(transp); // Fill with transparent value. // ++++Guessing a bit on the offset: frame->paint(&buf8, texsize - frame->get_xright() - 1, texsize - frame->get_ybelow() - 1); create(&buf8, pal, xforms, xfcnt); } /* * Create from a given (square, size 2^n) image. */ GL_texshape::GL_texshape ( Image_buffer8 *src, // Must be square. unsigned char *pal // 3*256 bytes (rgb). ) : frame(0), lru_next(0), lru_prev(0) { int w = src->get_width(), h = src->get_height(); assert (w == h); assert ((1<glshape = 0; // Tell owner. } /* * Paint it. */ void GL_texshape::paint ( int px, int py // Location in 'pixels' from top-left // of screen. ) { glEnable(GL_TEXTURE_2D); // Enable texture-mapping. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glPushMatrix(); float x = static_cast(px); float y = static_cast(py) + texsize; if (frame) { x += frame->get_xright() + 1 - (int) texsize; y += frame->get_ybelow() + 1 - (int) texsize; } // Game y-coord goes down from top. y = -y; float w = static_cast(texsize), h = static_cast(texsize); glTranslatef(x, y, 0); // Choose texture. glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_QUADS); { glTexCoord2f(0, 0); glVertex3f(0, h, 0); glTexCoord2f(0, 1); glVertex3f(0, 0, 0); glTexCoord2f(1, 1); glVertex3f(w, 0, 0); glTexCoord2f(1, 0); glVertex3f(w, h, 0); } glEnd(); glPopMatrix(); } /* * Create OpenGL manager. */ GL_manager::GL_manager ( ) : shapes(0), num_shapes(0), palette(0), scale(1) { assert (instance == 0); // Should only be one. instance = this; GLint max_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); max_texsize = max_size; glShadeModel(GL_SMOOTH); // Smooth shading. glClearColor(1, 1, 1, 0); // Background is white. glClearDepth(1); /* glEnable(GL_DEPTH_TEST); // Enable depth-testing. glDepthFunc(GL_LEQUAL); */ // I'm disabling depth buffer because it's not needed, at the moment. // It's also causing problems. Not being cleared perhaps? or bad depth // values for each object. Anyway, I'm disabling both testing and writing // -Colourless glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // ?? glEnable(GL_BLEND); // !These two calls do the trick. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Just a note for Jeff, You are using Alpha Blending, but you should // perhaps think about using Alpha Testing. // The functions are glAlphaFunc() and glEnable(GL_ALPHA_TEST). // Normally a glAlphaFunc(GL_GEQUAL, 127) will do the trick for you // -Colourless } /* * Free resources. */ GL_manager::~GL_manager ( ) { assert (this == instance); while (shapes) { GL_texshape *next = shapes->lru_next; delete shapes; shapes = next; } delete palette; instance = 0; } /* * Window was resized. */ void GL_manager::resized ( int new_width, int new_height, int new_scale ) { scale = new_scale; // Set viewing area to whole window. glViewport(0, 0, scale*new_width, scale*new_height); glMatrixMode(GL_PROJECTION); // Set up orthogonal volume. glLoadIdentity(); // Set camera area in 'pixels'. glOrtho(0, new_width, -new_height, 0, 1, -16); glMatrixMode(GL_MODELVIEW); // Use model-view matrix from now on. glLoadIdentity(); // Clear screen & depth buffer. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } /* * Paint an image directly. */ static void Paint_image ( Shape_frame *frame, int px, int py, // 'Pixel' position from top-left. unsigned char *pal, // 3*256 bytes (rgb). int scale // Scale factor. ) { px -= frame->get_xleft(); // Figure actual from hot-spot. py += frame->get_ybelow(); // Game y-coord goes down from top. py = -py; int w = frame->get_width(), h = frame->get_height(); // Render frame. Image_buffer8 buf8(w, h); w = buf8.get_width(); h = buf8.get_height(); buf8.fill8(transp); // Fill with transparent value. frame->paint(&buf8, frame->get_xleft(), frame->get_yabove()); // Convert to rgba. unsigned char *pixels = buf8.rgba(pal, transp); if (px < 0) // Doesn't paint if off screen. { glPixelStorei(GL_UNPACK_SKIP_PIXELS, -px); glPixelStorei(GL_UNPACK_ROW_LENGTH, w); w += px; px = 0; } //++++CHeck py too? // float x = static_cast(px); // float y = static_cast(py); glPixelZoom(scale, -scale); // Get right side up. glRasterPos2f(px, py + h); glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); delete pixels; } /* * Paint a shape. */ void GL_manager::paint ( Shape_frame *frame, int px, int py, // 'Pixel' position from top-left. Xform_palette *xforms, // Transforms translucent colors if !0. int xfcnt // Number of xforms. ) { GL_texshape *tex = frame->glshape; if (!tex) // Need to create texture? { if (frame->get_width() > max_texsize || frame->get_height() > max_texsize) { // Too big? Just paint it now. Paint_image(frame, px, py, palette, scale); return; } frame->glshape = tex = new GL_texshape(frame, palette, xforms, xfcnt); num_shapes++; //++++++When 'too many', we'll free LRU here. } else // Remove from chain. { if (tex->lru_next) tex->lru_next->lru_prev = tex->lru_prev; if (tex->lru_prev) tex->lru_prev->lru_next = tex->lru_next; tex->lru_prev = 0; // It will go to the head. } tex->lru_next = shapes; // Add to head of chain. if (shapes) shapes->lru_prev = tex; shapes = tex; tex->paint(px, py); } #endif /* HAVE_OPENGL */ exult-1.2/npcnear.h0000644000175000001440000000325307724430450010001 /* * npcnear.h - At random times, run proximity usecode functions on nearby NPC's. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NPCNEAR_H #define NPCNEAR_H 1 #include "lists.h" #include "tqueue.h" class Game_window; class Npc_actor; /* * This class keeps track of NPC's nearby, and randomly runs the Usecode * proximity functions for them. */ class Npc_proximity_handler : public Time_sensitive { Game_window *gwin; unsigned long wait_until; // Skip running usecodes until past. public: Npc_proximity_handler(Game_window *gw) : gwin(gw) { wait_until = 0; } // Add npc to queue. void add(unsigned long curtime, Npc_actor *npc, int additional_secs = 0); void remove(Npc_actor *npc); // Remove. // Run usecode function. void handle_event(unsigned long curtime, long udata); // Wait before running more funs. void wait(int secs); void get_all(Actor_queue& list); // Fill list with nearby NPC's. }; #endif /* INCL_NPCNEAR */ exult-1.2/stamp-h.in0000644000175000001440000000001210061527043010062 timestamp exult-1.2/README.MacOSX0000644000175000001440000000261310012217341010134 Exult instructions for Mac OS X ------------------------------- To play ------- First you need to get Ultima 7. Either you own it already, or you buy it somewhere. Then you must install it on a DOS/Windows machine in order to get the data file. A good way is to use a PC emulator for this, e.g. Virtual PC, Real PC or SoftWindows. Note that the Ultima Collection already contains an installed copy of Ultima 7. (In the Ultima7/ directory.) From the Ultima7 folder on your PC, copy the STATIC sub folder to the folder that contains the ExultMac application. Now run ExultMac, and have fun! More Information ---------------- More information can be found in the accompanying files README and FAQ. In addition, you might want to check out our homepage at http://exult.sourceforge.net How to compile on Mac OS X -------------------------- Install these from Apple: December 2002 Mac OS X Developer Tools (or newer) Dec 2002 gcc Updater (gcc 3.3) (or newer) Activate gcc 3.3 (from Apple's updater): sudo gcc_select 3.3 Install these packages with Fink: sdl sdl-mixer automake1.7 libtool14 Create these symbolic links: sudo ln -s /sw/lib/libsmpeg-0.4.0.dylib /sw/lib/libsmpeg.dylib sudo ln -s /sw/lib/libvorbisfile.3.dylib /sw/lib/libvorbisfile.dylib sudo ln -s /sw/lib/libvorbis.0.dylib /sw/lib/libvorbis.dylib sudo ln -s /sw/lib/libogg.0.dylib /sw/lib/libogg.dylib Compile Exult: ./autogen.sh ./configure make exult-1.2/usecode/0000777000175000001440000000000010062225333007701 5exult-1.2/usecode/ucxt/0000777000175000001440000000000010062225333010664 5exult-1.2/usecode/ucxt/src/0000777000175000001440000000000010062225333011453 5exult-1.2/usecode/ucxt/src/ucfunc.cc0000644000175000001440000010013107724430454013172 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ucdata.h" #include "ucfunc.h" #include #ifdef HAVE_SSTREAM #include #else #include #endif #include #include #include "files/utils.h" #include "ops.h" #if 0 #define DEBUG_INDENT #define DEBUG_PARSE #define DEBUG_PARSE2 #define DEBUG_PARSE2a #define DEBUG_READ #define DEBUG_PRINT #define DEBUG_READ_PAIR(X, Y) cout << '\t' << X << '\t' << Y << endl; #else #undef DEBUG_INDENT #undef DEBUG_PARSE #undef DEBUG_PARSE2 #undef DEBUG_READ #undef DEBUG_PRINT #define DEBUG_READ_PAIR(X, Y) #endif //#define DEBUG_PARSE2 //#define DEBUG_PARSE2a //#define DEBUG_PRINT using std::ostream; using std::ifstream; using std::string; using std::vector; using std::map; using std::endl; using std::pair; using std::ios; using std::streampos; using std::cout; using std::setw; using std::less; const string VARNAME = "var"; const string VARPREFIX = "var"; string demunge_ocstring(UCFunc &ucf, const FuncMap &funcmap, const string &asmstr, const vector ¶ms, const map &intrinsics, const UCc &op, bool ucs_output); /* Assumption the 'var's are in their 'zeroed' state on initialization, unless something else is assigned to them. */ inline ostream &tab_indent(const unsigned int indent, ostream &o) { #ifdef DEBUG_INDENT o << indent; #endif switch(indent) { case 0: break; case 1: o << '\t'; break; case 2: o << "\t\t"; break; case 3: o << "\t\t\t"; break; case 4: o << "\t\t\t\t"; break; case 5: o << "\t\t\t\t\t"; break; default: for(unsigned int i=0; isecond; o << endl; return true; } /* Outputs the usecode-script formatted usecode, returns true upon success */ bool UCFunc::output_ucs(ostream &o, const FuncMap &funcmap, const map &intrinsics, const UCOptions &options) { unsigned int indent=0; if(_externs.size()) tab_indent(indent, o) << "// externs" << endl; // output the 'externs' for(vector::iterator e=_externs.begin(); e!=_externs.end(); e++) { FuncMap::const_iterator fmp = funcmap.find(*e); output_ucs_funcname(tab_indent(indent, o) << "extern ", funcmap, *e, fmp->second.num_args, fmp->second.return_var) << ';' << endl; } if(_externs.size()) o << endl; // output the function name output_ucs_funcname(tab_indent(indent, o), funcmap, _funcid, _num_args, return_var) << endl; // start of func tab_indent(indent++, o) << '{' << endl; for(unsigned int i=_num_args; i<_num_args+_num_locals; i++) tab_indent(indent, o) << VARNAME << ' ' << VARPREFIX << std::setw(4) << i << ';' << endl; if(return_var) tab_indent(indent, o) << VARNAME << ' ' << "rr" << ';' << endl; if(_num_locals>0) o << endl; output_ucs_data(o, funcmap, intrinsics, options, indent); tab_indent(--indent, o) << '}' << endl; return true; } /* outputs the general 'function name' in long format. For function declarations and externs */ ostream &UCFunc::output_ucs_funcname(ostream &o, const FuncMap &funcmap, unsigned int funcid, unsigned int numargs, bool return_var) { // do we return a variable if(return_var) o << VARNAME << ' '; // output the "function name" // TODO: Probably want to grab this from a file in the future... //o << demunge_ocstring(*this, funcmap, "%f1", ucc._params_parsed, intrinsics, ucc, true) FuncMap::const_iterator fmp = funcmap.find(funcid); if(fmp->second.funcname.size()) { if(fmp->second.funcname[0]=='&') o << fmp->second.funcname.substr(1, fmp->second.funcname.size()-1); else o << fmp->second.funcname; } else o << "Func" << std::setw(4) << funcid; // output the "function number" o << " 0x" << funcid // output ObCurly braces << " ("; for(unsigned int i=0; i &intrinsics, const UCOptions &options, unsigned int indent) { vector labeltmp(1); for(vector::iterator i=gotoset.begin(); i!=gotoset.end(); ++i) { // we don't want to output the first "jump" (the start of the function) if(i!=gotoset.begin()) { labeltmp[0]=i->offset(); tab_indent(indent++, o) << demunge_ocstring(*this, funcmap, "label%f*_%1:", labeltmp, intrinsics, UCc(), true) << endl; } for(GotoSet::iterator j=(*i)().begin(); j!=(*i)().end(); j++) { const UCc &ucc = *(j->first); if(options.uselesscomment) tab_indent(indent, o) << "// Offset: " << std::setw(4) << ucc._offset << endl; output_ucs_opcode(o, funcmap, opcode_table_data, ucc, intrinsics, indent); } if(i!=gotoset.begin()) --indent; //decrement it again to skip the label statement. } } void UCFunc::output_ucs_opcode(ostream &o, const FuncMap &funcmap, const vector &optab, const UCc &op, const map &intrinsics, unsigned int indent) { tab_indent(indent, o) << demunge_ocstring(*this, funcmap, optab[op._id].ucs_nmo, op._params_parsed, intrinsics, op, true) << ';' << endl; #ifdef DEBUG_PRINT for(vector::const_iterator i=op._popped.begin(); i!=op._popped.end(); i++) { if((*i)->_popped.size()) output_ucs_opcode(o, funcmap, opcode_table_data, **i, intrinsics, indent+1); else // tab_indent(indent+1, o) << demunge_ocstring(*this, funcmap, optab[(*i)->_id].ucs_nmo, op._params_parsed, **i) << endl; tab_indent(indent+1, o) << optab[(*i)->_id].ucs_nmo << endl; } #endif } void UCFunc::output_ucs_node(ostream &o, const FuncMap &funcmap, UCNode* ucn, const map &intrinsics, unsigned int indent, const UCOptions &options) { if(!ucn->nodelist.empty()) tab_indent(indent, o) << '{' << endl; if(ucn->ucc!=0) output_asm_opcode(tab_indent(indent, o), funcmap, opcode_table_data, intrinsics, *(ucn->ucc), options); if(ucn->nodelist.size()) for(vector::iterator i=ucn->nodelist.begin(); i!=ucn->nodelist.end(); i++) { //tab_indent(indent, o); output_ucs_node(o, funcmap, *i, intrinsics, indent+1, options); } // end of func if(!ucn->nodelist.empty()) tab_indent(indent, o) << '}' << endl; } /* Just a quick function to remove all the ucc structured flagged as removable */ inline void gc_gotoset(vector &gotoset) { for(vector::iterator i=gotoset.begin(); i!=gotoset.end(); i++) { i->gc(); #ifdef DEBUG_GOTOSET cout << "----" << endl; #endif } } void UCFunc::parse_ucs(const FuncMap &funcmap, const map &intrinsics, const UCOptions &options) { for(vector::iterator i=_opcodes.begin(); i!=_opcodes.end(); i++) node.nodelist.push_back(new UCNode(&(*i))); parse_ucs_pass1(node.nodelist); parse_ucs_pass2(gotoset, funcmap, intrinsics); gc_gotoset(gotoset); if(!options.basic) { parse_ucs_pass3(gotoset, intrinsics); } #ifdef DEBUG_PARSE2 for(vector::iterator i=gotoset.begin(); i!=gotoset.end(); i++) { cout << std::setw(4) << i->offset() << endl; for(GotoSet::iterator j=(*i)().begin(); j!=(*i)().end(); j++) { cout << '\t' << std::setw(4) << j->first->_offset << '\t' << j->first->_id << endl; } } #endif } /* Pass 1 turns the 1-dimentional vector of opcodes, into a 2-dimentional array consisting of all the opcodes within two 'goto target offsets'. */ void UCFunc::parse_ucs_pass1(vector &nodes) { vector jumps; // collect jump references for(unsigned int i=0; iucc!=0) { unsigned int isjump=0; for(vector >::iterator op=opcode_jumps.begin(); op!=opcode_jumps.end(); op++) if(op->first==nodes[i]->ucc->_id) { isjump=op->second; break; } if(isjump!=0) { assert(nodes[i]->ucc->_params_parsed.size()>=isjump); jumps.push_back(nodes[i]->ucc->_params_parsed[isjump-1]); } } } gotoset.push_back(GotoSet()); for(unsigned int i=0; iucc!=0) { if(count(jumps.begin(), jumps.end(), nodes[i]->ucc->_offset)) { gotoset.push_back(nodes[i]->ucc); } else gotoset.back().add(nodes[i]->ucc); } } } /* In Pass 2 we convert our 2-dimensional 'GotoSet' array into an array with each UCc, having it's parameters sitting in it's UCc::_popped vector. Elements that are parameters are flagged for removal (Gotoset::()[i]->second=true) from the original GotoSet. */ void UCFunc::parse_ucs_pass2(vector &gotoset, const FuncMap &funcmap, const map &intrinsics) { for(vector::iterator i=gotoset.begin(); i!=gotoset.end(); ++i) { parse_ucs_pass2a((*i)().rbegin(), (*i)(), 0, funcmap, intrinsics); } } vector UCFunc::parse_ucs_pass2a(vector >::reverse_iterator current, vector > &vec, unsigned int opsneeded, const FuncMap &funcmap, const map &intrinsics) { vector vucc; unsigned int opsfound=0; #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif for(;vec.rend()!=current; current++) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(3, cout), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif if(current->second==false) { if((opcode_table_data[current->first->_id].num_pop!=0) || (opcode_table_data[current->first->_id].call_effect!=0)) { //if(opcode_table_data[current->first->_id].num_pop<0x7F) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(3, cout << "0x" << std::setw(2) << current->first->_id << "-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); tab_indent(3, cout << "0x" << std::setw(2) << current->first->_id << "-") << opcode_table_data[current->first->_id].num_pop << endl; #endif unsigned int num_args=0; if(opcode_table_data[current->first->_id].num_pop>0x7F) { #ifdef DEBUG_PARSE2a cout << "CALL EFFECT: " << opcode_table_data[current->first->_id].num_pop << '\t'; #endif unsigned int offset = 0x100 - opcode_table_data[current->first->_id].num_pop - 1; num_args = current->first->_params_parsed[offset]; #ifdef DEBUG_PARSE2a cout << num_args << endl; #endif } else if(opcode_table_data[current->first->_id].call_effect!=0) { assert(current->first->_params_parsed.size()>=1); assert(_externs.size()>=current->first->_params_parsed[0]); FuncMap::const_iterator fmp = funcmap.find(_externs[current->first->_params_parsed[0]]); assert(fmp!=funcmap.end()); #ifdef DEBUG_PARSE2 cout << "CALL: " << fmp->second.funcid << '\t' << fmp->second.num_args << endl; #endif num_args = fmp->second.num_args; } else { #ifdef DEBUG_PARSE2 cout << "Non-CALL: \t" << opcode_table_data[current->first->_id].num_pop << endl; #endif num_args = opcode_table_data[current->first->_id].num_pop; } if(num_args>0) { /* save the 'current' value as the return value and increment it so it's pointing at the 'next' current value */ vector >::reverse_iterator ret(current); ret->first->_popped = parse_ucs_pass2a(++current, vec, num_args, funcmap, intrinsics); assert(current!=ret); --current; assert(current==ret); #ifdef DEBUG_PARSE2a output_asm_opcode(tab_indent(1, cout), *this, funcmap, opcode_table_data, intrinsics, *(ret->first)); for(vector::iterator i=ret->first->_popped.begin(); i!=ret->first->_popped.end(); i++) output_asm_opcode(tab_indent(2, cout), *this, funcmap, opcode_table_data, intrinsics, **i); #endif } } } if((opsneeded!=0) && (current->second==false)) { // if it's a 'push' opcode and we need items to return that we've popped off the stack... if(opcode_table_data[current->first->_id].num_push!=0) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout << "P-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif opsfound+=opcode_table_data[current->first->_id].num_push; vucc.push_back(current->first); current->second=true; } // if it's a call to a function that returns a variable... else if(opcode_table_data[current->first->_id].call_effect!=0) { FuncMap::const_iterator fmp = funcmap.find(_externs[current->first->_params_parsed[0]]); assert(fmp!=funcmap.end()); if(fmp->second.return_var) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout << "C-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif opsfound+=1; vucc.push_back(current->first); current->second=true; } } else current->second=true; // if we've found all the ops we were searching for, return them if(opsfound>=opsneeded) { return vucc; } } } } if(vucc.size()>0) cout << "DID NOT FIND ALL OPCODE PARAMETERS." << endl; return vucc; } /* The 'optimisation' phase. Attempting to remove as many goto...labels as possible. */ void UCFunc::parse_ucs_pass3(vector &gotoset, const map &intrinsics) { } bool UCFunc::output_tt(std::ostream &o) { o << "\t<0x" << setw(4) << _funcid << ">" << endl; for(map >::iterator i=_data.begin(); i!=_data.end(); i++) { o << "\t\t<0x" << setw(4) << i->first << ">" << endl << "\t\t`" << i->second << "`" << endl << "\t\t" << endl; } o << "\t" << endl; return true; } /* calculates the relative offset jump location, used in opcodes jmp && jne */ inline int calc16reloffset(const UCc &op, unsigned int param) { /* forumla: real offset = offset of start of current opcode + int of parameter (since you can jump backwards) + 1 (size of "opcode") + size of "opcode" parameter data NOTE: since param is unsigned, a twos-complimant is required: formula: 0xFFFF - (unsigned short)param + 1 ^^^^^^ max of unsighed short */ return op._offset + ((param>>15) ? (-1 * (0xFFFF - static_cast(param) + 1)) : static_cast(param)) + 1 + op._params.size(); } /* calculates the relative offset jump location, used in opcodes jmp && jne */ inline int calc32reloffset(const UCc &op, unsigned int param) //FIXME: Test this! { /* forumla: real offset = offset of start of current opcode + int of parameter (since you can jump backwards) + 1 (size of "opcode") + size of "opcode" parameter data NOTE: since param is unsigned, a twos-complimant is required: formula: 0xFFFFFFFF - (unsigned int)param + 1 ^^^^^^ max of unsighed int */ return op._offset + ((param>>31) ? (-1 * (0xFFFFFFFF - static_cast(param) + 1)) : static_cast(param)) + 1 + op._params.size(); } void ucc_parse_parambytes(UCc &ucop, const UCOpcodeData &otd) { unsigned int first=0; for(vector >::const_iterator s=otd.param_sizes.begin(); s!=otd.param_sizes.end(); ++s) { //cout << ucop._id << '\t' << ucop._params.size() << endl; assert(firstfirst; bool offset_munge=s->second; assert(ssize!=0); if(ssize==1) ucop._params_parsed.push_back(static_cast(ucop._params[first++])); else if(ssize==2) if(offset_munge) { unsigned int calcvar = static_cast(ucop._params[first++]); calcvar += ((static_cast(ucop._params[first++])) << 8); unsigned int reloffset = calc16reloffset(ucop, calcvar); ucop._params_parsed.push_back(reloffset); ucop._jump_offsets.push_back(reloffset); } else { unsigned int calcvar = static_cast(ucop._params[first++]); calcvar += ((static_cast(ucop._params[first++])) << 8); ucop._params_parsed.push_back(calcvar); } else if(ssize==4) if(offset_munge) { unsigned int calcvar = static_cast(ucop._params[first++]); calcvar += ((static_cast(ucop._params[first++])) << 8); calcvar += ((static_cast(ucop._params[first++])) << 16); calcvar += ((static_cast(ucop._params[first++])) << 24); unsigned int reloffset = calc32reloffset(ucop, calcvar); ucop._params_parsed.push_back(reloffset); ucop._jump_offsets.push_back(reloffset); } else { unsigned int calcvar = static_cast(ucop._params[first++]); calcvar += ((static_cast(ucop._params[first++])) << 8); calcvar += ((static_cast(ucop._params[first++])) << 16); calcvar += ((static_cast(ucop._params[first++])) << 24); ucop._params_parsed.push_back(calcvar); } else assert(false); // just paranoia. } } /* prints the "assembler" output of the usecode, currently trying to duplicate the output of the original ucdump... returns true if successful*/ bool UCFunc::output_asm(ostream &o, const FuncMap &funcmap, const map &intrinsics, const UCOptions &options) { if(options.verbose) cout << "Printing function..." << endl; o << "Function at file offset " << std::setw(8) << _offset << "H" << endl; o << "\t.funcnumber " << std::setw(4) << _funcid << "H" << endl; if(ext32) o << "\t.ext32" << endl; o << "\t.msize " << ((ext32) ? setw(8) : setw(4)) << _funcsize << "H" << endl; o << "\t.dsize " << ((ext32) ? setw(8) : setw(4)) << _datasize << "H" << endl; if(debugging_info) o << "\t .dbgoffset " << std::setw(4) << debugging_offset << "H" << endl; if(_data.size()) output_asm_data(o); o << "Code segment at file offset " << std::setw(8) << _codeoffset << "H" << endl; o << "\t.argc " << std::setw(4) << _num_args << "H" << endl; o << "\t.localc " << std::setw(4) << _num_locals << "H" << endl; o << "\t.externsize " << std::setw(4) << _externs.size() << "H" << endl; for(typeof(_externs.begin()) i=_externs.begin(); i!=_externs.end(); i++) o << '\t' << " .extern " << std::setw(4) << *i << "H" << endl; /* for(unsigned int i=0; i<_externs.size(); i++) //FIXME: ::iterators o << '\t' << " .extern " << std::setw(4) << _externs[i] << "H" << endl;*/ for(vector::iterator op=_opcodes.begin(); op!=_opcodes.end(); op++) output_asm_opcode(o, funcmap, opcode_table_data, intrinsics, *op, options); return true; } void UCFunc::output_asm_data(ostream &o) { static const unsigned int nochars=60; // limit of about 60 chars to a line, wrap to the next line if longer then this... for(map >::iterator i=_data.begin(); i!=_data.end(); i++) { for(unsigned int j=0; jsecond.size(); j++) { if(j==0) o << setw(4) << i->first; if((j!=0) && !(j%nochars)) o << "'" << endl; if(!(j%nochars)) o << "\tdb\t'"; o << i->second[j]; } o << "'" << endl; o << "\tdb\t00" << endl; } } void UCFunc::output_raw_opcodes(ostream &o, const UCc &op) { // chars in opcode o << ' ' << std::setw(2) << static_cast(op._id); if(op._params.size()) cout << ' '; for(unsigned int i=0; i(op._params[i]); if(i!=op._params.size()) o << ' '; } // seperator unsigned int numsep = op._params.size(); //cout << endl << numsep << endl; if(numsep>6) o << endl << "\t\t\t"; else if (numsep>5) o << " "; else if (numsep>2) o << "\t"; else o << "\t\t"; } void UCFunc::output_asm_opcode(ostream &o, const FuncMap &funcmap, const vector &optab, const map &intrinsics, const UCc &op, const UCOptions &options) { // offset o << std::setw(4) << op._offset << ':'; if(options.rawops) output_raw_opcodes(o, op); else o << '\t'; o << demunge_ocstring(*this, funcmap, optab[op._id].asm_nmo, op._params_parsed, intrinsics, op, false); if(options.autocomment) o << demunge_ocstring(*this, funcmap, optab[op._id].asm_comment, op._params_parsed, intrinsics, op, false); o << endl; } inline unsigned int charnum2uint(const char c) { switch(c) { case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return 0; } return 0; // can't happen } // FIXME: Remove the passed ¶ms value. Get it from op._params_parsed string demunge_ocstring(UCFunc &ucf, const FuncMap &funcmap, const string &asmstr, const vector ¶ms, const map &intrinsics, const UCc &op, bool ucs_output) { #ifdef HAVE_SSTREAM std::stringstream str; #else std::strstream str; #endif str << std::setfill('0') << std::setbase(16); str.setf(ios::uppercase); size_t len=asmstr.length(); if(len==0) return string(); // for the degenerate case bool finished=false; // terminating details are at end-of-while unsigned int i=0; // istr index unsigned int width=0; // width value for setw() if(ucs_output && opcode_table_data[op._id].flag_paren) str << '('; while(!finished&&i temporary exception handling for call (0x24) char c = asmstr[i]; width = 4; // with defaults to 4 switch(c) { case '\\': i++; c = asmstr[i]; switch(c) { case '\\': str << '\\'; break; case 'n': str << '\n'; break; case 't': str << '\t'; break; case '\'': str << '\''; break; case '"': str << '\"'; break; case 'b': // bell is invalid default: // we'll silently drop errors... it's the only "clean" way str << '\\' << c; } break; case '%': { i++; c = asmstr[i]; // if it's a "byte" set width to 2, and get the next char if(c=='b') { i++; c = asmstr[i]; width=2; } // if it's a "short" set width to 4, and get the next char else if(c=='s') { i++; c = asmstr[i]; width=4; } // if it's a "int" set width to 8, and get the next char else if(c=='n') { i++; c = asmstr[i]; width=8; } // if it's a "long" set width to 16, and get the next char else if(c=='l') { i++; c = asmstr[i]; width=16; } // if we want to output the 'decimal' value rather then the default hex else if(c=='d') { i++; c = asmstr[i]; unsigned int t = charnum2uint(c); if(t!=0) { assert(params.size()>=t); str << std::setbase(10) << params[t-1] << std::setbase(16); } else if(c=='%') str << '%'; break; } // if it's the character representation of a text data string we want else if(c=='t') { bool commentformat=false; i++; c = asmstr[i]; // if we only want to output the 'short' format of the text (comment format) if(c=='c') { commentformat=true; i++; c = asmstr[i]; } unsigned int t = charnum2uint(c); assert(params.size()>=t); assert(t!=0); string s = ucf._data.find(params[t-1])->second; if(commentformat) if(s.size()>17) s = s.substr(0, 17) + string("..."); // escape the appropriate characters... // we'll only do it in the 'full' text output for the moment. if(!commentformat) for(string::size_type i=0; i=t); assert(t!=0); string s = intrinsics.find(params[t-1])->second; str << s; break; } // if it's external function name we want else if(c=='f') { i++; c = asmstr[i]; if(c=='*') { if(ucf.funcname.size()) { if(ucf.funcname[0]=='&') str << ucf.funcname.substr(1, ucf.funcname.size()-1); else str << ucf.funcname; } else str << "Func" << std::setw(4) << ucf._funcid; } else { unsigned int t = charnum2uint(c); assert(ucf._externs.size()>=t); assert(t!=0); assert(op._params_parsed.size()>=1); FuncMap::const_iterator fmp = funcmap.find(ucf._externs[op._params_parsed[t-1]]); if(fmp->second.funcname.size()) { if(fmp->second.funcname[0]=='&') str << fmp->second.funcname.substr(1, fmp->second.funcname.size()-1); else str << fmp->second.funcname; } else str << "Func" << std::setw(4) << ucf._externs[op._params_parsed[t-1]]; } break; } // if it's the character representation of a text data string we want else if(c=='p') { i++; c = asmstr[i]; unsigned int t = charnum2uint(c); // FIXME: this is the special 'call' case, it may be a good idea to make more general if((t==0) && (c==',')) { special_call=true; for(vector::const_iterator i=op._popped.begin(); i!=op._popped.end();) { str << demunge_ocstring(ucf, funcmap, opcode_table_data[(*i)->_id].ucs_nmo, (*i)->_params_parsed, intrinsics, **i, ucs_output); if(++i!=op._popped.end()) str << ", "; } } if(t!=0) { if(t>op._popped.size()) str << "SOMETHING_GOES_HERE()"; else { UCc &ucc(*op._popped[t-1]); str << demunge_ocstring(ucf, funcmap, opcode_table_data[ucc._id].ucs_nmo, ucc._params_parsed, intrinsics, ucc, ucs_output); } } break; } if(special_call!=true) { unsigned int t = charnum2uint(c); if(t!=0) { assert(params.size()>=t); str << std::setw(width) << params[t-1]; } else if(c=='%') str << '%'; } } break; default: // it's just a character, leave it be str << c; } i++; if(i==asmstr.size()) finished=true; } if(ucs_output && opcode_table_data[op._id].flag_paren) str << ')'; return str.str(); } void readbin_U7UCFunc(ifstream &f, UCFunc &ucf, const UCOptions &options) { // #define DEBUG_READ_PAIR(X, Y) cout << '\t' << X << '\t' << Y << endl; // offset to start of function ucf._offset = f.tellg(); DEBUG_READ_PAIR(" Offset: ", ucf._offset); // Read Function Header ucf._funcid = Read2(f); if(options.very_verbose) cout << "\tReading Function: " << setw(4) << ucf._funcid << endl; DEBUG_READ_PAIR(" FuncID: ", ucf._funcid); if(ucf._funcid!=0xFFFF) { // This is the original usecode function header ucf._funcsize = Read2(f); DEBUG_READ_PAIR(" FuncSize: ", ucf._funcsize); // save body offset in case we need it ucf._bodyoffset = f.tellg(); ucf._datasize = Read2(f); DEBUG_READ_PAIR(" DataSize: ", ucf._datasize); } else { // This is the ext32 extended usecode function header ucf.ext32=true; ucf._funcid = Read2(f); if(options.very_verbose) cout << "\tReading Function: " << setw(4) << ucf._funcid << endl; DEBUG_READ_PAIR(" extFuncID: ", ucf._funcid); ucf._funcsize = Read4(f); DEBUG_READ_PAIR(" extFuncSize: ", ucf._funcsize); // save body offset in case we need it ucf._bodyoffset = f.tellg(); ucf._datasize = Read4(f); DEBUG_READ_PAIR(" extDataSize: ", ucf._datasize); } // process ze data segment! { streampos pos = f.tellg(); // paranoia unsigned int off = 0; // Load all strings & their offsets while( off < ucf._datasize ) { assert(!f.eof()); string data; getline(f, data, static_cast(0x00)); ucf._data.insert(pair(off, data)); off+=data.size()+1; } f.seekg(pos, ios::beg); // paranoia f.seekg(ucf._datasize, ios::cur); // paranoia } #if 0 if(ucf._funcid==_search_func) for(map::iterator i=ucf._data.begin(); i!=ucf._data.end(); i++) cout << i->first << "\t" << i->second << endl; #endif // process code segment { //streampos start_of_code_seg = f.tellg(); // what's this used for? ucf._codeoffset = f.tellg(); // get the number of arguments to the function ucf._num_args = Read2(f); // get the number of local variables ucf._num_locals = Read2(f); // get the number of external function numbers ucf._num_externs = Read2(f); // load the external function numbers for(unsigned int i=0; i=2); ucf.debugging_offset = ucop._params_parsed[1]; ucf.funcname = ucf._data.find(0x0000)->second; } ucf._opcodes.push_back(ucop); #ifdef DEBUG_READ cout << std::setw(4) << code_size << "\t" << std::setw(4) << code_offset << "\t" << std::setw(4) << (unsigned int)ucop._offset << "\t" << std::setw(2) << (unsigned int)ucop._id << "\t"; for(unsigned int i=0; i #endif #include #include #include #include #include #include #include #include #include "ucc.h" #include "ops.h" #include "ucdata.h" #include "ucfunc.h" #include "files/utils.h" // include xml configuration stuff #include "Configuration.h" #include "exult_constants.h" const std::string c_empty_string; // Ob for exult_constants.h /* Functions */ void usage(); void open_usecode_file(UCData &uc, const Configuration &config); UCData uc; using std::setw; using std::cerr; using std::cout; using std::ios; using std::string; using std::endl; int main(int argc, char** argv) { // Tends to make life easier cout << std::setfill('0') << std::setbase(16); cout.setf(ios::uppercase); // get the parameters uc.parse_params(argc, argv); if(uc.options.verbose) cout << "Parameters parsed..." << endl; Configuration config; // attempt to find an exult.cfg file... _somewhere_ if(uc.options.noconf == false) { if(uc.options.verbose) cout << "Loading exult configuration file..." << endl; if(config.read_config_file("exult.cfg") == false) { cout << "Failed to locate exult.cfg. Run exult before running ucxt or use the -nc switch. Exiting." << endl; exit(1); } } // init the run time tables if(uc.options.verbose) cout << "Initing runtime tables..." << endl; ucxtInit init; init.init(config, uc.options); #if 0 { cout << "" << endl; for(typeof(opcode_table_data.begin()) i=opcode_table_data.begin(); i!=opcode_table_data.end(); i++) { if(i->opcode!=0 && i->name!="NULL") { cout << "\t<0x" << setw(2) << i->opcode << '>' << endl; cout << "\t\t " << i->name << " " << endl; cout << "\t\t `" << i->asm_nmo << "` " << endl; cout << "\t\t `" << i->asm_comment << "` " << endl; cout << "\t\t `" << i->ucs_nmo << "` " << endl; cout << "\t\t " << i->num_bytes << " " << endl; cout << "\t\t {"; for(typeof(i->param_types.begin()) j=i->param_types.begin(); j!=i->param_types.end(); j++) cout << *j << ','; cout << "} " << endl; cout << "\t\t " << i->num_pop << " " << endl; cout << "\t\t " << i->num_push << " " << endl; cout << "\t\t " << i->call_effect << " " << endl; if(i->flag_return) cout << "\t\t" << endl; if(i->flag_paren) cout << "\t\t" << endl; if(i->flag_indent_inc) cout << "\t\t" << endl; if(i->flag_indent_dec) cout << "\t\t" << endl; if(i->flag_indent_tmpinc) cout << "\t\t" << endl; if(i->flag_indent_tmpdec) cout << "\t\t" << endl; cout << "\t" << endl; } } cout << "" << endl; } #endif // ICK! Don't try this at home kids... // done because for some reason it started crashing upon piping or redirection to file... wierd. // yes, it's a hack to fix an eldritch bug I could't find... it seems appropriate // FIXME: Problem nolonger exists. Probably should put some 'nice' code in it's place. std::ofstream outputstream; std::streambuf *coutbuf=0; if(uc.output_redirect().size()) { U7open(outputstream, uc.output_redirect().c_str(), false); if(outputstream.fail()) { cout << "error. failed to open " << uc.output_redirect() << " for writing. exiting." << endl; exit(1); } coutbuf = cout.rdbuf(); cout.rdbuf(outputstream.rdbuf()); } // you may now uncover your eyes open_usecode_file(uc, config); if(uc.opt().output_extern_header) { uc.output_extern_header(cout); } else if ( uc.options.mode_dis || uc.options.mode_all ) { uc.disassamble(); } else if( uc.options.output_flag ) { uc.dump_flags(cout); } else usage(); // now we clean up the y ness from before if(uc.output_redirect().size()) { cout.rdbuf(coutbuf); } return 0; } void open_usecode_file(UCData &uc, const Configuration &config) { string bgpath; if(uc.options.noconf == false) config.value("config/disk/game/blackgate/path", bgpath); string sipath; if(uc.options.noconf == false) config.value("config/disk/game/serpentisle/path", sipath); string u8path; if(uc.options.noconf == false) config.value("config/disk/game/pagan/path", u8path); /* ok, to find the usecode file we search: (where $PATH=bgpath or sipath) $PATH/static/usecode $PATH/STATIC/usecode $PATH/static/USECODE $PATH/STATIC/USECODE ./ultima7/static/usecode || ./serpent/static/usecode ./ultima7/STATIC/usecode || ./serpent/STATIC/usecode ./ultima7/static/USECODE || ./serpent/static/USECODE ./ultima7/STATIC/USECODE || ./serpent/STATIC/USECODE ./ULTIMA7/static/usecode || ./SERPENT/static/usecode ./ULTIMA7/STATIC/usecode || ./SERPENT/STATIC/usecode ./ULTIMA7/static/USECODE || ./SERPENT/static/USECODE ./ULTIMA7/STATIC/USECODE || ./SERPENT/STATIC/USECODE ./static/usecode ./STATIC/usecode ./static/USECODE ./STATIC/USECODE ./usecode.bg || ./usecode.si ./USECODE ./usecode Anything I'm missing? */ /* The capitilisation configurations: (yes, going overkill, typos are BAD!) */ // These 4 are only specific to BG && SI string mucc_sl("static"); string mucc_sc("STATIC"); string mucc_ul("usecode"); string mucc_uc("USECODE"); const string mucc_bgl("ultima7"); const string mucc_bgc("ULTIMA7"); const string mucc_sil("serpent"); const string mucc_sic("SERPENT"); const string mucc_u8l("pagan"); const string mucc_u8c("PAGAN"); string path, ucspecial, mucc_l, mucc_c; if(uc.options.game_bg()) { if(uc.options.verbose) cout << "Configuring for bg." << endl; path = bgpath; ucspecial = "usecode.bg"; mucc_l = mucc_bgl; mucc_c = mucc_bgc; } else if(uc.options.game_si()) { if(uc.options.verbose) cout << "Configuring for si." << endl; path = sipath; ucspecial = "usecode.si"; mucc_l = mucc_sil; mucc_c = mucc_sic; } else if(uc.options.game_u8()) { if(uc.options.verbose) cout << "Configuring for u8." << endl; path = u8path; ucspecial = "usecode.u8"; mucc_l = mucc_u8l; mucc_c = mucc_u8c; mucc_sl = "usecode"; mucc_sc = "USECODE"; mucc_ul = "eusecode.flx"; mucc_uc = "EUSECODE.FLX"; } else { cerr << "Error: uc.game() was not set to GAME_U7 or GAME_SI or GAME_U8 this can't happen" << endl; assert(false); exit(1); // just incase someone decides to compile without asserts; } /* The four mystical usecode configurations: */ const string mucc_ll(string("/") + mucc_sl + "/" + mucc_ul); const string mucc_cl(string("/") + mucc_sc + "/" + mucc_ul); const string mucc_lc(string("/") + mucc_sl + "/" + mucc_uc); const string mucc_cc(string("/") + mucc_sc + "/" + mucc_uc); // an icky exception chain for those who don't use .exult.cfg if(uc.input_usecode_file().size()) uc.open_usecode(uc.input_usecode_file()); else if(uc.options.noconf==false) { uc.open_usecode(path + mucc_ll); if(uc.fail()) uc.open_usecode(path + mucc_cl); if(uc.fail()) uc.open_usecode(path + mucc_lc); if(uc.fail()) uc.open_usecode(path + mucc_cc); if(uc.fail()) uc.open_usecode(mucc_l + mucc_ll); } else uc.open_usecode(mucc_l + mucc_ll); if(uc.fail()) uc.open_usecode(mucc_l + mucc_cl); if(uc.fail()) uc.open_usecode(mucc_l + mucc_lc); if(uc.fail()) uc.open_usecode(mucc_l + mucc_cc); if(uc.fail()) uc.open_usecode(mucc_c + mucc_ll); if(uc.fail()) uc.open_usecode(mucc_c + mucc_cl); if(uc.fail()) uc.open_usecode(mucc_c + mucc_lc); if(uc.fail()) uc.open_usecode(mucc_c + mucc_cc); if(uc.fail()) uc.open_usecode(mucc_ll); if(uc.fail()) uc.open_usecode(mucc_cl); if(uc.fail()) uc.open_usecode(mucc_lc); if(uc.fail()) uc.open_usecode(mucc_cc); if(uc.fail()) uc.open_usecode(ucspecial); if(uc.fail()) uc.open_usecode(mucc_uc); if(uc.fail()) uc.open_usecode(mucc_ul); // if we get through all this, usecode can't be installed anywhere sane if(uc.fail()) { cout << "Failed to locate usecode file. Exiting." << endl; exit(1); } } void usage() { cout << "Ultima 7/8 usecode disassembler v0.6.3" << endl #ifdef HAVE_CONFIG_H << " compiled with " << PACKAGE << " " << VERSION << endl #endif << endl; cout << "Usage:" << endl << "\tucxt [options] -a" << endl << "\t\t- prints all of the functions" << endl << "\tucxt [options] " << endl << "\t\t- disassembles single function to stdout" << endl // << "\tucdump -c - scans the whole usecode file for unknown opcodes" << endl // << "\tucdump -o - prints list of functions which use " // << "the given opcode" << endl // << "\tucdump -i - prints list of functions which use " // << "the given intrinsic function\n" << endl // << "\tucxt -f - prints list of all flags x functions" << endl << endl << "\tMisc Flags (any/all of these):" << endl << "\t\t-nc\t- don't look for exult's .xml config file" << endl << "\t\t-v \t- turns on verbose output mode" << endl << "\t\t-ofile\t- output to the specified file" << endl << "\t\t-ifile\t- load the usecode file specified by the filename" << endl << "\t\t-ro\t- output the raw opcodes in addition to the -f format" << endl << "\t\t-ac\t- output automatically generated comments" << endl << "\t\t-uc\t- output automatically generated 'useless' comments" << endl << "\t\t-b\t- only do 'basic' optimisations" << endl << "\t\t-dbg\t- output debugging information if present in USECODE." << endl << "\t\t-ext32\t- 'convert' function to ext32 format if not already." << endl << "\tGame Specifier Flags (only one of these):" << endl << "\t\t-bg\t- select the black gate usecode file" << endl << "\t\t-si\t- select the serpent isle usecode file" << endl << "\t\t-u8\t- select the ultima 8/pagan usecode file (experimental)" << endl << "\tOutput Format Flags (only one of these):" << endl << "\t\t-fl\t- output using brief \"list\" format" << endl << "\t\t-fa\t- output using \"assembler\" format (default)" << endl << "\t\t-fs\t- output using \"exult script\" format" << endl << "\t\t-fz\t- output using \"exult script\" format" << endl << "\t\t-ftt\t- output using the translation table xml format" << endl << "\t\t-ff\t- outputs all flags referenced in the usecode file" << endl << "\t\t\t sorted both by \"flags within a function\" and" << endl << "\t\t\t \"functions using flag\"" << endl ; exit(1); } exult-1.2/usecode/ucxt/src/ops.cc0000644000175000001440000002445607724430454012527 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "ops.h" #include "files/utils.h" #include "exceptions.h" #include #include #include #include #ifdef HAVE_SSTREAM #include using std::stringstream; #endif /*** head2data #ifndef __STRING #if defined __STDC__ && __STDC__ #define __STRING(x) #x #else #define __STRING(x) "x" #endif #endif */ using std::vector; using std::ifstream; using std::cout; using std::endl; using std::string; using std::cerr; using std::ends; using std::setw; using std::setfill; using std::setbase; using std::pair; using std::map; #define MAX_NO_OPCODES 512 vector opcode_table_data(MAX_NO_OPCODES); vector > opcode_jumps; map uc_intrinsics; map > type_size_map; void ucxtInit::init(const Configuration &config, const UCOptions &options) { datadir = get_datadir(config, options); misc_data = "u7misc.data"; misc_root = "misc"; opcodes_data = "u7opcodes.data"; opcodes_root = "opcodes"; bg_intrinsics_data = "u7bgintrinsics.data"; bg_intrinsics_root = "intrinsics"; si_intrinsics_data = "u7siintrinsics.data"; si_intrinsics_root = "intrinsics"; if(options.verbose) cout << "Initing misc..." << endl; misc(); if(options.verbose) cout << "Initing opcodes..." << endl; opcodes(); if(options.verbose) cout << "Initing intrinsics..." << endl; if(options.game_bg()) intrinsics(bg_intrinsics_data, bg_intrinsics_root); else if(options.game_si()) intrinsics(si_intrinsics_data, si_intrinsics_root); } string ucxtInit::get_datadir(const Configuration &config, const UCOptions &options) { string datadir; // just to handle if people are going to compile with makefile.unix, unsupported, but occasionally useful #ifdef HAVE_CONFIG_H if(options.noconf == false) config.value("config/ucxt/root", datadir, EXULT_DATADIR); #else if(options.noconf == false) config.value("config/ucxt/root", datadir, "data/"); #endif if(datadir.size() && datadir[datadir.size()-1]!='/' && datadir[datadir.size()-1]!='\\') datadir+='/'; if(options.verbose) cout << "datadir: " << datadir << endl; return datadir; } void ucxtInit::misc() { Configuration miscdata(datadir + misc_data, misc_root); Configuration::KeyTypeList om; miscdata.getsubkeys(om, misc_root + "/offset_munge"); Configuration::KeyTypeList st; miscdata.getsubkeys(st, misc_root + "/size_type"); // For each size type (small/long/byte/etc.) for(typeof(st.begin()) k=st.begin(); k!=st.end(); ++k) { bool munge_offset=false; const string tmpstr(k->first + "/"); /* ... we need to find out if we should munge it's parameter that is, it's some sort of goto target (like offset) or such */ for(typeof(om.begin()) m=om.begin(); m!=om.end(); ++m) if(m->first.size()-1==k->first.size()) if(m->first==tmpstr) // if(m->first.compare(0, m->first.size()-1, k->first, 0, k->first.size())==0) munge_offset=true; // once we've got it, add it to the map pair tsm_tmp(strtol(k->second.c_str(), 0, 0), munge_offset); type_size_map.insert(pair >(k->first, tsm_tmp)); } } /* constructs the usecode tables from datafiles in the /ucxt hierachy */ void ucxtInit::opcodes() { Configuration opdata(datadir + opcodes_data, opcodes_root); vector keys = opdata.listkeys(opcodes_root); #if 1 for(vector::iterator key=keys.begin(); key!=keys.end(); ++key) { if((*key)[0]!='!') { Configuration::KeyTypeList ktl; opdata.getsubkeys(ktl, *key); if(ktl.size()) { unsigned int i = strtol(key->substr(key->find_first_of("0")).c_str(), 0, 0); opcode_table_data[i] = UCOpcodeData(i, ktl); } } } #else string ucxtroot(datadir + "opcodes.txt"); std::ifstream file; try { U7open(file, ucxtroot.c_str(), true); } catch (const file_open_exception& e) { cerr << e.what() << ". exiting." << endl; exit(1); } std::string s; while(!file.eof()) { getline(file, s); if(s.size() && s[0]=='>') { UCOpcodeData uco(str2vec(s)); assert(uco.opcode::iterator op=opcode_table_data.begin(); op!=opcode_table_data.end(); op++) { for(unsigned int i=0; iparam_sizes.size(); i++) { if(op->param_sizes[i].second==true) // this is a calculated offset { opcode_jumps.push_back(std::pair(op->opcode, i+1)); // parameters are stored as base 1 } } } #if 0 std::cout << "Calculated Opcode pairs:" << std::endl; for(std::vector >::iterator i=opcode_jumps.begin(); i!=opcode_jumps.end(); i++) std::cout << setw(4) << i->first << '\t' << setw(4) << i->second << std::endl; #endif } void ucxtInit::intrinsics(const string &intrinsic_data, const string &intrinsic_root) { Configuration intdata(datadir + intrinsic_data, intrinsic_root); Configuration::KeyTypeList ktl; intdata.getsubkeys(ktl, intrinsic_root); for(Configuration::KeyTypeList::iterator k=ktl.begin(); k!=ktl.end(); k++) uc_intrinsics.insert(pair(strtol(k->first.c_str(), 0, 0), k->second)); } /* To be depricated when I get the complex std::vector splitter online */ std::vector qnd_ocsplit(const std::string &s) { assert((s[0]=='{') && (s[s.size()-1]=='}')); std::vector vs; std::string tstr; for(std::string::const_iterator i=s.begin(); i!=s.end(); ++i) { if(*i==',') { vs.push_back(tstr); tstr=""; } else if(*i=='{' || *i=='}') { /* nothing */ } else tstr+=*i; } if(tstr.size()) vs.push_back(tstr); return vs; } std::vector str2vec(const std::string &s) { std::vector vs; unsigned int lasti=0; // if it's empty return null if(s.size()==0) return vs; bool indquote=false; for(unsigned int i=0; i ¶m_types, std::vector > ¶m_sizes) { for(std::vector::const_iterator s=param_types.begin(); s!=param_types.end(); ++s) { map >::iterator tsm(type_size_map.find(*s)); if(tsm==type_size_map.end()) { cerr << "error: No size type `" << *s << "`" << endl; assert(tsm!=type_size_map.end()); } param_sizes.push_back(std::pair(tsm->second.first, tsm->second.second)); } } /*std::vector str2vec(const std::string &s) { std::vector vs; // the resulting strings stack vbound; // the "bounding" chars used to deonte collections of characters unsigned int lasti=0; std::string currstr; // the current string, gets appended to vs // if it's empty return null if(s.size()==0) return vs; for(unsigned int i=0; i'); break; // now the closures... case '}': if(vbound.top()=='}') vbound.pop(); if(vbound.size()==0) pushback=true; else currstr+=c; break; //case ']': // break; //case ')': // break; //case '>': // break; // now the ones that have the pretentiousness of being both // opening and closing causes case '\"': if(vs.size()) currstr+=c; vbound.push('\"'); break; case '\'': if(vs.size()) currstr+=c; vbound.push('\''); break; case '\"': if(vbound.top()=='\"') vbound.pop(); else vbound.push('\"'); if(vbound.size()==0) pushback=true; else currstr+=c; break; case '\'': if(vbound.top()=='\'') vbound.pop(); if(vbound.size()==0) pushback=true; else currstr+=c; break; // not to emulate isspace(); case ' ': // ze space case '\f': // form-feed case '\n': // newline case '\r': // carriage return case '\t': // horizontal tab case '\v': // vertical tab pushback=true; break; } if(pushback) { if(currstr.size()) vs.push_back(currstr); currstr=""; } } #if 1 //test for(unsigned int i=0; i #endif #include #include #include #include #include #include #include "ucdata.h" #include "ops.h" #include "files/utils.h" using std::cout; using std::setw; using std::endl; using std::vector; using std::setbase; using std::setfill; using std::string; using std::ostream; UCData::UCData() : _search_opcode(-1), _search_intrinsic(-1) { } UCData::~UCData() { _file.close(); for(unsigned int i=0; i<_funcs.size(); i++) delete _funcs[i]; } void UCData::parse_params(const unsigned int argc, char **argv) { /* Parse command line */ for(unsigned int i=1; i(strlen(argv[i])) ) /* Invalid number */ { /* Do Nothing */ } else { search_funcs.push_back(search_func); if(options.verbose) cout << "Disassembling Function: " << search_func << endl; options.mode_dis = true; } } else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-o") { _output_redirect = string(argv[i]).substr(2, string(argv[i]).size()-2); if(options.verbose) cout << "Outputting to filename: " << _output_redirect << endl; } else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-i") { _input_usecode_file = string(argv[i]).substr(2, string(argv[i]).size()-2); if(options.verbose) cout << "Inputting from file: " << _input_usecode_file << endl; } else { cout << "unsupported parameter " << argv[i] << " detected. countinuing." << endl; } } } void UCData::open_usecode(const string &filename) { file_open(filename); if(fail()) return; } // FIXME: Pass ostream to this, rather then cout-ing everything void UCData::disassamble() { load_funcs(); if(options.verbose) { for(vector::iterator i=search_funcs.begin(); i!=search_funcs.end(); i++) cout << "Looking for function number " << setw(8) << (*i) << endl; cout << endl; } if(options.output_list) cout << "Function offset size data code" << (options.ucdebug ? " funcname" : "") << endl; if(options.output_trans_table) cout << "" << endl; bool _foundfunc=false; //did we find and print the function? for(unsigned int i=0; i<_funcs.size(); i++) { if(options.mode_all || (options.mode_dis && count(search_funcs.begin(), search_funcs.end(), _funcs[i]->_funcid))) { _foundfunc=true; bool _func_printed=false; // to test if we've actually printed a function ouput if(options.output_list) _func_printed = _funcs[i]->output_list(cout, i, options); if(options.output_ucs) { _funcs[i]->parse_ucs(_funcmap, uc_intrinsics, options); _func_printed = _funcs[i]->output_ucs(cout, _funcmap, uc_intrinsics, options); //_func_printed=true; } if(options.output_trans_table) { _func_printed=_funcs[i]->output_tt(cout); //_func_printed=true; } // if we haven't printed one by now, we'll print an asm output. if(options.output_asm || (_func_printed==false)) _funcs[i]->output_asm(cout, _funcmap, uc_intrinsics, options); } } if(!_foundfunc) printf("Function not found.\n"); if(search_funcs.size()==0) { printf("Functions: %d\n", _funcs.size()); } if(options.output_list) cout << endl << "Functions: " << setbase(10) << _funcs.size() << setbase(16) << endl; if(options.output_trans_table) cout << "" << endl; cout << endl; } /* FIXME: Need to remove the hard coded opcode numbers (0x42 and 0x43) and replace them with 'variables' in the opcodes.txt file, that signify if it's a pop/push and a flag */ void UCData::dump_flags(ostream &o) { if(!(options.game_bg() || options.game_si())) { o << "This option only works for U7:BG and U7:SI" << endl; return; } load_funcs(); if(options.verbose) cout << "Finding flags..." << endl; vector flags; // *BLEH* ugly! for(vector::iterator func=_funcs.begin(); func!=_funcs.end(); func++) for(vector::iterator op=(*func)->_opcodes.begin(); op!=(*func)->_opcodes.end(); op++) { if(op->_id==0x42) flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::GETFLAG)); else if(op->_id==0x43) flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::SETFLAG)); } o << "Number of flags found: " << setbase(10) << flags.size() << endl << endl; // output per function { sort(flags.begin(), flags.end(), SortFlagDataLessFunc()); o << setbase(16) << setfill('0'); int currfunc = -1; for(unsigned int i=0; i(-1); for(unsigned int i=0; iext32=true; _funcs.push_back(ucfunc); { _file.get(); eof = _file.eof(); _file.unget(); } } #ifdef LOAD_SPEED_TEST dd.end(); cout << setbase(10) << setfill(' '); dd.print_start(cout) << endl; dd.print_end(cout) << endl; dd.print_diff(cout) << endl; cout << setbase(16) << setfill('0'); #endif if(options.verbose) cout << "Creating function map..." << endl; for(vector::iterator i=_funcs.begin(); i!=_funcs.end(); i++) { _funcmap.insert(FuncMapPair((*i)->_funcid, UCFuncSet((*i)->_funcid, (*i)->_num_args, (*i)->return_var, (*i)->funcname))); } /* for(map::iterator i=_funcmap.begin(); i!=_funcmap.end(); i++) cout << i->first << "\t" << i->second.num_args << endl;*/ } void UCData::output_extern_header(ostream &o) { if(!(options.game_bg() || options.game_si())) { o << "This option only works for U7:BG and U7:SI" << endl; return; } load_funcs(); for(vector::iterator func=_funcs.begin(); func!=_funcs.end(); func++) { //(*func)->output_ucs_funcname(o << "extern ", _funcmap, (*func)->_funcid, (*func)->_num_args, (*func)->return_var) << ';' << endl; (*func)->output_ucs_funcname(o << "extern ", _funcmap) << ';' << endl; } } exult-1.2/usecode/ucxt/Docs/0000777000175000001440000000000010062225333011554 5exult-1.2/usecode/ucxt/Docs/ucxtread.txt0000644000175000001440000010305707405167006014067 This file is currently a random pile of useful information... someday it'll be ordered in a coherent format. * Error: "error: could not locate */Docs/opcodes.txt. exiting" ucxt needs to find the abovementioned file for details of the opcodes. You either need to run ucxt in the path exult/usecode/ucxt or add the following to exult.cfg: (inside the tag) (the path to ucxt goes here (eg: /home/st/exult/usecode/ucxt/data)) * Error: "Failed to locate usecode file. Exiting." ucxt attempts to locate the exult.cfg file to find the locations of black gate (ultima7) and serpent isle (serpent). ucxt hunts for the usecode file under all permutations of the following filenamesthe following filenames: $MAINPATH = (bg path from exult.cfg) | (si path from exult.cfg) | "ultima7" | "ULTIMA7" | "serpent" | "SERPENT" $STATICPATH = "static" | "STATIC" $USECODENAME = "usecode" | "USECODE" $MAINPATH/$STATICPATH/$USECODE $STATICPATH/$USECODE $USECODE It also searches under: usecode.u7 usecode.si It's a mess, but I'm trying to be thorough. ***** Original ucdump.cc history, credits and stuff. ***** ---------------------------------------------------------------------------------- Ultima 7 usecode dump/disassembly utility Distributed under GPL Maintainer: Maxim S. Shatskih aka Moscow Dragon (maxim__s@mtu-net.ru) History: - originally written June 99 by Maxim S. Shatskih aka Moscow Dragon (maxim__s@mtu-net.ru) Thanks to Keldon Jones (keldon@umr.edu) and Wouter Dijklslag aka Wody Dragon (wody@wody.demon.nl) for their help 11-Oct-99 - added "function search by opcode & intrinsic" feature - added "unknown opcode & intrinsic counting" feature 12-Oct-99 - the good deal of intrinsic functions is now known See source file comments for the description of usecode opcodes & intrinsic functions (the latter one differs between BG & SI) Some general usecode ideas: - usecode functions 0x0-0x3ff are shape handlers - called on double-clicks & other event with appropriate shapes - usecode functions 0x401-0x4ff are NPC handlers - called on double-clicks & other event with appropriate NPCs - NPCID + 0x400 (401 for Iolo, 417 for LB etc). - usecode functions 0x500-0x5ff is for Wisps & guards (nonNPC characters able to talk) (these ranges seems to be hardcoded) - stack machine used to execute bytecodes - the machine's state is: stack local variables(forgotten on function exit, first N of them are call arguments - first pushed is 0, next are 1, 2...) game flags ItemRef (???seems to be valid only for top-level functions-event handlers or maybe is persistent till quitting usecode executuion???) EventID (???seems to be valid only for top-level functions-event handlers or maybe is persistent till quitting usecode executuion???) - game flags are bytes treated as booleans (0/1), persistent across engine shutdown/restart and stored as a simple array (??? 0 or 1 based. Don't remember. Flag 3 means - Tetrahedron is down, flag 4 means - Sphere is down) in GAMEDAT\FLAGINIT. - usecode can also manipulate items & NPCs by means of intrinsic functions - "add" opcode can sum strings (concatenation). Also it can add integer to string - any array operations can be peformed on scalar values. In fact, each scalar value is treated by the array operations as an array with a single element. Vice versa is also true - for instance, ItemsNearItem() function returns an array. Sometimes it is used in enum/next loop as an array, but sometimes it is used as an itemref. - array indices are 1-based as in VB - itemref is a unique ID of the given item. For NPCs, itemref is (-NPCID). For other items, itemrefs seems to be non-persistent (not saved to savegame & re-invented on each engine startup)??? indexes into engine's item lists - there is a value called "referent" which identifies item & stored in U7IBUF Maybe Itemref is the same thing? - -356 is always an Itemref for Avatar. So, Avatar's NPC ID is possibly 356. - usecode execution starts from the event handler function. It is called by the engine without arguments (double-click) in some cases. ItemRef & EventID are set before entering usecode. - the easiest case is double-click on some item. In this case, a usecode event handler function called. Function ID usually matches the shape's Type number or is (NPCID + 0x400) for NPCs. ItemRef is set to the item double-clicked, EventID is set to 1 (double-click). - other causes for the engine to call usecode function: - events scheduled by intrinsic functions 1 & 2 have EventID 2 - item is put on another item - the underlying item's handler is called with EventID 3 (Penumbra's plaque) - usecode Egg - also calls a function with EventID 3 - use item as a weapon (flammable oil) - EventID 4 - NPC being beaten to death (examples: Hook in BG, Dracothaxus in FoV, Pomdirgun & Rotoluncia in SI) - 7 in SI??? - Avatar & NPC approaching to some distance??? - 9 in SI - hex coords to sextant coords - ( x - 933 ) / 10, ( y - 1134 ) / 10 ---------------------------------------------------------------------------------- ***** Original ucdump Intrinsic Function Table Follows. ***** ---------------------------------------------------------------------------------- /* Embedded function table for Black Gate */ const char* bg_func_table[] = { /* Random1(Hi) - Returns a random integer or from 1 to Hi inclusively Used to select a random party member for remarks */ "Random1", /* 0 */ /* Takes itemref + array of several integers. Executes a macro for this itemref Macro opcodes: either 0x35 or 0x45 - deletes an item (fire caused by the flaming oil) 0x46 - sets item's frame number to integer (rotating crossbeam while opening the portcullis gate) 0x52 - the same as ItemSay() function 0x55 - call a usecode event for the item 0x56 - Guardian's phrase with given number All spells use this function - if current weather is 3 - 606 is called instead of the second part of the spell engine (magic negation field at Ambrosia, Armageddon is blocked after shouting 1st mantra & before shouting second). */ "MacroExec", /* 1 */ /* Takes itemref + array of several integers + one more integer The same as above - but schedules a macro for execution later (use a serpent venom on somebody - first raises stats, then - after some time - lower them) Can also shout exclamations - "Call it... Heads... Its tails..." - double-click on money. */ "MacroDelay", /* 2 */ /* SwitchTalkTo(itemref, face_frame) - switches conversation to other NPC, selecting one of possible face pictures Shows the face in the bottom of the screen if the face on top was not hidden yet Switching talk to -277 means - huge reg Guardian semi-transparent face */ "SwitchTalkTo", /* 3 */ /* HideNPC(itemref) - hides NPC face away from the conversation */ "HideNPC", /* 4 */ /* AddAnswer(str_or_array) - adds a answer or set of answers to */ /* the set of talk threads suggested */ "AddAnswer", /* 5 */ /* RemoveAnswer(str) - removes a given string from set of talk threads suggested */ "RemoveAnswer", /* 6 */ /* SaveTalkStartNew() - saves the conversation state & starts */ /* new blank set of talk answers suggested */ "SaveTalkStartNew", /* 7 */ /* RestoreTalk() - restores set of answers suggested */ /* as was saved in SaveTalkStartNew() */ "RestoreTalk", /* 8 */ /* EmptyTalk() - removes all talk answers Looks like the same as "cla" opcode */ "EmptyTalk", /* 9 */ /* GetAnswer() - asks user to select one of the talk threads & returns it Practically the same functionality as "ask" opcode */ "GetAnswer", /* a */ /* GetAnswerIndex() - asks user to select one of the talk threads & returns the 1-based index of it instead the text itself */ "GetAnswerIndex", /* b */ /* AskNumber(min, max, step, default) - asks user a number by showing a slider */ /* with given parameters */ "AskNumber", /* c */ /* SetItemType(itemref, type) - changes a type of given item to the new value */ "SetItemType", /* d */ /* AreItemsNearNPC(NPCID, type, distance) - returns boolean whether there are items of such Type at the given distance from the given NPC. Distance -1 means - screen borders */ "AreItemsNearNPC", /* e */ /* PlaySoundEffect(sound_num) - plays a given effect soundtrack */ "PlaySoundEffect", /* f */ /* Random2(lo, hi) - returns a random integer from lo to hi inclusively */ "Random2", /* 10 */ /* GetItemType(itemref) - returns a "type" value of the item */ "GetItemType", /* 11 */ /* GetItemFrame(itemref) - returns a "frame" value of the item */ "GetItemFrame", /* 12 */ /* SetItemFrame(itemref, frame) - sets a "frame" value for the item */ "SetItemFrame", /* 13 */ /* GetItemQuality(itemref) - returns a "quality" value of the item */ "GetItemQuality", /* 14 */ /* SetItemQuality(itemref, quality) - sets a "quality" value for the item (Penumbra's plaque) Returns old quality??? */ "SetItemQuality", /* 15 */ NULL, /* 16 */ NULL, /* 17 */ /* GetItemCoords(itemref) - parameter is itemref returned by ItemSelectModal(), returns array The array is 2 item's coordinates - array[1], array[2] */ "GetItemCoords", /* 18 */ NULL, /* 19 */ NULL, /* 1a */ /* GetNPCID(itemref) - returns NPCID from Itemref - possibly does-nothing function??? Accepts values like -2 for Spark or -356 for Avatar on input */ "GetNPCID", /* 1b */ /* GetNPCClass(NPCID) - returns a number specifying the NPC class - fighter/sage/shopkeeper etc. Used in exclamations like "Oh my aching back!" 10 seems to be Noble (Finnegan & his aching back :-) ) Or maybe this is GetNPCActivity??? */ "GetNPCClass", /* 1c */ /* SetNPCActivity(NPCID, activity) - sets an NPC activity 11 - Loiter (leave with "go home") 15 - Wait (leave with "wait here") ??? in cheat menu order? */ "SetNPCActivity", /* 1d */ /* JoinNPC(itemref) - joins NPC to the party This seems to only set Party flag on - the same effect as doing this in cheat mode ???in BG, unusual companions (joined by cheat) will not be shown in Inventory/Ztats gumps. Where this information (whether the NPC is a usual companion) is kept? In SI, they will (I saw Rotoluncia's Ztats - though no 2 keys + a wand usually taken from her when dead in inventory. Trying to display Vasculio's Ztats hung the game) - but headless :-) Once more - it is kept somewhere... */ "JoinNPC", /* 1e */ /* DismissNPC(itemref) - dismisses NPC from the party */ "DismissNPC", /* 1f */ /* GetNPCStat(NPCID, property_id) - returns NPC's statistic value (9 is food level, 0 is Strength, 3 is Hits, ) (1 & 4 seems to be Training & Combat???) Vas Mani (Restoration) spell is a good example */ "GetNPCStat", /* 20 */ /* ChangeNPCStat(itemref, property_id, delta) - increments (or decrements for negative delta) NPC's statistic value. */ "ChangeNPCStat", /* 21 */ /* AvatarNPCID() - returns Avatar's NPC ID */ "AvatarNPCID", /* 22 */ /* GetPartyMembers() - returns the array of NPCs which are party members currently */ /* ??? NPC IDs returned??? */ "GetPartyMembers", /* 23 */ /* CreateItem(Type) - creates an item of given Type, returns itemref Must be followed by SetItemFrame()??? */ "CreateItem", /* 24 */ NULL, /* 25 */ NULL, /* 26 */ /* GetNPCName(npc_id_or_array) - returns an NPC name by NPC ID Returns an array of names if array was specified */ "GetNPCName", /* 27 */ /* Counts the amount of party gold if called as Func28(-357, 644, -359, -359) 644 is for sure the Type of gold heap 649 is for sure the Type of serpent venom 839 for hourglass Last parameter seems to be the frame number of the items - -359 means "any" */ "CountNoItems", /* 28 */ /* Returns itemref of the given item in Avatar's (or party's??? - parameter 4???) posessions 0 if no such item Func28(-357, 761, -359, -359) - spellbook. Func28(-357, 839, -359, 0) - Nicodemus's hourglass (known as Hourglass Of Fate in SI). */ "ReturnItemsItemRef", /* 29 */ /* GetContainerItems(container_itemref, type, quality, ???) - returns an array */ /* ??? of itemrefs */ "GetContainerItems", /* 2a */ /* Reduces the amount of party gold if called Func2b(delta, 644, -359, -359, true) Reduces the amount of party eggs if called Func2b(delta, 377, -359, 24, true) */ "ReduceNoItems", /* 2b */ /* Increases the amount of party gold if called Func2c(delta, 644, -359, -359, true) Returns false if party is overloaded & cannot accept this */ "IncreaceNoItems", /* 2c */ /* Not used at all */ NULL, /* 2d */ /* PlayMusic(song#, itemref) - plays a MIDI music track. */ /* Song# = 255 means - mute the MIDI channel. */ "PlayMusic", /* 2e */ /* IsNPCInParty(npc_id) - returns true if given NPC is in party, */ /* otherwise returns false */ "IsNPCInParty", /* 2f */ /* Takes a Type(???), returns an array of all visible items/NPCs of this type */ NULL, /* 30 */ /* IsNPCxxx(itemref) - returns true if given NPC is ????? */ NULL, /* 31 */ /* DisplaySign(gump#, array_of_strings) - displays a sign/plaque */ /* of given gump number & given text (array of strings or single string). */ "DisplaySign", /* 32 */ /* ItemSelectModal() - switches the engine to cross-cursor "use" mode. Returns an itemref of the item selected by user by single-click. Does not return till user will single-click on something. The entity returned can be treated as array with coords at array[2], array[3] */ "ItemSelectModal", /* 33 */ /* Not used at all */ NULL, /* 34 */ /* ItemsNearItem(itemref, type, distance, ???) - returns an array of items of given Type which are closer then Distance to the item specified by Itemref Parameter 4 is possibly frame number to compare??? Type of -1 means - all NPC??? (Fear spell) (Powder keg & cannon ball near the cannon) */ "ItemsNearItem", /* 35 */ /* Takes an NPCID as a single parameter, seems to return the amount of free space in its inventory */ NULL, /* 36 */ NULL, /* 37 */ /* GetTimeHour() - returns hour part of current game time - 0-23 */ "GetTimeHour", /* 38 */ /* GetTimeMinute() - returns minute part of current game time - 0-59 */ "GetTimeMinute", /* 39 */ /* GetItemRef(NPCID) - returns Itemref from NPCID - possibly does-nothing function??? */ "GetItemRef", /* 3a */ NULL, /* 3b */ /* GetNPCxxx(NPCID) - returns the same??? NPC mode as set in function 3d */ NULL, /* 3c */ /* SetNPCxxx(NPCID, mode) - ???sets some NPC mode often called with mode=2 before entering combat ???alignment */ NULL, /* 3d */ /* TeleportItem(itemref, array) - teleports an NPC array[1] - X coord array[2] - Y coord array[3] - height Help spell calls this with (3a8, 47a, 0) array - LB throne room Recall spell calls this with (5aa, 500, 0) array (House of the Dead) - in some cases. Also interesting location - (217, 489, 0) - back from the Sphere. Function 6cf teleports there is Sphere is not destroyed & party does not posesses item 0x347 (the hourglass, maybe parameter 4 in 0x28 checks the Frame number to check whether the hourglass is enchanted??? BTW - there is a known bug in BG that sometimes you can enter the Sphere with non-enchanted hourglass - cause???) What are these locations? */ "TeleportItem", /* 3e */ /* VanishNPC(NPCID) - only parameter is NPCID, no return value Called in eventid 2 for the plaque - never mind what - and NPC -23 (LB) - plaque falling on LB's head Called on Weston (-69) when LB frees him Called on Batlin (GetNPCID(-26)) when he vanishes, feeling the Cube at Avatar's posession Called on -214 in Vesper - when Yvella want to tell Catherine's father & Mara something.... Called on Kreg/Kraig(-245) after he laughs when invis. potion is given to him Called on Addom (-164) after Brion attaches to crystal & completes the orrery viewer Called on -156 (Balayna???) when Rankin says he did not see Balayna for some time Called on all Scara Brae ghosts in For Each loop when Forsythe jumps into the Well The exact logic is not clear - what appears with the vanished NPC? Where it is teleported??? */ "VanishNPC", /* 3f */ /* ItemSay(itemref, str) - displays a string on the screen near the specified item */ "ItemSay", /* 40 */ NULL, /* 41 */ /* GetItemZCoord(itemref) - returns Z coordinate of the item */ "GetItemZCoord", /* 42 */ /* SetItemZCoord(itemref, coord) - sets a Z coordinate for the item */ "SetItemZCoord", /* 43 */ /* GetWeather() - returns current weather - 0-3 3 seems to negate magic */ "GetWeather", /* 44 */ /* SetWeather(weather) - sets new current weather - 0-3 */ "SetWeather", /* 45 */ NULL, /* 46 */ /* SummonCreature(Type, boolean) - engine under Kal Bet Xen (Swarm), Kal Xen (???) an Kal Vas Xen (Summon). Summons a creature of given Type. Second parameter is true only for Kal Vas Xen Return value??? */ "SummonCreature", /* 47 */ /* Shows a map of Britannia. Double-click on the map, Vas Wis (Peer) spell or reading the Brommer's Britannia book */ "ShowMap", /* 48 */ /* KillNPC(itemref) - kills the given NPC. Owen's suicide is this function alone. Plaque falling on LB's head - KillNPC, then VanishNPC. Balayna takes the vial from you & dies - this function alone Death bolt spell uses it too. These are all occurences. */ "KillNPC", /* 49 */ /* Some kind of comparing 2 numbers (2 params) - returns boolean Used to compare somebody' Strength to item's Quality */ "???", /* 4a */ /* SetNPCAttackMode(NPCID, mode) - sets a combat mode for the NPC Mode 7 is Fleeing - others are in men Fear spell, using dirty diapers on people (it is the same as Fear spell) - mode 7 LB attacking in an LB cheat room - mode 0 */ "SetNPCAttackMode", /* 4b */ /* SetTargetNPCToAttack(attacker_NPCID, target_NPCID) - sets target NPC to attack ??? how it is called in a cheat menu? Usually called with Avatar as target NPC */ "SetTargetNPCToAttack", /* 4c */ /* CloneNPC(NPCID) - clones an NPC - Clone spell Returns something - return value never used. */ "CloneNPC", /* 4d */ /* Not used at all */ NULL, /* 4e */ /* ShowCrystalBall(coords_array) - shows a crystal ball view of a given world point */ "ShowCrystalBall", /* 4f */ /* ShowWizardEye(parm1, parm2) - shows a view for telescope or Wizard Eye spell For telescope - ShowWizardEye(10000, 1000) For Wizard Eye spell - ShowWizardEye(45, 200) */ "ShowWizardEye", /* 50 */ /* ResurrectNPC(itemref) - resurrects an NPC. Itemref is a dead body's itemref Returns false is cannot resurrect - LB in this case says "Alas..." and then about burial. ???what is the cause of such LB's behaviour? */ "ResurrectNPC", /* 51 */ /* AddSpellToBook(spellnum, 0, spellbook_itemref) - Adds a new spell to the spellbook Returns false if there was already such spell in the book Maybe calling with 1 (never called such in BG) will remove the spell from the book? */ "AddSpellToBook", /* 52 */ /* ExecuteSprite(sprite, coordx, coordy, speedx, speedy, ???, ???) - executes an explosion-like sprite First parameter is sprite number in SPRITES.VGA speedx & speedy are non zero is the sprite floats away (smoke from smokebomb) Last parameters is usually -1 (not so for smokebomb) */ "ExecuteSprite", /* 53 */ /* Powder keg burst??? */ NULL, /* 54 */ /* DisplayBook(itemref) - Displays book or scroll Text will be displayed further by "say" opcode */ "DisplayBook", /* 55 */ /* StopTime(???) - freezes all NPCs for some time. Parameter is duration???? Type 6be object (Egg???) calls this with its Quality as a parameter on eventid 3 Also called in Stop Time spell with the parameter 100 */ "StopTime", /* 56 */ /* CauseLight(duration) - Glimmer/Light/Great Light spell logic duration is 110 for Glimmer, 500 for Light, 5000 for Great Light */ "CauseLight", /* 57 */ /* itemref as a parameter, returns some boolean... ???NPC is on barge At least true return from this blocks Mark spell - even mantra is not shouted */ "???", /* 58 */ /* CauseEarthquake(???) - causes an earthquake. Parameter is 40 for Armageddon spell & variable for Tremor spell Also called from func 85e (Forsythe jumping in the Well of Souls) - with parameter 15 */ "CauseEarthquake", /* 59 */ /* IsPlayerFemale() - returns 0 if male, 1 if female */ "IsPlayerFemale", /* 5a */ /* CauseArmageddon() - all logic of Armageddon spell except shouting mantras, weather change, earthquake, & setting the game flag which affects Batlin's & LB's behaviour. Walks through the all NPC list & makes all of the Dead with Hits < 0 Called also in LB's cheat room - "Busted, you thieving...." */ "CauseArmageddon", /* 5b */ /* Sets NPC to some state - like VanishNPC() or KillNPC() */ "???", /* 5c */ /* CauseBlackout() - darken the whole screen for some time */ "CauseBlackout", /* 5d */ /* ArraySize(a) - returns number of elements in the array */ "ArraySize", /* 5e */ /* Something for Mark spell??? */ "???", /* 5f */ /* Called only once, something in a Recall spell Called after setting activity to 31 (Follow Avatar) to all party members and resetting flag 0x39 (what is it???) No return value, single parameter which is itemref */ NULL, /* 60 */ /* Called only once, parameters are NPC strength, 0, 12, 3 Return value exists but not used */ NULL, /* 61 */ /* IsUnderTheRoof() - returns true if the party is under the roof. Sextant (twill) will not work under the roof. Also used in some place (???) where it causes a shout "Try it outside!" */ "IsUnderTheRoof", /* 62 */ /* SetOrreryState(coords_array, status) - sets the state of the planets in Brion's orrery. Coords are usually ordinary orrery coords - array of 2 integers. (59c, b4c) status is a small integer which influences the state of the planets. */ "SetOrreryState", /* 63 */ /* Not used at all */ NULL, /* 64 */ NULL, /* 65 */ NULL, /* 66 */ NULL, /* 67 */ NULL, /* 68 */ /* Function 0x69 - GetSpeechTrack() Returns a speech track number previously set by SetSpeech() */ "GetSpeechTrack", /* 69 */ NULL, /* 60 */ NULL, /* 6a */ NULL, /* 6b */ NULL, /* 6c */ NULL, /* 6d */ NULL, /* 6e */ /* Function 0x6f - DeleteItem(itemref) Deletes an item */ "DeleteItem", /* 6f */ /* Function 0x75 - SetSpeech(speech_number) Remembers a speech track number, returns false if speech effects are disabled or no sound card */ /* Function 0x75 - StartEndGame(boolean). TRUE is successful endgame (wand against the gate), FALSE is unsuccessful (passing through the gate) */ /* Function 0x76 - FireCannon(cannon_itemref, fire_direction, ball_type, ???, cannon_type, cannon_type). Fires a cannon in specified direction */ /* Function 0x7e - PlaySpeech() Plays a speech track set by SetSpeech() */ /* Function 0x88 - GetNPCFlag(Itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Flag 25 causes people to say "Oink!" Returns boolean Or maybe not only NPC flag? - see the very first function on sails & gangplanks... ??? Suggestion. Flagno 10 is "on barge" flag which is set when the NPC is unmovable and mouse controls barge itself (sitting on ship/carpet/cart). A reasonable one. Needs checking. */ /* Function 0x89 - SetNPCFlag(itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Sets flag to true */ /* Function 0x8a - ResetNPCFlag(itemref, flagno). Flagno 1 is Slept Flagno 8 is Poisoned Sets flag to false */ }; ---------------------------------------------------------------------------------- ***** Opcode Table from ucdump.cc Follows. ***** ---------------------------------------------------------------------------------- /* Opcode table - common to BG & SI */ const opcode_desc opcode_table[] = { { NULL, 0, 0 }, /* 00 */ { NULL, 0, 0 }, /* 01 */ /* Next iteration of For Each-style loop Operands are 1,2, , , is set to next value from Jumps to if array ended ??? what are 1,2? Are they used? */ { "next", 10, EFF_RELATIVE_JUMP }, /* 02 */ { NULL, 0, 0 }, /* 03 */ /* Asks user to select one the talk answers Jumps where specified if no answer available */ { "ask", 2, EFF_RELATIVE_JUMP }, /* 04 */ /* Pops a value from the top of stack, jump if false, zero or empty array */ { "jne", 2, EFF_RELATIVE_JUMP }, /* 05 */ /* jump */ { "jmp", 2, EFF_RELATIVE_JUMP }, /* 06 */ /* Pops the top-of-stack string & jumps if the string is NOT the last talk answer ??? first operand seems to be always 1 */ { "jmpa", 4, EFF_RELATIVE_JUMP }, /* 07 */ { NULL, 0, 0 }, /* 08 */ /* Adds two values on the stack, popping them & pushing result Can be used to add integer to string - in this case integer is converted to string and 2 strings are concatenated */ { "add", 0, EFF_BIMATH }, /* 09 */ /* Decrements second value of the stack by first value, popping them & pushing result */ { "sub", 0, EFF_BIMATH }, /* 0a */ /* Divides second value of the stack by first value, popping them & pushing result */ { "div", 0, EFF_BIMATH }, /* 0b */ /* Multiplies two values on the stack, popping them & pushing result */ { "mul", 0, EFF_BIMATH }, /* 0c */ /* Divides second value of the stack by first value, popping them & pushing reminder */ { "mod", 0, EFF_BIMATH }, /* 0d */ /* Boolean AND on two values on stack, popping them & pushing result Top-of-stack variable is the left one in case of string addition */ { "and", 0, EFF_BIMATH }, /* 0e */ /* Boolean OR on two values on stack, popping them & pushing result */ { "or", 0, EFF_BIMATH }, /* 0f */ /* Inverts a boolean value on top of stack */ { "not", 0, EFF_UNIMATH }, /* 10 */ { NULL, 0, 0 }, /* 11 */ /* Pops a stack value to given local variable */ { "pop", 2, EFF_POP }, /* 12 */ /* Pushes a TRUE boolean value on the stack */ { "push\ttrue", 0, EFF_PUSH }, /* 13 */ /* Pushes a FALSE boolean value on the stack */ { "push\tfalse", 0, EFF_PUSH }, /* 14 */ { NULL, 0, 0 }, /* 15 */ /* Pops 2 values from the stack, pushes boolean value - TRUE if second value "?" then first (where "?" can be greater, greater or equal etc...) */ { "cmpgt", 0, EFF_CMP }, /* 16 */ { "cmplt", 0, EFF_CMP }, /* 17 */ { "cmpge", 0, EFF_CMP }, /* 18 */ { "cmple", 0, EFF_CMP }, /* 19 */ { "cmpne", 0, EFF_CMP }, /* 1a */ { NULL, 0, 0 }, /* 1b */ /* Adds a string from data segment to string register current contents */ { "addsi", 2, EFF_STUPIDEFF }, /* 1c */ /* Pushes a string value given by 16bit string offset in data segment to stack */ { "pushs", 2, EFF_STUPIDEFF }, /* 1d */ /* Pops specified number of values from stack, builds an array from them & pushes it on the stack Pushes the empty array to top of the stack if operand is 0 */ { "arrc", 2, EFF_STUPIDEFF }, /* 1e */ /* Pushes immediate 16bit integer to stack */ { "pushi", 2, EFF_PUSH }, /* 1f */ { NULL, 0, 0 }, /* 20 */ /* Pushes a local variable on stack */ { "push", 2, EFF_PUSH }, /* 21 */ /* Compares 2 values on the stack, pops them & pushes TRUE if they are equal */ { "cmpeq", 0, EFF_CMP }, /* 22 */ { NULL, 0, 0 }, /* 23 */ /* Calls a usecode function - function number is 0-based index to externs array */ { "call", 2, EFF_SINGLELINE }, /* 24 */ /* Return from function without result returned on the stack */ { "ret", 0, EFF_SINGLELINE }, /* 25 */ /* Uses the top-of-stack value to index (1-based) the array variable, pops index & pushes result - the value from the array */ { "aget", 2, EFF_SINGLELINE }, /* 26 */ { NULL, 0, 0 }, /* 27 */ { NULL, 0, 0 }, /* 28 */ { NULL, 0, 0 }, /* 29 */ { NULL, 0, 0 }, /* 2a */ { NULL, 0, 0 }, /* 2b */ /* ??? Looks like to be the same as "exit" ??? Suggestion: maybe "exit" is for functions, while "exit2" is for event handlers? */ { "exit2", 0, EFF_EXIT | EFF_SINGLELINE }, /* 2c */ /* Pop the top-of-stack value & sets it as a return value */ { "popr", 0, EFF_STUPIDEFF }, /* 2d */ /* Opens a new For Each-style enumeration loop. Always followed by "next" opcode??? */ { "enum", 0, 0 }, /* 2e */ /* Adds local variable's string value to string register current contents */ { "addsv", 2, EFF_STUPIDEFF }, /* 2f */ /* If (top-of-stack - 1) value is in top-of-stack array, pushes true, otherwise pushes false - after popping array & value */ { "in", 0, EFF_STUPIDEFF }, /* 30 */ /* Something strange with 2 varrefs (???) as operands Appears in BG only - in talk to Raymundo in the Theatre - trying to sing a song I -am- the Avatar (function: 08D1H) */ { "???", 4, 0 }, /* 31 */ /* Return with a result returned on the stack */ { "retr", 0, EFF_STUPIDEFF }, /* 32 */ /* Displays the string register value (to current talk, sign, scroll or book), string register emptied */ { "say", 0, EFF_STUPIDEFF }, /* 33 */ { NULL, 0, 0 }, /* 34 */ { NULL, 0, 0 }, /* 35 */ { NULL, 0, 0 }, /* 36 */ { NULL, 0, 0 }, /* 37 */ /* Calls engine's intrinsic function with specified number of parameters (popping them). The return value remains on stack */ { "callis", 3, EFF_STUPIDEFF }, /* 38 */ /* Calls engine's intrinsic function with specified number of parameters (popping them). No return value */ { "calli", 3, EFF_SINGLELINE }, /* 39 */ { NULL, 0, 0 }, /* 3a */ { NULL, 0, 0 }, /* 3b */ { NULL, 0, 0 }, /* 3c */ { NULL, 0, 0 }, /* 3d */ /* Pushes identifier of the item ( for which the usecode event handler is called ) on the stack */ { "push\titemref", 0, EFF_PUSH }, /* 3e */ /* Aborts the function & all usecode execution, returning to the engine */ { "exit", 0, EFF_SINGLELINE }, /* 3f */ /* Removes all answers from the current talk */ { "cla", 0, 0 }, /* 40 */ { NULL, 0, 0 }, /* 41 */ /* Pushes game flag's value (boolean) on the stack */ { "pushf", 2, EFF_PUSH }, /* 42 */ /* Pops the stack value to the game flag (boolean) */ { "popf", 2, EFF_POP }, /* 43 */ /* Pushes an immediate byte to the stack */ { "pushbi", 1, EFF_PUSH }, /* 44 */ { NULL, 0, 0 }, /* 45 */ /* Uses the top-of-stack value to index (1-based) the array variable, (top-of-stack - 1) as the new value, and updates a value in the array slot (local variable specified in the operand) */ { "aput", 2, EFF_ARRAY | EFF_SINGLELINE }, /* 46 */ /* Call of usecode function - function # is the operand ???Suggestion: functions are divided into event handlers (called by external code and the usecode) and functions (called by usecode only). "calle" is used to call the event handler from the usecode, while "call" is used to call a function */ { "calle", 2, 0 }, /* 47 */ /* Pushes the cause of usecode event handler call on the stack */ /* (double-click on item is be 1, NPC death seems to be 7 in SI and 2 in BG ) */ { "push\teventid", 0, EFF_PUSH }, /* 48 */ { NULL, 0, 0 }, /* 49 */ /* Pops the value from the stack and adds it to array on the top of stack */ /* or pops both values from the stack, builds an array from them */ /* & pushes it on the stack if neither of them are arrays */ { "arra", 0, EFF_STUPIDEFF }, /* 4a */ /* Pops the top-of-stack value & sets the cause of usecode event handler to it (double-click on item is be 1, NPC death seems to be 7 in SI and 2 in BG ) Used to call event handlers from the usecode */ { "pop\teventid", 0, 0 }, /* 4b */ }; ---------------------------------------------------------------------------------- exult-1.2/usecode/ucxt/Docs/Makefile.am0000644000175000001440000000010007403432424013521 EXTRA_DIST = \ flags_pre.txt \ newopcodes.txt \ ucxtread.txt exult-1.2/usecode/ucxt/Docs/Makefile.in0000644000175000001440000001357610061527065013557 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ EXTRA_DIST = \ flags_pre.txt \ newopcodes.txt \ ucxtread.txt subdir = usecode/ucxt/Docs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DIST_COMMON = Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/ucxt/Docs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/ucxt/Docs/flags_pre.txt0000644000175000001440000035755607225441751014233 Ultima 7 usecode disassembler v0.6.1 Functions: 0 Function not found. Number of flags found: 2420 Function: 009b flag offset push 0197 0055 push 0197 0091 push 0197 00ef push 0197 01a5 push 0198 0036 push 0199 0257 pop 0199 026a push 01a3 006e push 01b3 002a push 01c3 0043 pop 01c3 004f Function: 0124 flag offset push 02e7 00e4 pop 02e7 00ef Function: 0133 flag offset pop 01d0 02ad Function: 01df flag offset push 013c 0040 pop 013c 004c push 0154 0027 Function: 0269 flag offset push 0000 00ef push 0001 0115 push 0001 022a push 0001 0238 push 0002 014d push 0002 038b push 0003 0102 push 0003 0184 push 0003 0309 push 0003 0371 push 0004 0028 push 0004 0128 push 0004 02ce push 0004 036e push 0005 0056 push 0005 013e push 0005 0160 pop 0007 0349 pop 0008 03a9 push 0012 002b pop 0012 004c push 0012 013b push 0013 0059 pop 0013 006e pop 01d2 02af push 01d3 00ad push 01d3 00e2 pop 01d3 025f push 01d4 0088 pop 01d4 00a1 push 0211 0173 Function: 0281 flag offset pop 003e 0093 Function: 0282 flag offset pop 0126 0132 pop 0159 0146 pop 0233 0154 Function: 02d9 flag offset push 0157 0037 Function: 02eb flag offset pop 01af 0093 Function: 02f0 flag offset pop 01a7 0034 Function: 02f2 flag offset pop 01aa 00da push 01af 0025 Function: 0311 flag offset push 0004 0008 push 0057 001b Function: 031d flag offset push 012b 00a0 pop 023f 014e Function: 0326 flag offset push 003d 002f push 003d 0084 pop 0042 00c4 Function: 0329 flag offset pop 001f 009c pop 0020 00a0 pop 0021 00a4 Function: 0347 flag offset push 0004 001a Function: 0378 flag offset push 0197 006c Function: 0401 flag offset pop 0014 0001 push 003b 0030 push 003b 0173 push 003b 0222 pop 003b 023f push 003c 0313 push 003c 032f push 003d 03ca push 003f 02f9 push 0057 02c8 push 0057 0316 push 005c 0034 pop 005c 0165 push 0065 03fc push 02ea 029c pop 02ea 02c4 Function: 0402 flag offset push 0015 0038 push 0015 008b pop 0015 0125 push 003e 0155 push 003e 0189 push 003e 025a push 003e 0584 pop 003f 04f9 push 0043 0204 push 0043 0314 pop 0043 032b push 0046 006d pop 0046 00c2 push 0047 0079 pop 0047 00d3 push 0048 0148 push 0049 0173 pop 0049 03c5 push 0064 018c pop 0064 0656 Function: 0403 flag offset push 0003 0444 push 0004 0423 push 0016 00a9 pop 0016 00b5 push 0017 0333 pop 006b 0489 push 006c 044b pop 006c 0457 push 006d 006c push 006e 0079 push 0098 021c push 00d5 00e7 pop 00d5 0411 push 00d9 014e pop 00d9 0178 push 02ec 0040 pop 02ec 0068 Function: 0404 flag offset push 0006 0100 push 0017 011a pop 0017 0126 push 016a 030b push 016a 035c push 016d 01af pop 016d 023b pop 016d 029d pop 016d 02b0 push 0186 03a4 push 0186 03cc push 02eb 0012 pop 02eb 003a Function: 0405 flag offset push 0003 023b push 0018 0052 push 0018 0081 pop 0018 008d push 0028 0074 pop 0028 00e1 push 0029 010a push 00e4 0061 push 00e4 00b3 push 00ef 0067 pop 00ef 00c1 Function: 0406 flag offset push 0019 0093 pop 0019 00d5 pop 0019 0117 push 00e2 016b pop 0129 0368 push 0132 015d push 0132 017b pop 0132 0392 push 0136 007b pop 0136 00bf pop 0136 00f9 push 0137 0087 pop 0137 00cd pop 0137 010d push 0138 012b push 013c 009a pop 013c 00d1 push 0151 0178 push 0154 0052 push 0155 013c push 0156 012e push 0156 0142 pop 0156 030f push 0158 0136 Function: 0407 flag offset push 001a 0066 pop 001a 0072 pop 00db 0147 pop 00db 0194 pop 00db 01bb push 00db 0210 Function: 0408 flag offset push 001b 0087 pop 001b 0093 push 00f7 0284 pop 00fd 0303 push 0101 007a push 0101 0159 pop 0101 01d5 pop 0101 01fa pop 0108 016b pop 0108 01d9 pop 0108 01fe push 010b 0048 push 011f 00c7 pop 011f 00fe push 0121 005b pop 0121 045f Function: 0409 flag offset push 001c 0092 pop 001c 009e push 017d 0078 push 0180 0085 pop 0180 0328 push 018d 006b Function: 040a flag offset push 001d 0133 push 001d 01d4 push 001d 0207 push 001d 0235 pop 001d 029e push 001d 02e8 push 001d 0337 push 001d 0436 push 001d 04a3 push 001d 0a0b push 0152 08ff pop 0152 0915 push 0153 0724 push 0153 07e6 pop 0153 0801 push 015d 0137 push 015d 01b8 pop 015d 037f push 015e 0127 pop 015f 01e3 push 015f 01fc pop 015f 02c0 push 015f 02c7 push 015f 049f push 0161 0269 pop 0161 0287 push 0161 02ab push 0161 0388 push 0161 09c3 push 0161 0a16 pop 0161 0a53 push 0162 01e6 push 0162 02f5 push 0162 09cd pop 0162 09dd Function: 040b flag offset push 0014 0036 push 003c 00a5 push 003c 00d1 push 003f 00b8 push 004b 005d pop 004b 007f pop 004b 0094 push 0057 0112 Function: 040c flag offset push 003c 005d push 003d 025c push 003d 0334 push 003d 0497 pop 003d 04b8 push 003f 0246 push 0042 0259 pop 0042 04e1 push 0044 026e pop 0044 0322 push 0044 03d0 push 0044 0494 push 0045 026b pop 0045 031e push 0048 0033 pop 0048 0093 push 004c 011f pop 004c 013e push 0059 00ce pop 0059 00e3 pop 0059 021b push 005a 002e push 005b 0239 pop 005b 035e push 005d 03dd pop 005d 03f5 Function: 040d flag offset push 003d 002d push 003d 01ad push 003f 003a pop 0040 013b push 0043 006e push 004d 007b pop 004d 0087 Function: 040e flag offset push 003c 005f push 003d 0052 push 003d 016c push 003f 006c push 0040 0082 pop 0042 01af push 004e 008f pop 004e 009b Function: 040f flag offset push 02c4 0022 pop 02c4 002e pop 02db 00a5 push 02dc 0038 push 02dd 003b push 02dd 0078 push 02dd 00dc pop 02dd 0187 push 02de 016a Function: 0410 flag offset push 0006 011f push 003e 0072 push 003f 004e push 0040 0088 pop 0041 01d5 push 0043 0065 push 004f 009f pop 004f 00ab Function: 0411 flag offset push 003f 0035 push 0052 0048 pop 0052 0054 Function: 0412 flag offset push 0053 0074 pop 0053 00b6 Function: 0413 flag offset push 0051 006a pop 0051 0076 Function: 0414 flag offset push 0054 003a pop 0054 0046 Function: 0415 flag offset push 003f 0046 push 0040 0039 push 0043 0053 push 0055 0066 pop 0055 0072 push 0058 01ec pop 0058 025d Function: 0416 flag offset push 0056 0054 pop 0056 0060 Function: 0417 flag offset push 0003 051f push 001e 000e push 0040 031f push 0043 0312 pop 0065 0577 push 0066 0180 pop 0066 04eb push 0098 00b5 pop 0098 00c1 push 0099 0526 push 0099 059a push 00cc 007f pop 00cc 0653 push 00cd 007c pop 00d1 02fc push 00d3 008e push 00d3 0144 pop 00d3 0153 push 00d4 00a8 pop 00d4 05cb push 00dd 006e pop 00dd 0214 push 0127 009b Function: 0418 flag offset push 0003 0035 push 0003 0052 push 0003 0073 push 0003 009a push 0003 013e push 0003 0166 push 0099 0023 pop 0099 002f Function: 0419 flag offset push 006f 0080 pop 0073 00da push 0073 025c push 009a 0012 pop 009a 001e Function: 041a flag offset pop 0006 00b6 push 0006 016c push 0006 0240 push 0006 0257 push 0006 03ed push 000a 0212 push 001e 0057 push 0038 0066 push 0038 0079 push 0041 0159 pop 0087 03a0 pop 0088 03d1 push 008a 020c push 008b 0221 push 008c 020f push 008d 0135 push 008d 01de push 008e 01be pop 008e 051f push 008f 0421 pop 008f 045f pop 0090 00ca push 0090 01f1 pop 0090 05f1 pop 0091 00b2 push 0091 0138 push 0091 01eb push 0094 01ff push 0096 0166 push 0096 03fa push 0096 0620 push 0097 01d1 push 0097 03fd push 009b 022e pop 009b 023a push 00d6 017d push 00d7 017a push 00d7 041e pop 00da 0048 push 0102 01a4 push 0105 0394 push 0105 03a3 push 0109 0180 push 0109 0190 push 011e 01b1 push 011e 04cc push 016b 03a6 push 016b 03b5 push 016b 03c1 push 0217 03b2 push 0284 03c4 push 0284 03d4 Function: 041b flag offset pop 0067 0108 push 0068 0037 push 0069 0044 push 009c 0057 pop 009c 0063 Function: 041c flag offset push 009d 003c pop 009d 0052 Function: 041d flag offset push 009e 0022 pop 009e 002e Function: 041e flag offset push 006b 0032 pop 006d 0170 pop 006e 0174 push 009f 0043 pop 009f 004f Function: 041f flag offset push 00a0 002b pop 00a0 0037 Function: 0420 flag offset push 00a1 0022 pop 00a1 002e Function: 0421 flag offset push 00a2 002b pop 00a2 0037 Function: 0422 flag offset pop 0082 0226 push 00a3 0077 pop 00a3 0083 push 00da 0052 Function: 0423 flag offset push 00a4 0033 pop 00a4 0043 Function: 0424 flag offset push 00a5 0037 pop 00a5 0043 Function: 0425 flag offset push 0083 0039 pop 0083 00aa push 0084 0045 pop 0084 00d4 pop 0084 010d push 00a6 007b pop 00a6 0117 Function: 0426 flag offset push 00a7 0044 pop 00a7 0050 Function: 0427 flag offset push 00a8 004f pop 00a8 005b Function: 0428 flag offset pop 0081 0132 push 00a9 004f pop 00a9 005b Function: 0429 flag offset pop 0080 0226 pop 008c 0216 push 00aa 0077 pop 00aa 0087 push 00da 0052 Function: 042a flag offset pop 0092 02e6 push 00ab 0049 pop 00ab 0055 push 00af 003c push 00dc 002f pop 00dc 0102 Function: 042b flag offset push 0006 0183 pop 007f 0174 push 0080 0062 push 0081 0209 push 0082 01d6 push 00ac 007c pop 00ac 008c push 00d1 006f push 00da 003d Function: 042c flag offset push 007a 004d push 007a 01cd push 0089 005a push 0089 01ec push 00ad 0067 pop 00ad 0073 Function: 042d flag offset push 0094 007c push 0094 0163 push 00ae 0089 pop 00ae 0095 push 00c6 006f push 00da 004a Function: 042e flag offset push 0092 003d push 00af 004a pop 00af 0056 Function: 042f flag offset push 007b 0037 pop 007d 0139 pop 007e 01ad pop 0085 0170 push 00b0 0044 pop 00b0 0050 Function: 0430 flag offset push 02c5 0022 pop 02c5 002e push 02dc 0038 push 02de 003e push 02de 007a push 02de 00a8 pop 02de 01ef pop 02de 01fa Function: 0431 flag offset push 0003 008b push 00b2 0037 pop 00b2 0043 Function: 0432 flag offset push 00b3 003d pop 00b3 0049 Function: 0433 flag offset push 00b4 003d pop 00b4 0049 Function: 0434 flag offset push 0085 004c push 00b5 00a1 pop 00b5 00ad push 00cb 0059 pop 00cb 031c Function: 0435 flag offset push 0067 00ff pop 0068 0178 push 00b5 007d push 00b6 008a pop 00b6 0096 push 00da 0058 Function: 0436 flag offset push 00b7 00e8 pop 00b7 013b Function: 0437 flag offset push 00b8 007d pop 00b8 0089 push 00da 0052 Function: 0438 flag offset push 00b9 0043 pop 00b9 004f Function: 0439 flag offset push 0040 0047 push 004a 0044 push 0086 0229 pop 0086 0235 push 00ba 0055 pop 00ba 0061 push 00d2 013a pop 00d2 0196 Function: 043a flag offset push 00bb 007d pop 00bb 0089 push 00da 0058 Function: 043b flag offset push 00bc 0084 pop 00bc 0090 push 00da 005f Function: 043c flag offset push 00bd 003c pop 00bd 0048 push 00ce 002f pop 00ce 01c4 push 00ce 0223 Function: 043d flag offset push 0093 0028 push 0093 010c pop 0093 0118 push 0095 0158 pop 0095 028c push 00be 0042 pop 00be 004e push 00cf 0035 pop 00cf 02b3 Function: 043e flag offset push 00bf 0028 pop 00bf 0034 Function: 043f flag offset pop 008a 0171 pop 008b 015a push 00c0 007c pop 00c0 0088 push 00da 004a push 0141 006f Function: 0440 flag offset push 0003 00fb push 0099 0028 push 00c1 0035 pop 00c1 0041 Function: 0441 flag offset push 00c2 002b pop 00c2 0037 Function: 0442 flag offset push 00c3 002e pop 00c3 0040 Function: 0443 flag offset pop 0071 00da push 0072 0022 pop 0072 010d push 00c4 0031 pop 00c4 003d Function: 0444 flag offset push 0071 0028 push 00c5 0043 pop 00c5 004f push 00d8 00c9 pop 00d8 00dd Function: 0445 flag offset pop 0094 013a push 00c6 0039 pop 00c6 0045 pop 00cd 030f Function: 0446 flag offset pop 0069 014c pop 006a 01e0 push 00c7 003c pop 00c7 004c push 00de 002f push 00de 021b Function: 0447 flag offset push 00c8 0022 pop 00c8 0032 Function: 0448 flag offset pop 0075 0150 pop 0076 0139 push 0077 0036 pop 0077 0184 push 0078 001e pop 0078 006a push 0078 0078 push 0079 002a pop 0079 0075 push 0079 0084 pop 007a 0190 push 00c9 0041 pop 00c9 0091 Function: 0449 flag offset push 0076 0022 push 007a 011a pop 007b 00ce pop 007c 0117 push 007d 002f push 007e 003c pop 0089 014c push 00ca 0049 pop 00ca 0055 Function: 044a flag offset push 0003 0048 push 0003 0078 push 0003 00a9 push 0003 01b7 push 0004 0143 push 0065 0023 push 00e7 0036 pop 00e7 0042 Function: 044b flag offset push 00e0 0063 push 00e0 0168 pop 00e1 01ca push 00e2 0069 pop 00e2 022b push 00e6 0097 push 00e6 0261 push 00e6 026f push 00e6 0282 pop 00e6 02bc push 00e8 00a4 pop 00e8 00c1 push 0129 0083 Function: 044c flag offset push 00e4 0037 push 00e4 0099 push 00e9 004a pop 00e9 0064 push 00ee 003d pop 00ee 00a7 pop 00ee 0153 Function: 044d flag offset push 006a 0036 push 00de 0210 pop 00de 0237 push 00e0 0029 push 00e0 01d0 pop 00e3 01dc pop 00e4 0148 push 00ea 0049 pop 00ea 0059 Function: 044e flag offset push 00e4 0030 push 00e4 006f push 00eb 0043 pop 00eb 004f push 00f0 0036 pop 00f0 007d Function: 044f flag offset push 00e4 0030 push 00e4 006f push 00ec 0043 pop 00ec 004f push 00f1 0036 pop 00f1 007d Function: 0450 flag offset push 00e3 0022 push 00e3 008f push 00e4 002f push 00e4 0072 push 00ed 0042 pop 00ed 0052 push 00f2 0035 pop 00f2 0080 Function: 0451 flag offset push 0006 0136 push 0040 01b9 push 0043 01c6 push 0087 0074 push 008f 0115 push 0096 00f2 push 00f7 0169 push 00f7 0381 push 0102 011b pop 0102 02be pop 0102 034a pop 0105 03d4 push 0109 0118 pop 0109 028b pop 0109 030d push 010c 00ae pop 010c 00ba push 011e 011e pop 011e 02d5 pop 011e 035b push 011f 00e8 pop 011f 0157 push 0125 00a1 push 0217 03c8 Function: 0452 flag offset push 00f7 01d2 push 010d 009e pop 010d 00aa push 011f 00d2 pop 011f 00f7 Function: 0453 flag offset push 0006 0123 push 0006 014d push 0006 015d push 00fe 002a push 00ff 0040 push 010e 004d pop 010e 0059 Function: 0454 flag offset push 010f 0029 pop 010f 0035 push 011b 010b Function: 0455 flag offset push 00f7 0165 push 0110 002f pop 0110 003b push 011f 0069 pop 011f 008b Function: 0456 flag offset pop 00fe 016a push 0111 0018 pop 0111 0024 push 011f 0062 pop 011f 0084 push 0122 00d5 pop 0125 0120 Function: 0457 flag offset pop 0106 028e push 0112 005f pop 0112 006b push 011f 0093 pop 011f 00b2 Function: 0458 flag offset push 00ff 0143 pop 00ff 0163 push 0113 0036 pop 0113 0042 push 011f 0076 pop 011f 009b Function: 0459 flag offset push 00f7 020b push 00f8 003a push 00f8 0077 pop 010b 01ae push 0114 004e pop 0114 005a pop 0120 01e5 push 0124 0034 pop 0124 0074 Function: 045a flag offset push 0040 0089 push 0040 0130 push 00f7 00b3 push 00f7 0115 push 00f7 01f0 push 00f7 0396 push 00f7 046e push 00f7 04b2 push 00f7 04d3 push 00f7 0586 push 00f9 0529 pop 00f9 0535 push 00fa 0554 pop 00fa 0560 push 00fb 00a6 pop 00fb 0222 push 00fb 03b0 push 00fc 03a5 pop 00fc 03d5 push 0115 00c0 pop 0115 00cc push 011f 010f pop 011f 0167 push 0122 042f push 0123 008f pop 0123 00fa Function: 045b flag offset push 00f7 0128 pop 00f7 0296 push 00fd 007b push 0116 0088 pop 0116 009c push 011f 00c4 pop 011f 00e3 Function: 045c flag offset push 0040 004a push 0043 0057 pop 0104 029b push 0117 0064 pop 0117 0070 push 011f 003d push 011f 009e pop 011f 0103 Function: 045d flag offset push 010a 0113 pop 010a 011f push 0118 007b pop 0118 0087 push 011f 00b5 pop 011f 00d4 Function: 045e flag offset push 00f4 0040 push 00f5 004d pop 00f6 013c push 0119 005a pop 0119 0066 push 011f 008e pop 011f 00b6 Function: 045f flag offset pop 00f4 0245 push 00f6 003d pop 00f8 022e push 011a 004a pop 011a 0056 push 011f 0085 pop 011f 00a4 Function: 0460 flag offset push 011b 004c pop 011b 0058 push 01d2 003f Function: 0461 flag offset push 0107 0059 push 011c 0066 pop 011c 0072 Function: 0462 flag offset push 0130 0110 pop 0130 0177 push 0131 007d push 0132 0070 push 0132 00b5 push 0132 010a push 0138 01bb push 013c 0047 pop 013c 0053 push 013d 0040 pop 013d 0057 pop 013d 0062 push 0154 0027 pop 0155 0216 push 0158 0080 pop 0158 01c9 Function: 0463 flag offset pop 0107 0081 push 011d 0021 pop 011d 002d Function: 0464 flag offset push 012e 009e pop 012e 00cb pop 012e 012b push 013c 0047 pop 013c 0053 push 013e 0040 pop 013e 0057 pop 013e 0062 push 0154 0027 Function: 0465 flag offset push 012a 024a pop 012a 0274 push 012b 006c push 012b 01ff push 0130 01f9 push 0131 00ab pop 0131 0239 push 013c 0047 pop 013c 0053 push 013f 0040 pop 013f 0057 pop 013f 0062 pop 0151 00b7 push 0154 0027 Function: 0466 flag offset push 0003 0079 push 0003 009c push 0003 00bd push 0003 00f1 push 0003 0156 push 0003 01eb push 0003 0259 push 0003 026e push 0003 028f push 0003 02fa push 012d 0241 pop 012d 02d4 push 0140 0067 pop 0140 0073 push 01d2 0043 push 0211 0059 push 0211 024e Function: 0467 flag offset push 0141 004f pop 0141 005b Function: 0468 flag offset push 0142 0028 pop 0142 0034 push 014d 0076 Function: 0469 flag offset push 0143 0028 pop 0143 0034 Function: 046a flag offset push 0144 002e pop 0144 003a Function: 046b flag offset push 0003 0212 push 0003 0242 push 02cf 0025 pop 02cf 0031 pop 02d5 0106 push 02d5 0229 push 02d5 02bf pop 02d6 00ee push 02d6 021f push 02d6 02b4 push 02db 004b Function: 046c flag offset push 0128 0084 push 0128 0098 push 0128 01ca pop 0128 01eb pop 0139 02df push 0139 031b push 0139 0436 pop 0139 0447 pop 013a 0312 push 013a 0315 pop 013a 03e8 pop 013a 044f push 013b 00f1 push 0146 0052 pop 0146 005e push 015a 0161 pop 015a 0186 push 0163 00a5 pop 0163 00d9 Function: 046d flag offset push 014c 018a push 02ca 0028 pop 02ca 0034 Function: 046e flag offset push 0000 0180 push 0003 0037 push 0003 007b push 0003 00a3 push 0003 00d7 push 0003 010f push 0003 0167 push 02ca 0023 push 02ce 0030 pop 02ce 0043 pop 02ce 004e Function: 046f flag offset push 0149 002e Function: 0470 flag offset push 0043 01a4 pop 0135 01c5 push 014a 003e pop 014a 004a Function: 0471 flag offset push 014b 0035 pop 014b 0041 Function: 0472 flag offset push 0128 0159 push 0148 00ad push 014c 003d pop 014c 0049 push 015a 002c push 015a 0072 push 015b 002f pop 015b 006f push 015c 015c pop 015c 017d Function: 0473 flag offset push 0142 00ba push 014d 0044 pop 014d 0050 push 01de 0060 push 01de 0089 Function: 0474 flag offset push 012a 0085 pop 012b 01d5 push 014e 0028 pop 014e 0034 Function: 0475 flag offset push 012c 003e push 014f 0028 pop 014f 0034 Function: 0476 flag offset push 0208 0033 pop 0208 003f Function: 0477 flag offset push 016a 00a7 pop 016c 01f4 push 016c 0205 push 016c 0273 push 016c 02bb push 0171 0047 pop 0171 0053 Function: 0478 flag offset push 0088 015c pop 016b 0168 push 0170 003c push 0172 0049 pop 0172 0055 push 0217 002f Function: 0479 flag offset push 0167 004a push 0167 017f pop 0167 023c pop 0167 0257 push 0168 0050 pop 0168 02c4 push 0170 0231 push 0170 0265 push 0173 005e pop 0173 006a pop 017b 0240 pop 017b 0253 push 0186 003d push 0186 016a Function: 047a flag offset push 0165 00bb pop 0165 0425 push 016e 0076 pop 016e 012f push 016f 0456 pop 016f 04ad push 0174 004d pop 0174 0059 push 02d7 0069 Function: 047b flag offset pop 016e 0251 push 0175 00aa pop 0175 00b6 push 017a 009b pop 017a 03b7 Function: 047c flag offset push 0168 005f push 016a 0062 push 016a 0074 push 016a 00cd push 016a 0116 push 0170 00c6 pop 0170 03f2 push 0176 0099 pop 0176 00a9 push 0186 00c0 pop 0186 03c4 Function: 047d flag offset push 0164 0071 push 0164 0187 push 0168 006b push 0170 0080 push 0177 004f pop 0177 0061 push 0186 01be Function: 047e flag offset pop 0164 00b9 push 0164 01c9 push 0164 0236 pop 0164 02cf push 0168 0056 push 0168 007f push 0168 0110 push 016a 0067 push 016a 0085 pop 016a 00b5 pop 016a 02cb push 0170 010d push 0178 015f pop 0178 016b Function: 047f flag offset push 0164 0059 push 0164 0140 push 0164 0168 push 0168 0053 push 0170 0068 push 0179 003d pop 0179 0049 Function: 0480 flag offset push 02bb 0029 push 02cc 0036 pop 02cc 0046 Function: 0481 flag offset push 0127 005e push 017d 0044 push 0180 0071 pop 0180 0296 push 0181 030c pop 0181 0318 push 0182 0331 pop 0182 033d push 018a 007e pop 018a 008a push 0193 00d8 pop 0193 014b Function: 0482 flag offset push 017d 004a push 017e 0469 pop 017e 0475 push 017f 044c push 0180 003d pop 0180 043a pop 0183 0463 push 0185 0457 push 018b 0072 pop 018b 007e push 0195 0057 pop 0195 0134 pop 0195 015e pop 0195 016a pop 0195 0180 Function: 0483 flag offset push 017e 0028 push 017f 002b push 017f 016b push 017f 01c8 pop 017f 01ee push 017f 0224 push 017f 0250 pop 017f 0276 push 0180 003a push 018c 0047 pop 018c 0053 Function: 0484 flag offset push 017d 0087 pop 017d 01c5 push 017f 0035 push 0180 0028 pop 0180 01f0 push 018d 0047 pop 018d 0053 push 01cd 0038 push 01cd 008a pop 01cd 0224 Function: 0485 flag offset push 0180 0055 pop 0180 01c1 push 0184 0062 push 0184 01e6 push 018e 007c pop 018e 0088 push 01cd 006f Function: 0486 flag offset push 017d 0062 push 0180 0098 pop 0184 031c push 018f 0089 pop 018f 0095 pop 018f 00c2 Function: 0487 flag offset push 017d 0041 push 0180 005d pop 0185 0249 push 0190 004e pop 0190 005a Function: 0488 flag offset push 017d 0041 push 0180 005d push 0191 004e pop 0191 005a Function: 0489 flag offset push 017d 0064 push 0180 0057 pop 0180 029a push 0187 0098 pop 0187 00f7 push 0188 00a4 push 018f 0071 push 0190 007e push 0191 008b push 0192 00b0 pop 0192 00bc Function: 048a flag offset push 02bb 004e pop 02bb 005a push 02cc 0041 push 02d2 0064 pop 02d2 02e9 pop 02d2 0330 Function: 048c flag offset push 0198 003d push 019a 02a7 pop 019a 02b3 push 01a4 0153 push 01aa 005b push 01b4 0012 push 01b9 013f push 01ba 01c8 pop 01bd 00fb push 01c4 00fe pop 01c4 010a push 01ca 001e Function: 048d flag offset push 0003 0246 push 0198 004d push 01a3 0037 push 01aa 0056 push 01ab 003d push 01b5 0008 push 01c5 00a3 pop 01c5 015e Function: 048e flag offset push 0198 0086 push 01a5 00a6 pop 01a5 021f push 01a6 0093 push 01a8 0053 push 01b6 0060 pop 01c1 00b7 pop 01c1 0245 push 01c7 00bd pop 01c7 00c9 push 01ce 0041 pop 01ce 004c push 01cf 0050 Function: 048f flag offset push 0198 00da push 01a0 03b2 pop 01a0 03be push 01a8 01a4 push 01aa 0056 push 01aa 01a7 push 01aa 029c push 01b7 0047 pop 01b7 0053 push 01c0 009e push 01c0 0224 pop 01c0 0243 push 01c8 00ef pop 01c8 0107 push 01d0 0097 Function: 0490 flag offset push 0198 0022 push 01a6 003c pop 01a7 001e push 01a7 0062 push 01a9 0068 push 01aa 004f push 01b8 0008 push 01c9 00db pop 01c9 00ed Function: 0491 flag offset push 017c 0048 push 0198 0129 push 019b 02e7 pop 019b 0303 push 01a4 009c pop 01a4 0316 push 01aa 0061 push 01b4 020a push 01b9 0055 push 01bd 00f7 pop 01bd 0126 push 01be 00b6 pop 01be 00e5 push 01ca 0136 pop 01ca 015b Function: 0492 flag offset push 017c 01c3 push 0198 0046 push 019c 03a6 pop 019c 03b8 push 01aa 0064 push 01b4 0254 push 01b4 02d4 push 01b4 0306 push 01ba 0012 push 01c4 0031 push 01cb 0187 pop 01cb 0199 Function: 0493 flag offset push 017c 0209 push 0198 007d push 0199 008a push 019a 0090 push 019b 0096 push 019c 009c push 019d 00ae push 019e 00a8 push 019f 02ec pop 019f 02ff push 01a0 00a2 push 01a1 00b4 pop 01a2 00bb push 01a2 0197 push 01a2 02f3 push 01a2 030b push 01aa 0136 push 01aa 0178 push 01aa 01aa push 01aa 01d9 push 01aa 028d push 01bb 0027 push 01cc 0171 pop 01cc 0191 Function: 0495 flag offset push 02c7 004f pop 02c7 00b2 Function: 0496 flag offset push 0000 0126 push 0003 009b push 0003 0106 push 0003 0176 push 0003 0242 push 0003 029c push 01df 004a pop 01df 0230 push 01e0 0057 pop 01e0 01a6 push 01e1 01ac push 01e1 02a3 pop 01e1 02f2 pop 01e2 0016 push 01e2 00a2 push 01e2 00ec push 01e2 010d push 01e2 017d push 01e2 0249 push 01e2 0358 push 01f8 0064 pop 01f8 008f Function: 0497 flag offset push 02c6 0061 pop 02c6 006d Function: 0498 flag offset pop 01da 0286 push 01da 02ba push 01db 004f push 01db 007f push 01dc 005c push 01dc 008c pop 01e3 02aa push 01f6 00b2 push 01fa 0039 pop 01fa 0045 Function: 0499 flag offset push 0003 0040 push 0003 005d push 0003 029b push 01fb 002e pop 01fb 003a Function: 049a flag offset push 02be 0063 pop 02be 006f push 02c3 00b9 push 02e1 02ea push 02e1 02fc push 02e2 02e7 push 02e2 02ff Function: 049b flag offset pop 01d6 015c pop 01d7 0160 push 01ff 004a pop 01ff 0056 Function: 049c flag offset pop 01d8 0285 push 01d8 02a2 push 01fd 0065 pop 01fd 0071 pop 020d 00fe push 020e 0081 Function: 049d flag offset push 01d5 0032 pop 01d5 01d3 push 01d6 0087 push 01d6 00b4 push 01fe 006b pop 01fe 0077 push 01fe 008a Function: 049e flag offset push 01d7 012c push 0200 002e pop 0200 003a Function: 049f flag offset push 01f6 008c push 0201 0035 pop 0201 0041 Function: 04a0 flag offset push 01f4 0059 push 01f4 00af pop 01f4 00e7 push 0202 007e pop 0202 008a Function: 04a1 flag offset push 01f1 0034 pop 01f1 00b3 push 01f2 004c pop 01f2 00cb push 01f3 0040 pop 01f3 0144 push 0203 0058 pop 0203 0148 Function: 04a2 flag offset push 01ed 0084 push 0204 002e Function: 04a3 flag offset push 01d9 00c5 pop 01d9 0109 push 01d9 021c push 01d9 0247 push 01d9 0273 push 01d9 0298 push 01d9 02c3 push 01d9 02e8 push 01d9 030d push 01d9 0338 push 01d9 0382 push 01da 00bf push 0205 00a3 pop 0205 00af Function: 04a4 flag offset push 01dd 004e push 01dd 0098 push 01dd 00ef pop 01de 0159 push 01ed 0051 push 01ed 009b pop 01ed 0214 push 0206 0032 pop 0206 003e Function: 04a5 flag offset push 0207 0032 pop 0207 0048 Function: 04a6 flag offset push 0212 0044 pop 0212 01ce push 0216 02a6 pop 0216 02b2 push 0218 0047 push 0218 01aa push 021a 0056 push 021b 006a push 021d 005c push 021d 0200 pop 021d 024a push 021f 0077 pop 021f 0083 push 0231 02cb pop 0231 02d7 Function: 04a7 flag offset push 0006 0176 push 0105 00c4 push 016b 0311 push 0212 0043 pop 0212 040c push 0213 003b pop 0213 0090 pop 0217 031d push 0218 00fd push 0218 039c push 0218 03e3 push 0218 0431 pop 021c 0094 push 0220 0119 pop 0220 0129 push 0221 01c3 push 0236 0038 Function: 04a8 flag offset push 0006 0111 push 0212 0028 pop 0212 0241 push 0218 002b push 0218 003a push 0218 01c5 push 0218 01ee push 0220 00c2 push 0221 0069 pop 0221 0075 Function: 04a9 flag offset push 00cc 009b push 0222 002f pop 0222 003b Function: 04aa flag offset push 0212 003a push 0215 005b pop 0215 00f3 push 0218 0047 push 021e 0067 pop 021e 0149 push 0223 008d pop 0223 00ef push 022d 0075 pop 022d 00c5 push 022e 0081 pop 022e 00dd Function: 04ab flag offset pop 0212 030f push 0218 00e8 push 0218 0101 push 0218 012a pop 0218 0245 push 0218 032c pop 0219 02f8 push 021c 002f push 021c 0137 push 0224 005e pop 0224 006a Function: 04ac flag offset pop 0212 04a4 push 0213 0081 push 0213 054a push 0214 0067 pop 0214 0123 push 0218 0084 push 0218 01ed push 0218 0461 push 0218 05d9 push 0225 00c2 pop 0225 0110 pop 0225 012d pop 0225 0132 push 022f 004f pop 022f 00f4 push 0230 005b pop 0230 010c push 0233 0093 push 0235 0073 pop 0235 04cf push 0237 0554 pop 0237 05a2 Function: 04ad flag offset pop 0211 023d push 0226 004d pop 0226 0059 Function: 04ae flag offset push 0227 0031 pop 0227 003d Function: 04af flag offset push 0212 0028 pop 0212 0094 push 0213 0082 push 0213 01df push 0218 0075 push 0228 0035 pop 0228 0041 Function: 04b0 flag offset push 0212 0041 pop 0212 02a0 push 0218 004e push 0229 0062 pop 0229 006e Function: 04b1 flag offset push 0212 0052 pop 0212 029a push 0213 0018 push 0213 005f push 0213 0244 push 0213 028e push 0218 006c push 021a 00d9 pop 021a 0204 push 022a 0086 pop 022a 0096 pop 022a 00b6 push 0234 001b pop 0234 003e Function: 04b2 flag offset push 0212 0036 pop 0212 023a push 0213 028c push 0218 003c push 0218 0050 push 0218 0074 push 0218 0090 push 0218 00d7 push 0218 010d push 0218 0121 push 0218 017b push 0218 0279 push 0218 02b4 push 021c 004a push 022a 00cd push 022b 005e pop 022b 006e Function: 04b3 flag offset push 0212 003d pop 0212 01cf push 0214 0064 push 0215 0057 push 0216 0071 push 0218 004a pop 021b 0213 push 022c 007e pop 022c 008a Function: 04b4 flag offset push 0004 003c push 01e0 00ba push 0238 002e pop 0238 0160 push 0238 01cd push 0239 0028 pop 0239 01d9 pop 023b 0119 push 0245 0049 pop 0245 0055 Function: 04b5 flag offset pop 023c 016e push 0244 0092 push 0246 002d pop 0246 0039 Function: 04b6 flag offset pop 023d 01d0 push 0244 0087 push 0247 0028 pop 0247 0034 Function: 04b7 flag offset push 0239 0051 push 0239 0071 push 023a 0187 pop 023a 0202 push 023f 003e push 0248 0028 pop 0248 0034 pop 0253 011d push 0254 004b pop 0254 006e Function: 04b8 flag offset push 023f 007a push 023f 00b5 push 0240 0087 push 0240 00c2 push 0249 005e pop 0249 006a push 0255 0074 pop 0255 00a4 Function: 04b9 flag offset push 0006 0139 push 01ef 0058 push 01f5 00be push 023c 015f push 023f 01f0 push 0240 01fd pop 0241 0282 push 0242 0162 pop 0242 02ac pop 0242 02c3 pop 0243 018c push 024a 0065 pop 024a 0071 push 0253 01bc push 0264 0180 Function: 04ba flag offset pop 023e 01ed push 024b 0058 pop 024b 0064 Function: 04bb flag offset push 023d 0047 push 024c 0022 pop 024c 002e Function: 04bc flag offset push 023f 0094 push 023f 00db push 0240 0085 push 0240 00cc pop 0240 0199 push 0241 0082 push 0241 00c9 push 024d 0062 pop 024d 006e push 0250 0078 pop 0250 00b8 Function: 04bd flag offset pop 023c 019b pop 0244 01c9 pop 0244 021c push 024e 0057 push 024e 00c4 pop 024e 00d0 Function: 04be flag offset push 023e 0042 push 023e 008d push 024f 0026 pop 024f 0032 push 0251 003c pop 0251 008a Function: 04bf flag offset push 023b 002f push 0256 003f pop 0256 009e push 0258 01a1 pop 0258 0204 Function: 04c0 flag offset push 0269 003d pop 0269 0049 Function: 04c1 flag offset push 025d 0147 push 025e 0048 push 026a 002c pop 026a 0038 push 0276 004b pop 0276 017e Function: 04c2 flag offset push 025c 0054 push 025c 008a push 025d 0057 push 025d 008d pop 025d 026f push 026b 0032 pop 026b 003e push 0274 00af pop 0274 0136 push 027c 004e pop 027c 0080 Function: 04c3 flag offset push 025d 0092 push 025e 00cc pop 025e 024e push 025f 0079 push 0260 00cf push 0260 0223 pop 0260 024a push 0261 0084 push 0261 0095 pop 0261 031f push 0262 02eb pop 0262 0362 push 0263 00e2 pop 0263 022f push 0265 007c push 026c 003b pop 026c 006f push 026e 005d Function: 04c4 flag offset push 0259 0305 pop 0259 033b push 025e 00be push 025f 00d0 push 025f 0109 push 0261 00c1 push 0265 00d3 push 0265 010c push 0266 0045 pop 0266 0092 push 0267 0051 pop 0267 00a3 push 026d 005d pop 026d 00ae push 0279 00e1 push 0279 0114 push 027b 00db pop 027b 00ff Function: 04c5 flag offset push 025e 007c push 025f 013d push 0261 0091 push 0265 007f pop 0265 016c push 026c 0040 push 026e 0022 pop 026e 0072 push 0276 008e Function: 04c6 flag offset push 025a 0046 pop 025a 008d push 025a 0142 push 025b 0052 pop 025b 0098 push 025b 014e pop 025c 02cb push 025e 0120 push 0261 0123 push 026f 005e pop 026f 0110 Function: 04c7 flag offset push 0259 0055 push 0259 00d4 push 025e 0037 push 025e 00ce push 025f 03f1 push 0261 003a push 0261 00d7 push 026e 01e5 push 0270 0092 pop 0270 009e push 0275 0042 push 0275 004f pop 0275 00c4 Function: 04c8 flag offset push 025e 004e push 0261 0051 push 026e 026d push 0271 0032 pop 0271 003e push 0277 0060 push 0277 0087 push 0277 00c1 pop 0277 0141 push 0278 0063 pop 0278 0103 pop 0278 0166 Function: 04c9 flag offset push 0259 0036 push 0259 0098 push 025e 00fd pop 025f 0195 push 0268 017c push 0272 0049 pop 0272 0055 push 027a 003c pop 027a 0095 Function: 04ca flag offset push 0006 0133 push 0006 0140 push 0243 0029 pop 0264 01db push 0273 0036 pop 0273 0042 push 02a8 01cf Function: 04cb flag offset push 0284 0084 push 0284 0182 push 0288 0091 pop 0288 009d Function: 04cc flag offset push 0289 0081 pop 0289 008d Function: 04cd flag offset push 028a 003c Function: 04ce flag offset push 028b 0036 pop 028b 0042 Function: 04cf flag offset pop 0283 0168 push 0283 0208 pop 0283 0225 push 028c 0072 pop 028c 0082 Function: 04d0 flag offset push 0280 0041 push 0280 0094 pop 0280 0101 push 0281 0050 pop 0281 0136 pop 0282 0057 push 0282 005e push 0283 003e push 0283 0091 push 028d 0028 pop 028d 0034 pop 0299 005b push 0299 006e pop 0299 00f0 Function: 04d1 flag offset push 0088 0036 push 01ef 01ee pop 0284 01fa push 028e 0043 pop 028e 004f Function: 04d2 flag offset push 028f 0032 pop 028f 003e Function: 04d3 flag offset push 0280 0082 push 0281 004d pop 0282 0175 push 0290 0022 pop 0290 002e push 02df 0057 push 02df 0085 pop 02df 01a9 Function: 04d4 flag offset push 027d 0283 push 027e 0049 pop 027e 0251 push 0285 004c pop 0285 02b0 push 0286 005b pop 0286 00a8 push 0287 0067 pop 0287 00c6 push 0291 0073 pop 0291 00d0 Function: 04d5 flag offset push 0285 003e push 0292 0052 pop 0292 005e Function: 04d6 flag offset pop 027d 0134 push 0293 0038 pop 0293 0044 Function: 04d7 flag offset push 0003 0115 push 0294 0022 pop 0294 002e Function: 04d8 flag offset push 0003 0022 push 0003 0057 push 0295 0028 pop 0295 0034 push 0295 0041 pop 0295 004d Function: 04db flag offset pop 027f 00dd push 027f 00ef push 0298 0022 pop 0298 002e Function: 04dc flag offset push 02c2 0069 push 02e2 0047 Function: 04dd flag offset push 029c 0091 push 029d 00a7 pop 029d 0207 push 029e 009c push 029f 003b pop 029f 0130 push 02a0 0047 pop 02a0 015a push 02aa 00bf pop 02aa 015e Function: 04de flag offset push 02ab 0030 pop 02ab 003c Function: 04df flag offset push 029a 003b pop 029a 0130 push 029b 0047 pop 029b 0151 push 029c 00a7 pop 029c 0207 push 029d 0091 push 029e 009c push 02ac 00bf pop 02ac 015b Function: 04e0 flag offset push 029c 0091 push 029d 009c push 029e 00a7 pop 029e 0204 push 02a1 003b pop 02a1 0134 push 02a2 0047 pop 02a2 0146 push 02ad 00c5 pop 02ad 0150 Function: 04e1 flag offset push 0104 004c push 0135 004f push 02ae 005d pop 02ae 0069 Function: 04e2 flag offset push 02a3 002f pop 02a3 0093 push 02a4 003b pop 02a4 00ab push 02a4 01ea push 02a5 0057 push 02a5 00be pop 02a5 020a push 02a5 025a push 02a6 00bb pop 02a6 0234 push 02a6 0257 push 02a7 005d push 02a7 020d push 02af 006a pop 02af 00b5 Function: 04e3 flag offset push 02a5 003f push 02a5 01c0 push 02a7 0039 pop 02a7 01bd push 02b0 004c pop 02b0 0058 Function: 04e4 flag offset push 02b1 0037 pop 02b1 0043 Function: 04e5 flag offset push 0104 004f push 0135 004c push 02b2 005d pop 02b2 00d0 push 02b6 018e pop 02b6 01f5 Function: 04e6 flag offset push 0006 011e push 0006 0199 push 0104 0048 push 0135 004b push 02b3 0059 pop 02b3 0065 Function: 04e7 flag offset push 0104 030a push 0135 0307 push 02a9 026b push 02aa 02ac push 02ab 029f push 02ac 02b9 push 02ad 02c6 push 02ae 02ed push 02af 0278 push 02b0 0285 push 02b1 02d3 push 02b2 0292 push 02b3 02e0 push 02b4 005a pop 02b4 0066 push 02b5 02fa Function: 04e8 flag offset push 02b5 003d pop 02b5 0049 Function: 04e9 flag offset push 02b8 0030 pop 02b8 003c Function: 04ec flag offset push 0050 0041 pop 0050 004d Function: 04ed flag offset push 00b1 005f pop 00b1 006b Function: 04ee flag offset pop 013b 0160 push 0145 002e Function: 04ef flag offset push 02bc 003d pop 02bc 0049 push 02bd 0078 pop 02d8 0159 push 02d8 019c pop 02d9 024a pop 02da 02aa Function: 04f0 flag offset push 02c3 006a pop 02c3 0076 push 02e1 0042 Function: 04f1 flag offset push 0152 027a push 02bf 004e pop 02bf 005a push 02d3 0013 pop 02d3 0180 pop 02d3 01bc push 02d4 0034 pop 02d4 0294 Function: 04f2 flag offset push 00e2 007b push 0100 00c6 push 0138 0048 pop 0138 01c7 push 0147 002c pop 0147 0038 push 0148 011a Function: 04f3 flag offset push 02bc 008c push 02bd 003d pop 02bd 0049 push 02d9 0063 push 02da 007b push 02da 00f3 Function: 04f4 flag offset push 02c8 003a pop 02c8 0046 pop 02e0 0102 Function: 04f5 flag offset push 012f 007d pop 012f 01c6 pop 012f 01eb push 0148 0053 push 0148 0061 pop 0148 006d push 0159 0050 push 0159 009f Function: 04f6 flag offset push 0133 002f push 0133 01f8 push 017c 0248 pop 017c 025b push 0189 0054 pop 0189 0060 push 0196 0032 push 0196 0047 push 0196 01fb push 0196 0231 Function: 04f7 flag offset push 017c 005c push 017c 00c1 push 0196 005f push 0196 00c4 pop 0196 0330 push 0198 009e push 01a1 00a4 pop 01a1 019e push 01aa 031b push 01b2 0012 push 01bc 02ed pop 01bc 036e push 01bf 0072 push 01bf 008a push 01bf 00ef push 01bf 013c pop 01bf 01ec push 01c0 0079 push 01c0 00f6 push 01c0 0143 push 01c2 0040 pop 01c2 004c push 01d0 0090 Function: 04f8 flag offset push 0008 0056 push 0100 00db push 01da 0088 push 01da 00a9 pop 01db 0132 push 01dd 0211 pop 01dd 0354 push 01e8 0208 pop 01e8 02a9 push 01e9 020b pop 01e9 0305 push 01ea 020e pop 01ea 0339 push 01ed 0070 pop 01ed 03a7 push 01ee 0063 push 01ee 0344 pop 01ee 0375 push 01f0 0073 pop 01f0 040f pop 01f6 01c1 push 01f7 0036 pop 01f7 0042 pop 01f9 0046 push 0209 0082 Function: 04f9 flag offset push 01da 00fa pop 01dc 00f7 push 01e3 005b push 01e4 01f0 pop 01e4 025f push 01e5 01f3 pop 01e5 02b9 push 01e6 01f6 pop 01e6 0356 push 01e7 01f9 pop 01e7 03b0 push 01f6 004e push 01f6 007e pop 01f7 003e push 01f9 002e pop 01f9 003a Function: 04fa flag offset push 0006 0382 push 0006 03c5 push 0006 04a9 push 01d8 00a0 push 01d8 00f7 push 01d8 0129 pop 01ef 03f1 push 01f5 011c push 01fc 004b push 01fc 0084 pop 01fc 0090 push 020a 00a3 push 020a 00c5 push 020a 00fa push 020a 012c pop 020a 048c push 020b 00ab pop 020b 00ed push 020c 0177 pop 020c 01cf pop 020c 046f pop 020c 0488 push 020d 015d pop 020e 0456 push 020f 00b8 pop 020f 02a9 pop 020f 031f push 0210 00c8 pop 0210 0247 push 0243 03e5 push 0284 0077 Function: 04fb flag offset push 0104 0058 push 0135 005b push 0264 0069 pop 02a8 029b push 02a9 0076 pop 02a9 00a2 Function: 04fc flag offset push 02c9 003e pop 02c9 004a pop 02e0 009f Function: 04fd flag offset push 02cb 003a pop 02cb 0046 push 02d0 01ad pop 02d0 01d5 pop 02d7 006c pop 02e0 01aa Function: 04fe flag offset push 029c 01a8 push 029c 0263 push 029d 01a5 push 029d 0260 push 029e 01ab push 029e 0266 push 02cd 0019 pop 02cd 0025 pop 02d0 03b1 push 02d1 0365 pop 02d1 0403 push 02e0 0386 Function: 04ff flag offset push 02c0 004b pop 02c0 00ef push 02d4 0098 push 02d4 00f9 Function: 0500 flag offset push 0100 006b pop 0127 0214 pop 0133 0135 push 0133 0167 pop 0134 01be push 0150 0078 pop 0150 008c pop 0157 0194 Function: 060a flag offset push 0006 0167 Function: 060b flag offset push 001f 0008 push 001f 0016 pop 001f 001e push 0020 000b push 0020 0022 pop 0020 002a Function: 060c flag offset push 0006 00c6 push 0022 0106 pop 0022 010f pop 0022 026a push 0023 0242 pop 0023 024a pop 0023 026e push 0024 0250 pop 0024 0258 push 0024 0262 pop 0024 0272 push 0025 025e pop 0025 0276 Function: 060e flag offset pop 0039 007c pop 003a 00a7 push 003a 00aa push 0057 007f Function: 0610 flag offset pop 0026 0143 pop 003a 0147 Function: 0613 flag offset pop 0039 0001 Function: 0617 flag offset pop 01a8 0001 pop 01ce 0075 Function: 061c flag offset push 0197 0011 pop 0197 0031 pop 0197 0051 Function: 0621 flag offset push 0003 0531 push 0004 04bd push 0005 04f7 push 0157 0040 Function: 0631 flag offset push 003d 00ad push 0057 00b9 push 0057 013b push 0057 01c4 push 0057 025d push 0057 0286 push 0057 02bf Function: 0633 flag offset pop 02ea 00a2 pop 02eb 004c pop 02ec 006f Function: 063e flag offset pop 001e 014a Function: 0645 flag offset pop 0027 0027 push 003d 000d Function: 0662 flag offset push 0039 003e Function: 0666 flag offset pop 01b2 0086 pop 01b2 0151 pop 01b3 008a pop 01b3 0155 pop 01b4 008e pop 01b4 0159 pop 01b5 0092 pop 01b5 015d pop 01b6 0096 pop 01b6 0161 pop 01b7 009a pop 01b7 00ae pop 01b7 0165 pop 01b7 0179 pop 01b8 009e pop 01b8 0169 pop 01b9 00a2 pop 01b9 016d pop 01ba 00a6 pop 01ba 0171 pop 01bb 00aa pop 01bb 0175 Function: 0674 flag offset pop 02ed 0022 push 02ed 0093 Function: 0680 flag offset pop 001e 00c7 Function: 068a flag offset pop 02ed 0001 Function: 06a4 flag offset pop 003c 0009 Function: 06a5 flag offset push 0006 0008 Function: 06a6 flag offset push 0000 0005 pop 0000 0014 Function: 06a7 flag offset push 0001 0005 pop 0001 0014 Function: 06a8 flag offset push 0002 0005 pop 0002 0014 Function: 06a9 flag offset pop 0009 0009 Function: 06ab flag offset pop 0122 0009 Function: 06ac flag offset pop 0257 0047 Function: 06c1 flag offset push 0157 0008 push 0157 0160 push 0194 000b pop 0194 0153 Function: 06c2 flag offset push 0057 0008 Function: 06c3 flag offset push 0122 0008 pop 0122 0010 Function: 06c4 flag offset pop 02b7 0009 Function: 06c5 flag offset pop 0097 0009 Function: 06c6 flag offset push 0213 003a push 021c 0025 push 0220 0008 push 0224 000e push 0225 0014 push 022a 0011 push 022b 000b push 0234 003d pop 0236 001f push 0236 0022 Function: 06cc flag offset push 0005 0008 Function: 06cf flag offset push 0004 0000 Function: 06d4 flag offset push 0004 0008 Function: 06d5 flag offset push 0005 0008 Function: 06d7 flag offset push 01d4 0008 Function: 06d8 flag offset push 0157 0008 Function: 06d9 flag offset push 008e 0008 Function: 06df flag offset push 0003 0008 Function: 06e0 flag offset push 0004 0008 Function: 06e1 flag offset push 0003 0080 push 0004 00a0 push 0005 00b0 push 012d 0090 push 0134 0040 push 01e1 0070 push 01e2 0050 push 01ed 0030 push 0257 0060 Function: 0807 flag offset push 02e4 019d push 02e4 01dc push 02e4 0210 push 02e4 024f push 02e4 028d push 02e5 01b2 push 02e5 01e0 push 02e5 0225 push 02e5 0253 push 02e5 0299 push 02e6 01c7 push 02e6 01e4 push 02e6 023a push 02e6 0257 push 02e6 02a5 Function: 0808 flag offset pop 02e4 0006 push 02e4 002e pop 02e5 000f push 02e5 003a pop 02e6 0018 push 02e6 0046 Function: 080c flag offset push 012b 0100 Function: 080d flag offset pop 02e8 0005 Function: 0816 flag offset push 0003 00b5 push 0003 00cd Function: 0817 flag offset push 0003 00b5 push 0003 00cd Function: 0819 flag offset push 0003 005c Function: 081e flag offset push 02b6 0008 Function: 081f flag offset push 0003 002b push 0198 00be pop 0198 00cf push 01a6 00aa push 01ac 0070 push 01ad 0016 pop 01ad 001e push 01ae 0098 pop 01ae 00a4 push 01d1 0039 push 01d1 005e push 01d1 0077 Function: 0820 flag offset pop 01ac 0024 pop 01d1 0018 pop 01d1 0028 Function: 0821 flag offset push 01a3 0059 push 01ab 007f Function: 0822 flag offset push 01c5 0000 Function: 0823 flag offset pop 01ab 0058 Function: 0824 flag offset push 017c 0014 push 01b0 003d Function: 082b flag offset pop 00e0 0029 Function: 0830 flag offset pop 0154 0055 Function: 0835 flag offset push 0006 0207 Function: 0838 flag offset push 02e7 0022 Function: 083f flag offset push 012b 00f7 Function: 0841 flag offset pop 01a6 0056 push 01a8 001d push 01a8 00fa push 01c1 0016 push 01c1 0089 pop 01cf 013d Function: 0842 flag offset push 019e 002b pop 019e 0047 Function: 0845 flag offset push 0154 000a push 0154 0055 pop 0154 0063 push 0154 0069 Function: 0846 flag offset push 0026 00c6 push 003a 0000 push 003a 001f push 0087 0026 push 0087 0031 push 0088 0065 push 0088 0071 push 0105 0034 push 0105 0040 push 016b 0056 push 016b 0062 push 01ef 0083 push 01ef 008f push 0217 0043 pop 0217 0050 push 0217 0053 push 0243 0092 push 0243 009e push 0264 00a1 push 0264 00ad push 0284 0074 push 0284 0080 push 02a8 00b0 push 02a8 00bc Function: 0847 flag offset pop 0154 0055 Function: 0849 flag offset pop 006f 017b pop 006f 01be Function: 084d flag offset pop 001d 01ec push 0161 00fd pop 0161 0145 Function: 084e flag offset pop 015e 0034 pop 015e 0065 Function: 084f flag offset push 015d 0016 pop 015d 0031 Function: 0850 flag offset pop 015f 0243 push 0161 01f4 pop 0161 021d Function: 085d flag offset pop 0198 0067 Function: 085e flag offset pop 01a3 00b5 Function: 086d flag offset pop 0154 0055 Function: 086e flag offset push 012b 0115 Function: 0873 flag offset push 0134 0071 Function: 087b flag offset pop 0039 001e Function: 087f flag offset pop 0029 01bd pop 0029 01de pop 0029 01ff Function: 0880 flag offset pop 000a 0159 Function: 0881 flag offset push 012b 0106 Function: 0886 flag offset push 0006 0077 push 00e2 0062 push 0100 00ad pop 0100 00bb Function: 08d3 flag offset push 0039 0011 Function: 08d9 flag offset push 012b 011b Function: 08da flag offset push 012b 00d9 Function: 08dd flag offset push 0057 0000 pop 0057 0009 Function: 08e3 flag offset push 019d 003b pop 019d 0057 Function: 08e4 flag offset pop 019d 008b pop 01a6 004a Function: 08e5 flag offset pop 01a7 0023 push 01a9 0027 pop 01a9 00ad push 01b8 000d push 01c7 004c Function: 08e6 flag offset push 01c9 0000 Function: 08f3 flag offset pop 008d 0026 push 0096 0007 push 0097 000a Function: 08f4 flag offset pop 0096 017d Function: 08f5 flag offset pop 0006 0306 push 0038 02da pop 0090 031a pop 0091 0302 Function: 08f7 flag offset pop 008f 0050 push 00d6 0000 pop 00d6 0075 pop 00d7 0069 Function: 08f8 flag offset push 0032 001c pop 0032 008b push 0032 0140 push 0033 0020 pop 0033 00ab push 0033 0158 push 0034 0024 pop 0034 00cb push 0034 0170 push 0035 0028 pop 0035 00eb push 0035 0188 push 0036 002c pop 0036 010b push 0036 01a0 push 0037 0030 pop 0037 012b push 0037 01b8 pop 0038 025f pop 0038 026e Function: 08fd flag offset pop 0154 0055 Function: 08fe flag offset push 009b 0168 Function: 08ff flag offset push 003d 00bc Function: 0905 flag offset push 012b 0100 Function: 0906 flag offset push 0003 0026 pop 0003 003d Function: 0908 flag offset push 0004 0000 pop 0004 0088 Function: 090a flag offset push 0005 0000 pop 0005 005f Function: 090b flag offset pop 0039 002c Function: 090c flag offset push 01f1 0012 push 01f2 002a push 01f3 001e Function: 090d flag offset push 012b 0109 Function: 0922 flag offset push 012b 00f4 Function: 0926 flag offset pop 02e1 002c pop 02e1 0072 pop 02e2 003a pop 02e2 0080 Function: 092a flag offset pop 003d 0245 pop 003d 0273 push 0040 01c0 pop 0042 022d push 0043 0173 push 0044 01eb pop 0044 0221 pop 0045 0216 pop 0045 0225 push 005e 000a pop 005e 0035 push 005f 0040 pop 005f 006f push 0060 009f pop 0060 00ce push 0061 00d9 pop 0061 0119 push 0062 0152 pop 0062 0197 push 0063 01a2 pop 0063 01e4 Function: 092b flag offset push 003c 001d pop 0048 0045 pop 005a 0057 pop 005a 006a pop 005a 007d pop 005a 0089 Function: 092c flag offset push 002a 0022 pop 002a 009b push 002a 0190 push 002b 0026 pop 002b 00bb push 002b 01a8 push 002c 002a pop 002c 00db push 002c 01c0 push 002d 002e pop 002d 00fb push 002d 01d8 push 002e 0032 pop 002e 011b push 002e 01f0 push 002f 0036 pop 002f 013b push 002f 0208 push 0030 003a pop 0030 015b push 0030 0220 push 0031 003e pop 0031 017b push 0031 0238 Function: 0933 flag offset push 01a5 0157 push 01a6 013c push 01a6 01c0 push 01a8 015d push 01a9 01db push 01aa 0179 push 01aa 022b push 01aa 02e7 push 01c0 0200 pop 01c0 0213 push 01c2 0061 push 01c3 002d push 01c4 003a push 01c7 0054 push 01cb 0047 push 01cc 0020 Flag: 0000 func offset push 0269 00ef push 046e 0180 push 0496 0126 push 06a6 0005 pop 06a6 0014 Flag: 0001 func offset push 0269 0115 push 0269 022a push 0269 0238 push 06a7 0005 pop 06a7 0014 Flag: 0002 func offset push 0269 014d push 0269 038b push 06a8 0005 pop 06a8 0014 Flag: 0003 func offset push 0269 0102 push 0269 0184 push 0269 0309 push 0269 0371 push 0403 0444 push 0405 023b push 0417 051f push 0418 0035 push 0418 0052 push 0418 0073 push 0418 009a push 0418 013e push 0418 0166 push 0431 008b push 0440 00fb push 044a 0048 push 044a 0078 push 044a 00a9 push 044a 01b7 push 0466 0079 push 0466 009c push 0466 00bd push 0466 00f1 push 0466 0156 push 0466 01eb push 0466 0259 push 0466 026e push 0466 028f push 0466 02fa push 046b 0212 push 046b 0242 push 046e 0037 push 046e 007b push 046e 00a3 push 046e 00d7 push 046e 010f push 046e 0167 push 048d 0246 push 0496 009b push 0496 0106 push 0496 0176 push 0496 0242 push 0496 029c push 0499 0040 push 0499 005d push 0499 029b push 04d7 0115 push 04d8 0022 push 04d8 0057 push 0621 0531 push 06df 0008 push 06e1 0080 push 0816 00b5 push 0816 00cd push 0817 00b5 push 0817 00cd push 0819 005c push 081f 002b push 0906 0026 pop 0906 003d Flag: 0004 func offset push 0269 0028 push 0269 0128 push 0269 02ce push 0269 036e push 0311 0008 push 0347 001a push 0403 0423 push 044a 0143 push 04b4 003c push 0621 04bd push 06cf 0000 push 06d4 0008 push 06e0 0008 push 06e1 00a0 push 0908 0000 pop 0908 0088 Flag: 0005 func offset push 0269 0056 push 0269 013e push 0269 0160 push 0621 04f7 push 06cc 0008 push 06d5 0008 push 06e1 00b0 push 090a 0000 pop 090a 005f Flag: 0006 func offset push 0404 0100 push 0410 011f pop 041a 00b6 push 041a 016c push 041a 0240 push 041a 0257 push 041a 03ed push 042b 0183 push 0451 0136 push 0453 0123 push 0453 014d push 0453 015d push 04a7 0176 push 04a8 0111 push 04b9 0139 push 04ca 0133 push 04ca 0140 push 04e6 011e push 04e6 0199 push 04fa 0382 push 04fa 03c5 push 04fa 04a9 push 060a 0167 push 060c 00c6 push 06a5 0008 push 0835 0207 push 0886 0077 pop 08f5 0306 Flag: 0007 func offset pop 0269 0349 Flag: 0008 func offset pop 0269 03a9 push 04f8 0056 Flag: 0009 func offset pop 06a9 0009 Flag: 000a func offset push 041a 0212 pop 0880 0159 Flag: 0012 func offset push 0269 002b pop 0269 004c push 0269 013b Flag: 0013 func offset push 0269 0059 pop 0269 006e Flag: 0014 func offset pop 0401 0001 push 040b 0036 Flag: 0015 func offset push 0402 0038 push 0402 008b pop 0402 0125 Flag: 0016 func offset push 0403 00a9 pop 0403 00b5 Flag: 0017 func offset push 0403 0333 push 0404 011a pop 0404 0126 Flag: 0018 func offset push 0405 0052 push 0405 0081 pop 0405 008d Flag: 0019 func offset push 0406 0093 pop 0406 00d5 pop 0406 0117 Flag: 001a func offset push 0407 0066 pop 0407 0072 Flag: 001b func offset push 0408 0087 pop 0408 0093 Flag: 001c func offset push 0409 0092 pop 0409 009e Flag: 001d func offset push 040a 0133 push 040a 01d4 push 040a 0207 push 040a 0235 pop 040a 029e push 040a 02e8 push 040a 0337 push 040a 0436 push 040a 04a3 push 040a 0a0b pop 084d 01ec Flag: 001e func offset push 0417 000e push 041a 0057 pop 063e 014a pop 0680 00c7 Flag: 001f func offset pop 0329 009c push 060b 0008 push 060b 0016 pop 060b 001e Flag: 0020 func offset pop 0329 00a0 push 060b 000b push 060b 0022 pop 060b 002a Flag: 0021 func offset pop 0329 00a4 Flag: 0022 func offset push 060c 0106 pop 060c 010f pop 060c 026a Flag: 0023 func offset push 060c 0242 pop 060c 024a pop 060c 026e Flag: 0024 func offset push 060c 0250 pop 060c 0258 push 060c 0262 pop 060c 0272 Flag: 0025 func offset push 060c 025e pop 060c 0276 Flag: 0026 func offset pop 0610 0143 push 0846 00c6 Flag: 0027 func offset pop 0645 0027 Flag: 0028 func offset push 0405 0074 pop 0405 00e1 Flag: 0029 func offset push 0405 010a pop 087f 01bd pop 087f 01de pop 087f 01ff Flag: 002a func offset push 092c 0022 pop 092c 009b push 092c 0190 Flag: 002b func offset push 092c 0026 pop 092c 00bb push 092c 01a8 Flag: 002c func offset push 092c 002a pop 092c 00db push 092c 01c0 Flag: 002d func offset push 092c 002e pop 092c 00fb push 092c 01d8 Flag: 002e func offset push 092c 0032 pop 092c 011b push 092c 01f0 Flag: 002f func offset push 092c 0036 pop 092c 013b push 092c 0208 Flag: 0030 func offset push 092c 003a pop 092c 015b push 092c 0220 Flag: 0031 func offset push 092c 003e pop 092c 017b push 092c 0238 Flag: 0032 func offset push 08f8 001c pop 08f8 008b push 08f8 0140 Flag: 0033 func offset push 08f8 0020 pop 08f8 00ab push 08f8 0158 Flag: 0034 func offset push 08f8 0024 pop 08f8 00cb push 08f8 0170 Flag: 0035 func offset push 08f8 0028 pop 08f8 00eb push 08f8 0188 Flag: 0036 func offset push 08f8 002c pop 08f8 010b push 08f8 01a0 Flag: 0037 func offset push 08f8 0030 pop 08f8 012b push 08f8 01b8 Flag: 0038 func offset push 041a 0066 push 041a 0079 push 08f5 02da pop 08f8 025f pop 08f8 026e Flag: 0039 func offset pop 060e 007c pop 0613 0001 push 0662 003e pop 087b 001e push 08d3 0011 pop 090b 002c Flag: 003a func offset pop 060e 00a7 push 060e 00aa pop 0610 0147 push 0846 0000 push 0846 001f Flag: 003b func offset push 0401 0030 push 0401 0173 push 0401 0222 pop 0401 023f Flag: 003c func offset push 0401 0313 push 0401 032f push 040b 00a5 push 040b 00d1 push 040c 005d push 040e 005f pop 06a4 0009 push 092b 001d Flag: 003d func offset push 0326 002f push 0326 0084 push 0401 03ca push 040c 025c push 040c 0334 push 040c 0497 pop 040c 04b8 push 040d 002d push 040d 01ad push 040e 0052 push 040e 016c push 0631 00ad push 0645 000d push 08ff 00bc pop 092a 0245 pop 092a 0273 Flag: 003e func offset pop 0281 0093 push 0402 0155 push 0402 0189 push 0402 025a push 0402 0584 push 0410 0072 Flag: 003f func offset push 0401 02f9 pop 0402 04f9 push 040b 00b8 push 040c 0246 push 040d 003a push 040e 006c push 0410 004e push 0411 0035 push 0415 0046 Flag: 0040 func offset pop 040d 013b push 040e 0082 push 0410 0088 push 0415 0039 push 0417 031f push 0439 0047 push 0451 01b9 push 045a 0089 push 045a 0130 push 045c 004a push 092a 01c0 Flag: 0041 func offset pop 0410 01d5 push 041a 0159 Flag: 0042 func offset pop 0326 00c4 push 040c 0259 pop 040c 04e1 pop 040e 01af pop 092a 022d Flag: 0043 func offset push 0402 0204 push 0402 0314 pop 0402 032b push 040d 006e push 0410 0065 push 0415 0053 push 0417 0312 push 0451 01c6 push 045c 0057 push 0470 01a4 push 092a 0173 Flag: 0044 func offset push 040c 026e pop 040c 0322 push 040c 03d0 push 040c 0494 push 092a 01eb pop 092a 0221 Flag: 0045 func offset push 040c 026b pop 040c 031e pop 092a 0216 pop 092a 0225 Flag: 0046 func offset push 0402 006d pop 0402 00c2 Flag: 0047 func offset push 0402 0079 pop 0402 00d3 Flag: 0048 func offset push 0402 0148 push 040c 0033 pop 040c 0093 pop 092b 0045 Flag: 0049 func offset push 0402 0173 pop 0402 03c5 Flag: 004a func offset push 0439 0044 Flag: 004b func offset push 040b 005d pop 040b 007f pop 040b 0094 Flag: 004c func offset push 040c 011f pop 040c 013e Flag: 004d func offset push 040d 007b pop 040d 0087 Flag: 004e func offset push 040e 008f pop 040e 009b Flag: 004f func offset push 0410 009f pop 0410 00ab Flag: 0050 func offset push 04ec 0041 pop 04ec 004d Flag: 0051 func offset push 0413 006a pop 0413 0076 Flag: 0052 func offset push 0411 0048 pop 0411 0054 Flag: 0053 func offset push 0412 0074 pop 0412 00b6 Flag: 0054 func offset push 0414 003a pop 0414 0046 Flag: 0055 func offset push 0415 0066 pop 0415 0072 Flag: 0056 func offset push 0416 0054 pop 0416 0060 Flag: 0057 func offset push 0311 001b push 0401 02c8 push 0401 0316 push 040b 0112 push 060e 007f push 0631 00b9 push 0631 013b push 0631 01c4 push 0631 025d push 0631 0286 push 0631 02bf push 06c2 0008 push 08dd 0000 pop 08dd 0009 Flag: 0058 func offset push 0415 01ec pop 0415 025d Flag: 0059 func offset push 040c 00ce pop 040c 00e3 pop 040c 021b Flag: 005a func offset push 040c 002e pop 092b 0057 pop 092b 006a pop 092b 007d pop 092b 0089 Flag: 005b func offset push 040c 0239 pop 040c 035e Flag: 005c func offset push 0401 0034 pop 0401 0165 Flag: 005d func offset push 040c 03dd pop 040c 03f5 Flag: 005e func offset push 092a 000a pop 092a 0035 Flag: 005f func offset push 092a 0040 pop 092a 006f Flag: 0060 func offset push 092a 009f pop 092a 00ce Flag: 0061 func offset push 092a 00d9 pop 092a 0119 Flag: 0062 func offset push 092a 0152 pop 092a 0197 Flag: 0063 func offset push 092a 01a2 pop 092a 01e4 Flag: 0064 func offset push 0402 018c pop 0402 0656 Flag: 0065 func offset push 0401 03fc pop 0417 0577 push 044a 0023 Flag: 0066 func offset push 0417 0180 pop 0417 04eb Flag: 0067 func offset pop 041b 0108 push 0435 00ff Flag: 0068 func offset push 041b 0037 pop 0435 0178 Flag: 0069 func offset push 041b 0044 pop 0446 014c Flag: 006a func offset pop 0446 01e0 push 044d 0036 Flag: 006b func offset pop 0403 0489 push 041e 0032 Flag: 006c func offset push 0403 044b pop 0403 0457 Flag: 006d func offset push 0403 006c pop 041e 0170 Flag: 006e func offset push 0403 0079 pop 041e 0174 Flag: 006f func offset push 0419 0080 pop 0849 017b pop 0849 01be Flag: 0071 func offset pop 0443 00da push 0444 0028 Flag: 0072 func offset push 0443 0022 pop 0443 010d Flag: 0073 func offset pop 0419 00da push 0419 025c Flag: 0075 func offset pop 0448 0150 Flag: 0076 func offset pop 0448 0139 push 0449 0022 Flag: 0077 func offset push 0448 0036 pop 0448 0184 Flag: 0078 func offset push 0448 001e pop 0448 006a push 0448 0078 Flag: 0079 func offset push 0448 002a pop 0448 0075 push 0448 0084 Flag: 007a func offset push 042c 004d push 042c 01cd pop 0448 0190 push 0449 011a Flag: 007b func offset push 042f 0037 pop 0449 00ce Flag: 007c func offset pop 0449 0117 Flag: 007d func offset pop 042f 0139 push 0449 002f Flag: 007e func offset pop 042f 01ad push 0449 003c Flag: 007f func offset pop 042b 0174 Flag: 0080 func offset pop 0429 0226 push 042b 0062 Flag: 0081 func offset pop 0428 0132 push 042b 0209 Flag: 0082 func offset pop 0422 0226 push 042b 01d6 Flag: 0083 func offset push 0425 0039 pop 0425 00aa Flag: 0084 func offset push 0425 0045 pop 0425 00d4 pop 0425 010d Flag: 0085 func offset pop 042f 0170 push 0434 004c Flag: 0086 func offset push 0439 0229 pop 0439 0235 Flag: 0087 func offset pop 041a 03a0 push 0451 0074 push 0846 0026 push 0846 0031 Flag: 0088 func offset pop 041a 03d1 push 0478 015c push 04d1 0036 push 0846 0065 push 0846 0071 Flag: 0089 func offset push 042c 005a push 042c 01ec pop 0449 014c Flag: 008a func offset push 041a 020c pop 043f 0171 Flag: 008b func offset push 041a 0221 pop 043f 015a Flag: 008c func offset push 041a 020f pop 0429 0216 Flag: 008d func offset push 041a 0135 push 041a 01de pop 08f3 0026 Flag: 008e func offset push 041a 01be pop 041a 051f push 06d9 0008 Flag: 008f func offset push 041a 0421 pop 041a 045f push 0451 0115 pop 08f7 0050 Flag: 0090 func offset pop 041a 00ca push 041a 01f1 pop 041a 05f1 pop 08f5 031a Flag: 0091 func offset pop 041a 00b2 push 041a 0138 push 041a 01eb pop 08f5 0302 Flag: 0092 func offset pop 042a 02e6 push 042e 003d Flag: 0093 func offset push 043d 0028 push 043d 010c pop 043d 0118 Flag: 0094 func offset push 041a 01ff push 042d 007c push 042d 0163 pop 0445 013a Flag: 0095 func offset push 043d 0158 pop 043d 028c Flag: 0096 func offset push 041a 0166 push 041a 03fa push 041a 0620 push 0451 00f2 push 08f3 0007 pop 08f4 017d Flag: 0097 func offset push 041a 01d1 push 041a 03fd pop 06c5 0009 push 08f3 000a Flag: 0098 func offset push 0403 021c push 0417 00b5 pop 0417 00c1 Flag: 0099 func offset push 0417 0526 push 0417 059a push 0418 0023 pop 0418 002f push 0440 0028 Flag: 009a func offset push 0419 0012 pop 0419 001e Flag: 009b func offset push 041a 022e pop 041a 023a push 08fe 0168 Flag: 009c func offset push 041b 0057 pop 041b 0063 Flag: 009d func offset push 041c 003c pop 041c 0052 Flag: 009e func offset push 041d 0022 pop 041d 002e Flag: 009f func offset push 041e 0043 pop 041e 004f Flag: 00a0 func offset push 041f 002b pop 041f 0037 Flag: 00a1 func offset push 0420 0022 pop 0420 002e Flag: 00a2 func offset push 0421 002b pop 0421 0037 Flag: 00a3 func offset push 0422 0077 pop 0422 0083 Flag: 00a4 func offset push 0423 0033 pop 0423 0043 Flag: 00a5 func offset push 0424 0037 pop 0424 0043 Flag: 00a6 func offset push 0425 007b pop 0425 0117 Flag: 00a7 func offset push 0426 0044 pop 0426 0050 Flag: 00a8 func offset push 0427 004f pop 0427 005b Flag: 00a9 func offset push 0428 004f pop 0428 005b Flag: 00aa func offset push 0429 0077 pop 0429 0087 Flag: 00ab func offset push 042a 0049 pop 042a 0055 Flag: 00ac func offset push 042b 007c pop 042b 008c Flag: 00ad func offset push 042c 0067 pop 042c 0073 Flag: 00ae func offset push 042d 0089 pop 042d 0095 Flag: 00af func offset push 042a 003c push 042e 004a pop 042e 0056 Flag: 00b0 func offset push 042f 0044 pop 042f 0050 Flag: 00b1 func offset push 04ed 005f pop 04ed 006b Flag: 00b2 func offset push 0431 0037 pop 0431 0043 Flag: 00b3 func offset push 0432 003d pop 0432 0049 Flag: 00b4 func offset push 0433 003d pop 0433 0049 Flag: 00b5 func offset push 0434 00a1 pop 0434 00ad push 0435 007d Flag: 00b6 func offset push 0435 008a pop 0435 0096 Flag: 00b7 func offset push 0436 00e8 pop 0436 013b Flag: 00b8 func offset push 0437 007d pop 0437 0089 Flag: 00b9 func offset push 0438 0043 pop 0438 004f Flag: 00ba func offset push 0439 0055 pop 0439 0061 Flag: 00bb func offset push 043a 007d pop 043a 0089 Flag: 00bc func offset push 043b 0084 pop 043b 0090 Flag: 00bd func offset push 043c 003c pop 043c 0048 Flag: 00be func offset push 043d 0042 pop 043d 004e Flag: 00bf func offset push 043e 0028 pop 043e 0034 Flag: 00c0 func offset push 043f 007c pop 043f 0088 Flag: 00c1 func offset push 0440 0035 pop 0440 0041 Flag: 00c2 func offset push 0441 002b pop 0441 0037 Flag: 00c3 func offset push 0442 002e pop 0442 0040 Flag: 00c4 func offset push 0443 0031 pop 0443 003d Flag: 00c5 func offset push 0444 0043 pop 0444 004f Flag: 00c6 func offset push 042d 006f push 0445 0039 pop 0445 0045 Flag: 00c7 func offset push 0446 003c pop 0446 004c Flag: 00c8 func offset push 0447 0022 pop 0447 0032 Flag: 00c9 func offset push 0448 0041 pop 0448 0091 Flag: 00ca func offset push 0449 0049 pop 0449 0055 Flag: 00cb func offset push 0434 0059 pop 0434 031c Flag: 00cc func offset push 0417 007f pop 0417 0653 push 04a9 009b Flag: 00cd func offset push 0417 007c pop 0445 030f Flag: 00ce func offset push 043c 002f pop 043c 01c4 push 043c 0223 Flag: 00cf func offset push 043d 0035 pop 043d 02b3 Flag: 00d1 func offset pop 0417 02fc push 042b 006f Flag: 00d2 func offset push 0439 013a pop 0439 0196 Flag: 00d3 func offset push 0417 008e push 0417 0144 pop 0417 0153 Flag: 00d4 func offset push 0417 00a8 pop 0417 05cb Flag: 00d5 func offset push 0403 00e7 pop 0403 0411 Flag: 00d6 func offset push 041a 017d push 08f7 0000 pop 08f7 0075 Flag: 00d7 func offset push 041a 017a push 041a 041e pop 08f7 0069 Flag: 00d8 func offset push 0444 00c9 pop 0444 00dd Flag: 00d9 func offset push 0403 014e pop 0403 0178 Flag: 00da func offset pop 041a 0048 push 0422 0052 push 0429 0052 push 042b 003d push 042d 004a push 0435 0058 push 0437 0052 push 043a 0058 push 043b 005f push 043f 004a Flag: 00db func offset pop 0407 0147 pop 0407 0194 pop 0407 01bb push 0407 0210 Flag: 00dc func offset push 042a 002f pop 042a 0102 Flag: 00dd func offset push 0417 006e pop 0417 0214 Flag: 00de func offset push 0446 002f push 0446 021b push 044d 0210 pop 044d 0237 Flag: 00e0 func offset push 044b 0063 push 044b 0168 push 044d 0029 push 044d 01d0 pop 082b 0029 Flag: 00e1 func offset pop 044b 01ca Flag: 00e2 func offset push 0406 016b push 044b 0069 pop 044b 022b push 04f2 007b push 0886 0062 Flag: 00e3 func offset pop 044d 01dc push 0450 0022 push 0450 008f Flag: 00e4 func offset push 0405 0061 push 0405 00b3 push 044c 0037 push 044c 0099 pop 044d 0148 push 044e 0030 push 044e 006f push 044f 0030 push 044f 006f push 0450 002f push 0450 0072 Flag: 00e6 func offset push 044b 0097 push 044b 0261 push 044b 026f push 044b 0282 pop 044b 02bc Flag: 00e7 func offset push 044a 0036 pop 044a 0042 Flag: 00e8 func offset push 044b 00a4 pop 044b 00c1 Flag: 00e9 func offset push 044c 004a pop 044c 0064 Flag: 00ea func offset push 044d 0049 pop 044d 0059 Flag: 00eb func offset push 044e 0043 pop 044e 004f Flag: 00ec func offset push 044f 0043 pop 044f 004f Flag: 00ed func offset push 0450 0042 pop 0450 0052 Flag: 00ee func offset push 044c 003d pop 044c 00a7 pop 044c 0153 Flag: 00ef func offset push 0405 0067 pop 0405 00c1 Flag: 00f0 func offset push 044e 0036 pop 044e 007d Flag: 00f1 func offset push 044f 0036 pop 044f 007d Flag: 00f2 func offset push 0450 0035 pop 0450 0080 Flag: 00f4 func offset push 045e 0040 pop 045f 0245 Flag: 00f5 func offset push 045e 004d Flag: 00f6 func offset pop 045e 013c push 045f 003d Flag: 00f7 func offset push 0408 0284 push 0451 0169 push 0451 0381 push 0452 01d2 push 0455 0165 push 0459 020b push 045a 00b3 push 045a 0115 push 045a 01f0 push 045a 0396 push 045a 046e push 045a 04b2 push 045a 04d3 push 045a 0586 push 045b 0128 pop 045b 0296 Flag: 00f8 func offset push 0459 003a push 0459 0077 pop 045f 022e Flag: 00f9 func offset push 045a 0529 pop 045a 0535 Flag: 00fa func offset push 045a 0554 pop 045a 0560 Flag: 00fb func offset push 045a 00a6 pop 045a 0222 push 045a 03b0 Flag: 00fc func offset push 045a 03a5 pop 045a 03d5 Flag: 00fd func offset pop 0408 0303 push 045b 007b Flag: 00fe func offset push 0453 002a pop 0456 016a Flag: 00ff func offset push 0453 0040 push 0458 0143 pop 0458 0163 Flag: 0100 func offset push 04f2 00c6 push 04f8 00db push 0500 006b push 0886 00ad pop 0886 00bb Flag: 0101 func offset push 0408 007a push 0408 0159 pop 0408 01d5 pop 0408 01fa Flag: 0102 func offset push 041a 01a4 push 0451 011b pop 0451 02be pop 0451 034a Flag: 0104 func offset pop 045c 029b push 04e1 004c push 04e5 004f push 04e6 0048 push 04e7 030a push 04fb 0058 Flag: 0105 func offset push 041a 0394 push 041a 03a3 pop 0451 03d4 push 04a7 00c4 push 0846 0034 push 0846 0040 Flag: 0106 func offset pop 0457 028e Flag: 0107 func offset push 0461 0059 pop 0463 0081 Flag: 0108 func offset pop 0408 016b pop 0408 01d9 pop 0408 01fe Flag: 0109 func offset push 041a 0180 push 041a 0190 push 0451 0118 pop 0451 028b pop 0451 030d Flag: 010a func offset push 045d 0113 pop 045d 011f Flag: 010b func offset push 0408 0048 pop 0459 01ae Flag: 010c func offset push 0451 00ae pop 0451 00ba Flag: 010d func offset push 0452 009e pop 0452 00aa Flag: 010e func offset push 0453 004d pop 0453 0059 Flag: 010f func offset push 0454 0029 pop 0454 0035 Flag: 0110 func offset push 0455 002f pop 0455 003b Flag: 0111 func offset push 0456 0018 pop 0456 0024 Flag: 0112 func offset push 0457 005f pop 0457 006b Flag: 0113 func offset push 0458 0036 pop 0458 0042 Flag: 0114 func offset push 0459 004e pop 0459 005a Flag: 0115 func offset push 045a 00c0 pop 045a 00cc Flag: 0116 func offset push 045b 0088 pop 045b 009c Flag: 0117 func offset push 045c 0064 pop 045c 0070 Flag: 0118 func offset push 045d 007b pop 045d 0087 Flag: 0119 func offset push 045e 005a pop 045e 0066 Flag: 011a func offset push 045f 004a pop 045f 0056 Flag: 011b func offset push 0454 010b push 0460 004c pop 0460 0058 Flag: 011c func offset push 0461 0066 pop 0461 0072 Flag: 011d func offset push 0463 0021 pop 0463 002d Flag: 011e func offset push 041a 01b1 push 041a 04cc push 0451 011e pop 0451 02d5 pop 0451 035b Flag: 011f func offset push 0408 00c7 pop 0408 00fe push 0451 00e8 pop 0451 0157 push 0452 00d2 pop 0452 00f7 push 0455 0069 pop 0455 008b push 0456 0062 pop 0456 0084 push 0457 0093 pop 0457 00b2 push 0458 0076 pop 0458 009b push 045a 010f pop 045a 0167 push 045b 00c4 pop 045b 00e3 push 045c 003d push 045c 009e pop 045c 0103 push 045d 00b5 pop 045d 00d4 push 045e 008e pop 045e 00b6 push 045f 0085 pop 045f 00a4 Flag: 0120 func offset pop 0459 01e5 Flag: 0121 func offset push 0408 005b pop 0408 045f Flag: 0122 func offset push 0456 00d5 push 045a 042f pop 06ab 0009 push 06c3 0008 pop 06c3 0010 Flag: 0123 func offset push 045a 008f pop 045a 00fa Flag: 0124 func offset push 0459 0034 pop 0459 0074 Flag: 0125 func offset push 0451 00a1 pop 0456 0120 Flag: 0126 func offset pop 0282 0132 Flag: 0127 func offset push 0417 009b push 0481 005e pop 0500 0214 Flag: 0128 func offset push 046c 0084 push 046c 0098 push 046c 01ca pop 046c 01eb push 0472 0159 Flag: 0129 func offset pop 0406 0368 push 044b 0083 Flag: 012a func offset push 0465 024a pop 0465 0274 push 0474 0085 Flag: 012b func offset push 031d 00a0 push 0465 006c push 0465 01ff pop 0474 01d5 push 080c 0100 push 083f 00f7 push 086e 0115 push 0881 0106 push 08d9 011b push 08da 00d9 push 0905 0100 push 090d 0109 push 0922 00f4 Flag: 012c func offset push 0475 003e Flag: 012d func offset push 0466 0241 pop 0466 02d4 push 06e1 0090 Flag: 012e func offset push 0464 009e pop 0464 00cb pop 0464 012b Flag: 012f func offset push 04f5 007d pop 04f5 01c6 pop 04f5 01eb Flag: 0130 func offset push 0462 0110 pop 0462 0177 push 0465 01f9 Flag: 0131 func offset push 0462 007d push 0465 00ab pop 0465 0239 Flag: 0132 func offset push 0406 015d push 0406 017b pop 0406 0392 push 0462 0070 push 0462 00b5 push 0462 010a Flag: 0133 func offset push 04f6 002f push 04f6 01f8 pop 0500 0135 push 0500 0167 Flag: 0134 func offset pop 0500 01be push 06e1 0040 push 0873 0071 Flag: 0135 func offset pop 0470 01c5 push 04e1 004f push 04e5 004c push 04e6 004b push 04e7 0307 push 04fb 005b Flag: 0136 func offset push 0406 007b pop 0406 00bf pop 0406 00f9 Flag: 0137 func offset push 0406 0087 pop 0406 00cd pop 0406 010d Flag: 0138 func offset push 0406 012b push 0462 01bb push 04f2 0048 pop 04f2 01c7 Flag: 0139 func offset pop 046c 02df push 046c 031b push 046c 0436 pop 046c 0447 Flag: 013a func offset pop 046c 0312 push 046c 0315 pop 046c 03e8 pop 046c 044f Flag: 013b func offset push 046c 00f1 pop 04ee 0160 Flag: 013c func offset push 01df 0040 pop 01df 004c push 0406 009a pop 0406 00d1 push 0462 0047 pop 0462 0053 push 0464 0047 pop 0464 0053 push 0465 0047 pop 0465 0053 Flag: 013d func offset push 0462 0040 pop 0462 0057 pop 0462 0062 Flag: 013e func offset push 0464 0040 pop 0464 0057 pop 0464 0062 Flag: 013f func offset push 0465 0040 pop 0465 0057 pop 0465 0062 Flag: 0140 func offset push 0466 0067 pop 0466 0073 Flag: 0141 func offset push 043f 006f push 0467 004f pop 0467 005b Flag: 0142 func offset push 0468 0028 pop 0468 0034 push 0473 00ba Flag: 0143 func offset push 0469 0028 pop 0469 0034 Flag: 0144 func offset push 046a 002e pop 046a 003a Flag: 0145 func offset push 04ee 002e Flag: 0146 func offset push 046c 0052 pop 046c 005e Flag: 0147 func offset push 04f2 002c pop 04f2 0038 Flag: 0148 func offset push 0472 00ad push 04f2 011a push 04f5 0053 push 04f5 0061 pop 04f5 006d Flag: 0149 func offset push 046f 002e Flag: 014a func offset push 0470 003e pop 0470 004a Flag: 014b func offset push 0471 0035 pop 0471 0041 Flag: 014c func offset push 046d 018a push 0472 003d pop 0472 0049 Flag: 014d func offset push 0468 0076 push 0473 0044 pop 0473 0050 Flag: 014e func offset push 0474 0028 pop 0474 0034 Flag: 014f func offset push 0475 0028 pop 0475 0034 Flag: 0150 func offset push 0500 0078 pop 0500 008c Flag: 0151 func offset push 0406 0178 pop 0465 00b7 Flag: 0152 func offset push 040a 08ff pop 040a 0915 push 04f1 027a Flag: 0153 func offset push 040a 0724 push 040a 07e6 pop 040a 0801 Flag: 0154 func offset push 01df 0027 push 0406 0052 push 0462 0027 push 0464 0027 push 0465 0027 pop 0830 0055 push 0845 000a push 0845 0055 pop 0845 0063 push 0845 0069 pop 0847 0055 pop 086d 0055 pop 08fd 0055 Flag: 0155 func offset push 0406 013c pop 0462 0216 Flag: 0156 func offset push 0406 012e push 0406 0142 pop 0406 030f Flag: 0157 func offset push 02d9 0037 pop 0500 0194 push 0621 0040 push 06c1 0008 push 06c1 0160 push 06d8 0008 Flag: 0158 func offset push 0406 0136 push 0462 0080 pop 0462 01c9 Flag: 0159 func offset pop 0282 0146 push 04f5 0050 push 04f5 009f Flag: 015a func offset push 046c 0161 pop 046c 0186 push 0472 002c push 0472 0072 Flag: 015b func offset push 0472 002f pop 0472 006f Flag: 015c func offset push 0472 015c pop 0472 017d Flag: 015d func offset push 040a 0137 push 040a 01b8 pop 040a 037f push 084f 0016 pop 084f 0031 Flag: 015e func offset push 040a 0127 pop 084e 0034 pop 084e 0065 Flag: 015f func offset pop 040a 01e3 push 040a 01fc pop 040a 02c0 push 040a 02c7 push 040a 049f pop 0850 0243 Flag: 0161 func offset push 040a 0269 pop 040a 0287 push 040a 02ab push 040a 0388 push 040a 09c3 push 040a 0a16 pop 040a 0a53 push 084d 00fd pop 084d 0145 push 0850 01f4 pop 0850 021d Flag: 0162 func offset push 040a 01e6 push 040a 02f5 push 040a 09cd pop 040a 09dd Flag: 0163 func offset push 046c 00a5 pop 046c 00d9 Flag: 0164 func offset push 047d 0071 push 047d 0187 pop 047e 00b9 push 047e 01c9 push 047e 0236 pop 047e 02cf push 047f 0059 push 047f 0140 push 047f 0168 Flag: 0165 func offset push 047a 00bb pop 047a 0425 Flag: 0167 func offset push 0479 004a push 0479 017f pop 0479 023c pop 0479 0257 Flag: 0168 func offset push 0479 0050 pop 0479 02c4 push 047c 005f push 047d 006b push 047e 0056 push 047e 007f push 047e 0110 push 047f 0053 Flag: 016a func offset push 0404 030b push 0404 035c push 0477 00a7 push 047c 0062 push 047c 0074 push 047c 00cd push 047c 0116 push 047e 0067 push 047e 0085 pop 047e 00b5 pop 047e 02cb Flag: 016b func offset push 041a 03a6 push 041a 03b5 push 041a 03c1 pop 0478 0168 push 04a7 0311 push 0846 0056 push 0846 0062 Flag: 016c func offset pop 0477 01f4 push 0477 0205 push 0477 0273 push 0477 02bb Flag: 016d func offset push 0404 01af pop 0404 023b pop 0404 029d pop 0404 02b0 Flag: 016e func offset push 047a 0076 pop 047a 012f pop 047b 0251 Flag: 016f func offset push 047a 0456 pop 047a 04ad Flag: 0170 func offset push 0478 003c push 0479 0231 push 0479 0265 push 047c 00c6 pop 047c 03f2 push 047d 0080 push 047e 010d push 047f 0068 Flag: 0171 func offset push 0477 0047 pop 0477 0053 Flag: 0172 func offset push 0478 0049 pop 0478 0055 Flag: 0173 func offset push 0479 005e pop 0479 006a Flag: 0174 func offset push 047a 004d pop 047a 0059 Flag: 0175 func offset push 047b 00aa pop 047b 00b6 Flag: 0176 func offset push 047c 0099 pop 047c 00a9 Flag: 0177 func offset push 047d 004f pop 047d 0061 Flag: 0178 func offset push 047e 015f pop 047e 016b Flag: 0179 func offset push 047f 003d pop 047f 0049 Flag: 017a func offset push 047b 009b pop 047b 03b7 Flag: 017b func offset pop 0479 0240 pop 0479 0253 Flag: 017c func offset push 0491 0048 push 0492 01c3 push 0493 0209 push 04f6 0248 pop 04f6 025b push 04f7 005c push 04f7 00c1 push 0824 0014 Flag: 017d func offset push 0409 0078 push 0481 0044 push 0482 004a push 0484 0087 pop 0484 01c5 push 0486 0062 push 0487 0041 push 0488 0041 push 0489 0064 Flag: 017e func offset push 0482 0469 pop 0482 0475 push 0483 0028 Flag: 017f func offset push 0482 044c push 0483 002b push 0483 016b push 0483 01c8 pop 0483 01ee push 0483 0224 push 0483 0250 pop 0483 0276 push 0484 0035 Flag: 0180 func offset push 0409 0085 pop 0409 0328 push 0481 0071 pop 0481 0296 push 0482 003d pop 0482 043a push 0483 003a push 0484 0028 pop 0484 01f0 push 0485 0055 pop 0485 01c1 push 0486 0098 push 0487 005d push 0488 005d push 0489 0057 pop 0489 029a Flag: 0181 func offset push 0481 030c pop 0481 0318 Flag: 0182 func offset push 0481 0331 pop 0481 033d Flag: 0183 func offset pop 0482 0463 Flag: 0184 func offset push 0485 0062 push 0485 01e6 pop 0486 031c Flag: 0185 func offset push 0482 0457 pop 0487 0249 Flag: 0186 func offset push 0404 03a4 push 0404 03cc push 0479 003d push 0479 016a push 047c 00c0 pop 047c 03c4 push 047d 01be Flag: 0187 func offset push 0489 0098 pop 0489 00f7 Flag: 0188 func offset push 0489 00a4 Flag: 0189 func offset push 04f6 0054 pop 04f6 0060 Flag: 018a func offset push 0481 007e pop 0481 008a Flag: 018b func offset push 0482 0072 pop 0482 007e Flag: 018c func offset push 0483 0047 pop 0483 0053 Flag: 018d func offset push 0409 006b push 0484 0047 pop 0484 0053 Flag: 018e func offset push 0485 007c pop 0485 0088 Flag: 018f func offset push 0486 0089 pop 0486 0095 pop 0486 00c2 push 0489 0071 Flag: 0190 func offset push 0487 004e pop 0487 005a push 0489 007e Flag: 0191 func offset push 0488 004e pop 0488 005a push 0489 008b Flag: 0192 func offset push 0489 00b0 pop 0489 00bc Flag: 0193 func offset push 0481 00d8 pop 0481 014b Flag: 0194 func offset push 06c1 000b pop 06c1 0153 Flag: 0195 func offset push 0482 0057 pop 0482 0134 pop 0482 015e pop 0482 016a pop 0482 0180 Flag: 0196 func offset push 04f6 0032 push 04f6 0047 push 04f6 01fb push 04f6 0231 push 04f7 005f push 04f7 00c4 pop 04f7 0330 Flag: 0197 func offset push 009b 0055 push 009b 0091 push 009b 00ef push 009b 01a5 push 0378 006c push 061c 0011 pop 061c 0031 pop 061c 0051 Flag: 0198 func offset push 009b 0036 push 048c 003d push 048d 004d push 048e 0086 push 048f 00da push 0490 0022 push 0491 0129 push 0492 0046 push 0493 007d push 04f7 009e push 081f 00be pop 081f 00cf pop 085d 0067 Flag: 0199 func offset push 009b 0257 pop 009b 026a push 0493 008a Flag: 019a func offset push 048c 02a7 pop 048c 02b3 push 0493 0090 Flag: 019b func offset push 0491 02e7 pop 0491 0303 push 0493 0096 Flag: 019c func offset push 0492 03a6 pop 0492 03b8 push 0493 009c Flag: 019d func offset push 0493 00ae push 08e3 003b pop 08e3 0057 pop 08e4 008b Flag: 019e func offset push 0493 00a8 push 0842 002b pop 0842 0047 Flag: 019f func offset push 0493 02ec pop 0493 02ff Flag: 01a0 func offset push 048f 03b2 pop 048f 03be push 0493 00a2 Flag: 01a1 func offset push 0493 00b4 push 04f7 00a4 pop 04f7 019e Flag: 01a2 func offset pop 0493 00bb push 0493 0197 push 0493 02f3 push 0493 030b Flag: 01a3 func offset push 009b 006e push 048d 0037 push 0821 0059 pop 085e 00b5 Flag: 01a4 func offset push 048c 0153 push 0491 009c pop 0491 0316 Flag: 01a5 func offset push 048e 00a6 pop 048e 021f push 0933 0157 Flag: 01a6 func offset push 048e 0093 push 0490 003c push 081f 00aa pop 0841 0056 pop 08e4 004a push 0933 013c push 0933 01c0 Flag: 01a7 func offset pop 02f0 0034 pop 0490 001e push 0490 0062 pop 08e5 0023 Flag: 01a8 func offset push 048e 0053 push 048f 01a4 pop 0617 0001 push 0841 001d push 0841 00fa push 0933 015d Flag: 01a9 func offset push 0490 0068 push 08e5 0027 pop 08e5 00ad push 0933 01db Flag: 01aa func offset pop 02f2 00da push 048c 005b push 048d 0056 push 048f 0056 push 048f 01a7 push 048f 029c push 0490 004f push 0491 0061 push 0492 0064 push 0493 0136 push 0493 0178 push 0493 01aa push 0493 01d9 push 0493 028d push 04f7 031b push 0933 0179 push 0933 022b push 0933 02e7 Flag: 01ab func offset push 048d 003d push 0821 007f pop 0823 0058 Flag: 01ac func offset push 081f 0070 pop 0820 0024 Flag: 01ad func offset push 081f 0016 pop 081f 001e Flag: 01ae func offset push 081f 0098 pop 081f 00a4 Flag: 01af func offset pop 02eb 0093 push 02f2 0025 Flag: 01b0 func offset push 0824 003d Flag: 01b2 func offset push 04f7 0012 pop 0666 0086 pop 0666 0151 Flag: 01b3 func offset push 009b 002a pop 0666 008a pop 0666 0155 Flag: 01b4 func offset push 048c 0012 push 0491 020a push 0492 0254 push 0492 02d4 push 0492 0306 pop 0666 008e pop 0666 0159 Flag: 01b5 func offset push 048d 0008 pop 0666 0092 pop 0666 015d Flag: 01b6 func offset push 048e 0060 pop 0666 0096 pop 0666 0161 Flag: 01b7 func offset push 048f 0047 pop 048f 0053 pop 0666 009a pop 0666 00ae pop 0666 0165 pop 0666 0179 Flag: 01b8 func offset push 0490 0008 pop 0666 009e pop 0666 0169 push 08e5 000d Flag: 01b9 func offset push 048c 013f push 0491 0055 pop 0666 00a2 pop 0666 016d Flag: 01ba func offset push 048c 01c8 push 0492 0012 pop 0666 00a6 pop 0666 0171 Flag: 01bb func offset push 0493 0027 pop 0666 00aa pop 0666 0175 Flag: 01bc func offset push 04f7 02ed pop 04f7 036e Flag: 01bd func offset pop 048c 00fb push 0491 00f7 pop 0491 0126 Flag: 01be func offset push 0491 00b6 pop 0491 00e5 Flag: 01bf func offset push 04f7 0072 push 04f7 008a push 04f7 00ef push 04f7 013c pop 04f7 01ec Flag: 01c0 func offset push 048f 009e push 048f 0224 pop 048f 0243 push 04f7 0079 push 04f7 00f6 push 04f7 0143 push 0933 0200 pop 0933 0213 Flag: 01c1 func offset pop 048e 00b7 pop 048e 0245 push 0841 0016 push 0841 0089 Flag: 01c2 func offset push 04f7 0040 pop 04f7 004c push 0933 0061 Flag: 01c3 func offset push 009b 0043 pop 009b 004f push 0933 002d Flag: 01c4 func offset push 048c 00fe pop 048c 010a push 0492 0031 push 0933 003a Flag: 01c5 func offset push 048d 00a3 pop 048d 015e push 0822 0000 Flag: 01c7 func offset push 048e 00bd pop 048e 00c9 push 08e5 004c push 0933 0054 Flag: 01c8 func offset push 048f 00ef pop 048f 0107 Flag: 01c9 func offset push 0490 00db pop 0490 00ed push 08e6 0000 Flag: 01ca func offset push 048c 001e push 0491 0136 pop 0491 015b Flag: 01cb func offset push 0492 0187 pop 0492 0199 push 0933 0047 Flag: 01cc func offset push 0493 0171 pop 0493 0191 push 0933 0020 Flag: 01cd func offset push 0484 0038 push 0484 008a pop 0484 0224 push 0485 006f Flag: 01ce func offset push 048e 0041 pop 048e 004c pop 0617 0075 Flag: 01cf func offset push 048e 0050 pop 0841 013d Flag: 01d0 func offset pop 0133 02ad push 048f 0097 push 04f7 0090 Flag: 01d1 func offset push 081f 0039 push 081f 005e push 081f 0077 pop 0820 0018 pop 0820 0028 Flag: 01d2 func offset pop 0269 02af push 0460 003f push 0466 0043 Flag: 01d3 func offset push 0269 00ad push 0269 00e2 pop 0269 025f Flag: 01d4 func offset push 0269 0088 pop 0269 00a1 push 06d7 0008 Flag: 01d5 func offset push 049d 0032 pop 049d 01d3 Flag: 01d6 func offset pop 049b 015c push 049d 0087 push 049d 00b4 Flag: 01d7 func offset pop 049b 0160 push 049e 012c Flag: 01d8 func offset pop 049c 0285 push 049c 02a2 push 04fa 00a0 push 04fa 00f7 push 04fa 0129 Flag: 01d9 func offset push 04a3 00c5 pop 04a3 0109 push 04a3 021c push 04a3 0247 push 04a3 0273 push 04a3 0298 push 04a3 02c3 push 04a3 02e8 push 04a3 030d push 04a3 0338 push 04a3 0382 Flag: 01da func offset pop 0498 0286 push 0498 02ba push 04a3 00bf push 04f8 0088 push 04f8 00a9 push 04f9 00fa Flag: 01db func offset push 0498 004f push 0498 007f pop 04f8 0132 Flag: 01dc func offset push 0498 005c push 0498 008c pop 04f9 00f7 Flag: 01dd func offset push 04a4 004e push 04a4 0098 push 04a4 00ef push 04f8 0211 pop 04f8 0354 Flag: 01de func offset push 0473 0060 push 0473 0089 pop 04a4 0159 Flag: 01df func offset push 0496 004a pop 0496 0230 Flag: 01e0 func offset push 0496 0057 pop 0496 01a6 push 04b4 00ba Flag: 01e1 func offset push 0496 01ac push 0496 02a3 pop 0496 02f2 push 06e1 0070 Flag: 01e2 func offset pop 0496 0016 push 0496 00a2 push 0496 00ec push 0496 010d push 0496 017d push 0496 0249 push 0496 0358 push 06e1 0050 Flag: 01e3 func offset pop 0498 02aa push 04f9 005b Flag: 01e4 func offset push 04f9 01f0 pop 04f9 025f Flag: 01e5 func offset push 04f9 01f3 pop 04f9 02b9 Flag: 01e6 func offset push 04f9 01f6 pop 04f9 0356 Flag: 01e7 func offset push 04f9 01f9 pop 04f9 03b0 Flag: 01e8 func offset push 04f8 0208 pop 04f8 02a9 Flag: 01e9 func offset push 04f8 020b pop 04f8 0305 Flag: 01ea func offset push 04f8 020e pop 04f8 0339 Flag: 01ed func offset push 04a2 0084 push 04a4 0051 push 04a4 009b pop 04a4 0214 push 04f8 0070 pop 04f8 03a7 push 06e1 0030 Flag: 01ee func offset push 04f8 0063 push 04f8 0344 pop 04f8 0375 Flag: 01ef func offset push 04b9 0058 push 04d1 01ee pop 04fa 03f1 push 0846 0083 push 0846 008f Flag: 01f0 func offset push 04f8 0073 pop 04f8 040f Flag: 01f1 func offset push 04a1 0034 pop 04a1 00b3 push 090c 0012 Flag: 01f2 func offset push 04a1 004c pop 04a1 00cb push 090c 002a Flag: 01f3 func offset push 04a1 0040 pop 04a1 0144 push 090c 001e Flag: 01f4 func offset push 04a0 0059 push 04a0 00af pop 04a0 00e7 Flag: 01f5 func offset push 04b9 00be push 04fa 011c Flag: 01f6 func offset push 0498 00b2 push 049f 008c pop 04f8 01c1 push 04f9 004e push 04f9 007e Flag: 01f7 func offset push 04f8 0036 pop 04f8 0042 pop 04f9 003e Flag: 01f8 func offset push 0496 0064 pop 0496 008f Flag: 01f9 func offset pop 04f8 0046 push 04f9 002e pop 04f9 003a Flag: 01fa func offset push 0498 0039 pop 0498 0045 Flag: 01fb func offset push 0499 002e pop 0499 003a Flag: 01fc func offset push 04fa 004b push 04fa 0084 pop 04fa 0090 Flag: 01fd func offset push 049c 0065 pop 049c 0071 Flag: 01fe func offset push 049d 006b pop 049d 0077 push 049d 008a Flag: 01ff func offset push 049b 004a pop 049b 0056 Flag: 0200 func offset push 049e 002e pop 049e 003a Flag: 0201 func offset push 049f 0035 pop 049f 0041 Flag: 0202 func offset push 04a0 007e pop 04a0 008a Flag: 0203 func offset push 04a1 0058 pop 04a1 0148 Flag: 0204 func offset push 04a2 002e Flag: 0205 func offset push 04a3 00a3 pop 04a3 00af Flag: 0206 func offset push 04a4 0032 pop 04a4 003e Flag: 0207 func offset push 04a5 0032 pop 04a5 0048 Flag: 0208 func offset push 0476 0033 pop 0476 003f Flag: 0209 func offset push 04f8 0082 Flag: 020a func offset push 04fa 00a3 push 04fa 00c5 push 04fa 00fa push 04fa 012c pop 04fa 048c Flag: 020b func offset push 04fa 00ab pop 04fa 00ed Flag: 020c func offset push 04fa 0177 pop 04fa 01cf pop 04fa 046f pop 04fa 0488 Flag: 020d func offset pop 049c 00fe push 04fa 015d Flag: 020e func offset push 049c 0081 pop 04fa 0456 Flag: 020f func offset push 04fa 00b8 pop 04fa 02a9 pop 04fa 031f Flag: 0210 func offset push 04fa 00c8 pop 04fa 0247 Flag: 0211 func offset push 0269 0173 push 0466 0059 push 0466 024e pop 04ad 023d Flag: 0212 func offset push 04a6 0044 pop 04a6 01ce push 04a7 0043 pop 04a7 040c push 04a8 0028 pop 04a8 0241 push 04aa 003a pop 04ab 030f pop 04ac 04a4 push 04af 0028 pop 04af 0094 push 04b0 0041 pop 04b0 02a0 push 04b1 0052 pop 04b1 029a push 04b2 0036 pop 04b2 023a push 04b3 003d pop 04b3 01cf Flag: 0213 func offset push 04a7 003b pop 04a7 0090 push 04ac 0081 push 04ac 054a push 04af 0082 push 04af 01df push 04b1 0018 push 04b1 005f push 04b1 0244 push 04b1 028e push 04b2 028c push 06c6 003a Flag: 0214 func offset push 04ac 0067 pop 04ac 0123 push 04b3 0064 Flag: 0215 func offset push 04aa 005b pop 04aa 00f3 push 04b3 0057 Flag: 0216 func offset push 04a6 02a6 pop 04a6 02b2 push 04b3 0071 Flag: 0217 func offset push 041a 03b2 push 0451 03c8 push 0478 002f pop 04a7 031d push 0846 0043 pop 0846 0050 push 0846 0053 Flag: 0218 func offset push 04a6 0047 push 04a6 01aa push 04a7 00fd push 04a7 039c push 04a7 03e3 push 04a7 0431 push 04a8 002b push 04a8 003a push 04a8 01c5 push 04a8 01ee push 04aa 0047 push 04ab 00e8 push 04ab 0101 push 04ab 012a pop 04ab 0245 push 04ab 032c push 04ac 0084 push 04ac 01ed push 04ac 0461 push 04ac 05d9 push 04af 0075 push 04b0 004e push 04b1 006c push 04b2 003c push 04b2 0050 push 04b2 0074 push 04b2 0090 push 04b2 00d7 push 04b2 010d push 04b2 0121 push 04b2 017b push 04b2 0279 push 04b2 02b4 push 04b3 004a Flag: 0219 func offset pop 04ab 02f8 Flag: 021a func offset push 04a6 0056 push 04b1 00d9 pop 04b1 0204 Flag: 021b func offset push 04a6 006a pop 04b3 0213 Flag: 021c func offset pop 04a7 0094 push 04ab 002f push 04ab 0137 push 04b2 004a push 06c6 0025 Flag: 021d func offset push 04a6 005c push 04a6 0200 pop 04a6 024a Flag: 021e func offset push 04aa 0067 pop 04aa 0149 Flag: 021f func offset push 04a6 0077 pop 04a6 0083 Flag: 0220 func offset push 04a7 0119 pop 04a7 0129 push 04a8 00c2 push 06c6 0008 Flag: 0221 func offset push 04a7 01c3 push 04a8 0069 pop 04a8 0075 Flag: 0222 func offset push 04a9 002f pop 04a9 003b Flag: 0223 func offset push 04aa 008d pop 04aa 00ef Flag: 0224 func offset push 04ab 005e pop 04ab 006a push 06c6 000e Flag: 0225 func offset push 04ac 00c2 pop 04ac 0110 pop 04ac 012d pop 04ac 0132 push 06c6 0014 Flag: 0226 func offset push 04ad 004d pop 04ad 0059 Flag: 0227 func offset push 04ae 0031 pop 04ae 003d Flag: 0228 func offset push 04af 0035 pop 04af 0041 Flag: 0229 func offset push 04b0 0062 pop 04b0 006e Flag: 022a func offset push 04b1 0086 pop 04b1 0096 pop 04b1 00b6 push 04b2 00cd push 06c6 0011 Flag: 022b func offset push 04b2 005e pop 04b2 006e push 06c6 000b Flag: 022c func offset push 04b3 007e pop 04b3 008a Flag: 022d func offset push 04aa 0075 pop 04aa 00c5 Flag: 022e func offset push 04aa 0081 pop 04aa 00dd Flag: 022f func offset push 04ac 004f pop 04ac 00f4 Flag: 0230 func offset push 04ac 005b pop 04ac 010c Flag: 0231 func offset push 04a6 02cb pop 04a6 02d7 Flag: 0233 func offset pop 0282 0154 push 04ac 0093 Flag: 0234 func offset push 04b1 001b pop 04b1 003e push 06c6 003d Flag: 0235 func offset push 04ac 0073 pop 04ac 04cf Flag: 0236 func offset push 04a7 0038 pop 06c6 001f push 06c6 0022 Flag: 0237 func offset push 04ac 0554 pop 04ac 05a2 Flag: 0238 func offset push 04b4 002e pop 04b4 0160 push 04b4 01cd Flag: 0239 func offset push 04b4 0028 pop 04b4 01d9 push 04b7 0051 push 04b7 0071 Flag: 023a func offset push 04b7 0187 pop 04b7 0202 Flag: 023b func offset pop 04b4 0119 push 04bf 002f Flag: 023c func offset pop 04b5 016e push 04b9 015f pop 04bd 019b Flag: 023d func offset pop 04b6 01d0 push 04bb 0047 Flag: 023e func offset pop 04ba 01ed push 04be 0042 push 04be 008d Flag: 023f func offset pop 031d 014e push 04b7 003e push 04b8 007a push 04b8 00b5 push 04b9 01f0 push 04bc 0094 push 04bc 00db Flag: 0240 func offset push 04b8 0087 push 04b8 00c2 push 04b9 01fd push 04bc 0085 push 04bc 00cc pop 04bc 0199 Flag: 0241 func offset pop 04b9 0282 push 04bc 0082 push 04bc 00c9 Flag: 0242 func offset push 04b9 0162 pop 04b9 02ac pop 04b9 02c3 Flag: 0243 func offset pop 04b9 018c push 04ca 0029 push 04fa 03e5 push 0846 0092 push 0846 009e Flag: 0244 func offset push 04b5 0092 push 04b6 0087 pop 04bd 01c9 pop 04bd 021c Flag: 0245 func offset push 04b4 0049 pop 04b4 0055 Flag: 0246 func offset push 04b5 002d pop 04b5 0039 Flag: 0247 func offset push 04b6 0028 pop 04b6 0034 Flag: 0248 func offset push 04b7 0028 pop 04b7 0034 Flag: 0249 func offset push 04b8 005e pop 04b8 006a Flag: 024a func offset push 04b9 0065 pop 04b9 0071 Flag: 024b func offset push 04ba 0058 pop 04ba 0064 Flag: 024c func offset push 04bb 0022 pop 04bb 002e Flag: 024d func offset push 04bc 0062 pop 04bc 006e Flag: 024e func offset push 04bd 0057 push 04bd 00c4 pop 04bd 00d0 Flag: 024f func offset push 04be 0026 pop 04be 0032 Flag: 0250 func offset push 04bc 0078 pop 04bc 00b8 Flag: 0251 func offset push 04be 003c pop 04be 008a Flag: 0253 func offset pop 04b7 011d push 04b9 01bc Flag: 0254 func offset push 04b7 004b pop 04b7 006e Flag: 0255 func offset push 04b8 0074 pop 04b8 00a4 Flag: 0256 func offset push 04bf 003f pop 04bf 009e Flag: 0257 func offset pop 06ac 0047 push 06e1 0060 Flag: 0258 func offset push 04bf 01a1 pop 04bf 0204 Flag: 0259 func offset push 04c4 0305 pop 04c4 033b push 04c7 0055 push 04c7 00d4 push 04c9 0036 push 04c9 0098 Flag: 025a func offset push 04c6 0046 pop 04c6 008d push 04c6 0142 Flag: 025b func offset push 04c6 0052 pop 04c6 0098 push 04c6 014e Flag: 025c func offset push 04c2 0054 push 04c2 008a pop 04c6 02cb Flag: 025d func offset push 04c1 0147 push 04c2 0057 push 04c2 008d pop 04c2 026f push 04c3 0092 Flag: 025e func offset push 04c1 0048 push 04c3 00cc pop 04c3 024e push 04c4 00be push 04c5 007c push 04c6 0120 push 04c7 0037 push 04c7 00ce push 04c8 004e push 04c9 00fd Flag: 025f func offset push 04c3 0079 push 04c4 00d0 push 04c4 0109 push 04c5 013d push 04c7 03f1 pop 04c9 0195 Flag: 0260 func offset push 04c3 00cf push 04c3 0223 pop 04c3 024a Flag: 0261 func offset push 04c3 0084 push 04c3 0095 pop 04c3 031f push 04c4 00c1 push 04c5 0091 push 04c6 0123 push 04c7 003a push 04c7 00d7 push 04c8 0051 Flag: 0262 func offset push 04c3 02eb pop 04c3 0362 Flag: 0263 func offset push 04c3 00e2 pop 04c3 022f Flag: 0264 func offset push 04b9 0180 pop 04ca 01db push 04fb 0069 push 0846 00a1 push 0846 00ad Flag: 0265 func offset push 04c3 007c push 04c4 00d3 push 04c4 010c push 04c5 007f pop 04c5 016c Flag: 0266 func offset push 04c4 0045 pop 04c4 0092 Flag: 0267 func offset push 04c4 0051 pop 04c4 00a3 Flag: 0268 func offset push 04c9 017c Flag: 0269 func offset push 04c0 003d pop 04c0 0049 Flag: 026a func offset push 04c1 002c pop 04c1 0038 Flag: 026b func offset push 04c2 0032 pop 04c2 003e Flag: 026c func offset push 04c3 003b pop 04c3 006f push 04c5 0040 Flag: 026d func offset push 04c4 005d pop 04c4 00ae Flag: 026e func offset push 04c3 005d push 04c5 0022 pop 04c5 0072 push 04c7 01e5 push 04c8 026d Flag: 026f func offset push 04c6 005e pop 04c6 0110 Flag: 0270 func offset push 04c7 0092 pop 04c7 009e Flag: 0271 func offset push 04c8 0032 pop 04c8 003e Flag: 0272 func offset push 04c9 0049 pop 04c9 0055 Flag: 0273 func offset push 04ca 0036 pop 04ca 0042 Flag: 0274 func offset push 04c2 00af pop 04c2 0136 Flag: 0275 func offset push 04c7 0042 push 04c7 004f pop 04c7 00c4 Flag: 0276 func offset push 04c1 004b pop 04c1 017e push 04c5 008e Flag: 0277 func offset push 04c8 0060 push 04c8 0087 push 04c8 00c1 pop 04c8 0141 Flag: 0278 func offset push 04c8 0063 pop 04c8 0103 pop 04c8 0166 Flag: 0279 func offset push 04c4 00e1 push 04c4 0114 Flag: 027a func offset push 04c9 003c pop 04c9 0095 Flag: 027b func offset push 04c4 00db pop 04c4 00ff Flag: 027c func offset push 04c2 004e pop 04c2 0080 Flag: 027d func offset push 04d4 0283 pop 04d6 0134 Flag: 027e func offset push 04d4 0049 pop 04d4 0251 Flag: 027f func offset pop 04db 00dd push 04db 00ef Flag: 0280 func offset push 04d0 0041 push 04d0 0094 pop 04d0 0101 push 04d3 0082 Flag: 0281 func offset push 04d0 0050 pop 04d0 0136 push 04d3 004d Flag: 0282 func offset pop 04d0 0057 push 04d0 005e pop 04d3 0175 Flag: 0283 func offset pop 04cf 0168 push 04cf 0208 pop 04cf 0225 push 04d0 003e push 04d0 0091 Flag: 0284 func offset push 041a 03c4 push 041a 03d4 push 04cb 0084 push 04cb 0182 pop 04d1 01fa push 04fa 0077 push 0846 0074 push 0846 0080 Flag: 0285 func offset push 04d4 004c pop 04d4 02b0 push 04d5 003e Flag: 0286 func offset push 04d4 005b pop 04d4 00a8 Flag: 0287 func offset push 04d4 0067 pop 04d4 00c6 Flag: 0288 func offset push 04cb 0091 pop 04cb 009d Flag: 0289 func offset push 04cc 0081 pop 04cc 008d Flag: 028a func offset push 04cd 003c Flag: 028b func offset push 04ce 0036 pop 04ce 0042 Flag: 028c func offset push 04cf 0072 pop 04cf 0082 Flag: 028d func offset push 04d0 0028 pop 04d0 0034 Flag: 028e func offset push 04d1 0043 pop 04d1 004f Flag: 028f func offset push 04d2 0032 pop 04d2 003e Flag: 0290 func offset push 04d3 0022 pop 04d3 002e Flag: 0291 func offset push 04d4 0073 pop 04d4 00d0 Flag: 0292 func offset push 04d5 0052 pop 04d5 005e Flag: 0293 func offset push 04d6 0038 pop 04d6 0044 Flag: 0294 func offset push 04d7 0022 pop 04d7 002e Flag: 0295 func offset push 04d8 0028 pop 04d8 0034 push 04d8 0041 pop 04d8 004d Flag: 0298 func offset push 04db 0022 pop 04db 002e Flag: 0299 func offset pop 04d0 005b push 04d0 006e pop 04d0 00f0 Flag: 029a func offset push 04df 003b pop 04df 0130 Flag: 029b func offset push 04df 0047 pop 04df 0151 Flag: 029c func offset push 04dd 0091 push 04df 00a7 pop 04df 0207 push 04e0 0091 push 04fe 01a8 push 04fe 0263 Flag: 029d func offset push 04dd 00a7 pop 04dd 0207 push 04df 0091 push 04e0 009c push 04fe 01a5 push 04fe 0260 Flag: 029e func offset push 04dd 009c push 04df 009c push 04e0 00a7 pop 04e0 0204 push 04fe 01ab push 04fe 0266 Flag: 029f func offset push 04dd 003b pop 04dd 0130 Flag: 02a0 func offset push 04dd 0047 pop 04dd 015a Flag: 02a1 func offset push 04e0 003b pop 04e0 0134 Flag: 02a2 func offset push 04e0 0047 pop 04e0 0146 Flag: 02a3 func offset push 04e2 002f pop 04e2 0093 Flag: 02a4 func offset push 04e2 003b pop 04e2 00ab push 04e2 01ea Flag: 02a5 func offset push 04e2 0057 push 04e2 00be pop 04e2 020a push 04e2 025a push 04e3 003f push 04e3 01c0 Flag: 02a6 func offset push 04e2 00bb pop 04e2 0234 push 04e2 0257 Flag: 02a7 func offset push 04e2 005d push 04e2 020d push 04e3 0039 pop 04e3 01bd Flag: 02a8 func offset push 04ca 01cf pop 04fb 029b push 0846 00b0 push 0846 00bc Flag: 02a9 func offset push 04e7 026b push 04fb 0076 pop 04fb 00a2 Flag: 02aa func offset push 04dd 00bf pop 04dd 015e push 04e7 02ac Flag: 02ab func offset push 04de 0030 pop 04de 003c push 04e7 029f Flag: 02ac func offset push 04df 00bf pop 04df 015b push 04e7 02b9 Flag: 02ad func offset push 04e0 00c5 pop 04e0 0150 push 04e7 02c6 Flag: 02ae func offset push 04e1 005d pop 04e1 0069 push 04e7 02ed Flag: 02af func offset push 04e2 006a pop 04e2 00b5 push 04e7 0278 Flag: 02b0 func offset push 04e3 004c pop 04e3 0058 push 04e7 0285 Flag: 02b1 func offset push 04e4 0037 pop 04e4 0043 push 04e7 02d3 Flag: 02b2 func offset push 04e5 005d pop 04e5 00d0 push 04e7 0292 Flag: 02b3 func offset push 04e6 0059 pop 04e6 0065 push 04e7 02e0 Flag: 02b4 func offset push 04e7 005a pop 04e7 0066 Flag: 02b5 func offset push 04e7 02fa push 04e8 003d pop 04e8 0049 Flag: 02b6 func offset push 04e5 018e pop 04e5 01f5 push 081e 0008 Flag: 02b7 func offset pop 06c4 0009 Flag: 02b8 func offset push 04e9 0030 pop 04e9 003c Flag: 02bb func offset push 0480 0029 push 048a 004e pop 048a 005a Flag: 02bc func offset push 04ef 003d pop 04ef 0049 push 04f3 008c Flag: 02bd func offset push 04ef 0078 push 04f3 003d pop 04f3 0049 Flag: 02be func offset push 049a 0063 pop 049a 006f Flag: 02bf func offset push 04f1 004e pop 04f1 005a Flag: 02c0 func offset push 04ff 004b pop 04ff 00ef Flag: 02c2 func offset push 04dc 0069 Flag: 02c3 func offset push 049a 00b9 push 04f0 006a pop 04f0 0076 Flag: 02c4 func offset push 040f 0022 pop 040f 002e Flag: 02c5 func offset push 0430 0022 pop 0430 002e Flag: 02c6 func offset push 0497 0061 pop 0497 006d Flag: 02c7 func offset push 0495 004f pop 0495 00b2 Flag: 02c8 func offset push 04f4 003a pop 04f4 0046 Flag: 02c9 func offset push 04fc 003e pop 04fc 004a Flag: 02ca func offset push 046d 0028 pop 046d 0034 push 046e 0023 Flag: 02cb func offset push 04fd 003a pop 04fd 0046 Flag: 02cc func offset push 0480 0036 pop 0480 0046 push 048a 0041 Flag: 02cd func offset push 04fe 0019 pop 04fe 0025 Flag: 02ce func offset push 046e 0030 pop 046e 0043 pop 046e 004e Flag: 02cf func offset push 046b 0025 pop 046b 0031 Flag: 02d0 func offset push 04fd 01ad pop 04fd 01d5 pop 04fe 03b1 Flag: 02d1 func offset push 04fe 0365 pop 04fe 0403 Flag: 02d2 func offset push 048a 0064 pop 048a 02e9 pop 048a 0330 Flag: 02d3 func offset push 04f1 0013 pop 04f1 0180 pop 04f1 01bc Flag: 02d4 func offset push 04f1 0034 pop 04f1 0294 push 04ff 0098 push 04ff 00f9 Flag: 02d5 func offset pop 046b 0106 push 046b 0229 push 046b 02bf Flag: 02d6 func offset pop 046b 00ee push 046b 021f push 046b 02b4 Flag: 02d7 func offset push 047a 0069 pop 04fd 006c Flag: 02d8 func offset pop 04ef 0159 push 04ef 019c Flag: 02d9 func offset pop 04ef 024a push 04f3 0063 Flag: 02da func offset pop 04ef 02aa push 04f3 007b push 04f3 00f3 Flag: 02db func offset pop 040f 00a5 push 046b 004b Flag: 02dc func offset push 040f 0038 push 0430 0038 Flag: 02dd func offset push 040f 003b push 040f 0078 push 040f 00dc pop 040f 0187 Flag: 02de func offset push 040f 016a push 0430 003e push 0430 007a push 0430 00a8 pop 0430 01ef pop 0430 01fa Flag: 02df func offset push 04d3 0057 push 04d3 0085 pop 04d3 01a9 Flag: 02e0 func offset pop 04f4 0102 pop 04fc 009f pop 04fd 01aa push 04fe 0386 Flag: 02e1 func offset push 049a 02ea push 049a 02fc push 04f0 0042 pop 0926 002c pop 0926 0072 Flag: 02e2 func offset push 049a 02e7 push 049a 02ff push 04dc 0047 pop 0926 003a pop 0926 0080 Flag: 02e4 func offset push 0807 019d push 0807 01dc push 0807 0210 push 0807 024f push 0807 028d pop 0808 0006 push 0808 002e Flag: 02e5 func offset push 0807 01b2 push 0807 01e0 push 0807 0225 push 0807 0253 push 0807 0299 pop 0808 000f push 0808 003a Flag: 02e6 func offset push 0807 01c7 push 0807 01e4 push 0807 023a push 0807 0257 push 0807 02a5 pop 0808 0018 push 0808 0046 Flag: 02e7 func offset push 0124 00e4 pop 0124 00ef push 0838 0022 Flag: 02e8 func offset pop 080d 0005 Flag: 02ea func offset push 0401 029c pop 0401 02c4 pop 0633 00a2 Flag: 02eb func offset push 0404 0012 pop 0404 003a pop 0633 004c Flag: 02ec func offset push 0403 0040 pop 0403 0068 pop 0633 006f Flag: 02ed func offset pop 0674 0022 push 0674 0093 pop 068a 0001 exult-1.2/usecode/ucxt/Docs/newopcodes.txt0000644000175000001440000000014607225441751014413 NEW OPCODES: * Make an array out of 'n' number of data segments, whose offsets are on the stack exult-1.2/usecode/ucxt/data/0000777000175000001440000000000010062225333011575 5exult-1.2/usecode/ucxt/data/u7opcodes.data0000644000175000001440000005655007451606103014275 <0x02> NEXT `next\t[%1], [%2], [%3], [%4], %5` `\t\t\t;` `for (var%3 in var%4 with var%1 to var%2 atend label%f*_%5)` 10 {short,short,short,varoffset,offset} 0 0 0 <0x04> ASK `ask\t%1` `` `UcAsk` 2 {offset} 0 0 0 <0x05> JNE `jne\t%1` `` `if(!%p1) goto label%f*_%1` 2 {offset} 1 0 0 <0x06> JMP `jmp\t%1` `` `goto label%f*_%1` 2 {offset} 0 0 0 <0x07> CMPS `cmps\t%1H, %2` `\t\t;` `cmps(%p,)` 4 {short,offset} 0xFF 0 0 <0x09> ADD `add` `` `%p2 + %p1` 0 {} 2 1 0 <0x0A> SUB `sub` `` `%p2 - %p1` 0 {} 2 1 0 <0x0B> DIV `div` `` `%p2 / %p1` 0 {} 2 1 0 <0x0C> MUL `mul` `` `%p2 * %p1` 0 {} 2 1 0 <0x0D> MOD `mod` `` `%p2 %% %p1` 0 {} 2 1 0 <0x0E> AND `and` `` `%p2 && %p1` 0 {} 2 1 0 <0x0F> OR `or` `` amp; `%p2 || %p1` 0 {} 2 1 0 <0x10> NOT `not` `` `!%p1` 0 {} 1 1 0 <0x12> POP `pop\t[%1]` `\t\t\t;` `var%1 = %p1` 2 {varoffset} 1 0 0 <0x13> PUSHT `push\ttrue` `` `true` 0 {} 0 1 0 <0x14> PUSHF `push\tfalse` `` `false` 0 {} 0 1 0 <0x16> CMPGT `cmpgt` `` `%p2 > %p1` 0 {} 2 1 0 <0x17> CMPLT `cmplt` `` `%p2 < %p1` 0 {} 2 1 0 <0x18> CMPGE `cmpge` `` `%p2 >= %p1` 0 {} 2 1 0 <0x19> CMPLE `cmple` `` `%p2 <= %p1` 0 {} 2 1 0 <0x1A> CMPNE `cmpne` `` `%p2 != %p1` 0 {} 2 1 0 <0x1C> ADDSI `addsi\t%1H` `\t\t\t; %tc1` `UcMessage(\"%t1\")` 2 {dataoffset} 0 0 0 <0x1D> PUSHS `pushs\t%1H` `\t\t\t; %tc1` `\"%t1\"` 2 {dataoffset} 0 1 0 <0x1E> ARRC `arrc\t%1H` `\t\t\t;` `[%p,]` 2 {short} 0xFF 1 0 <0x1F> PUSHI `pushi\t%1H` `\t\t\t; %d1` `0x%1` 2 {short} 0 1 0 <0x21> PUSH `push\t[%1]` `\t\t\t;` `var%1` 2 {varoffset} 0 1 0 <0x22> CMPEQ `cmpeq` `` `%p2 == %p1` 0 {} 2 1 0 <0x24> CALL `call\textern:[%1]` `\t\t;` `%f1(%p,)` 2 {extoffset} 0 0 1 <0x25> RET `ret` `` `return` 0 {} 0 0 0 <0x26> AIDX `aid\t[%1]` `\t\t\t;` `var%1[%p1]` 2 {varoffset} 1 1 0 <0x2C> EXIT2 `exit2` `` `exit2()` 0 {} 0 0 0 <0x2D> SETR `setr` `` `rr = %p1` 0 {} 1 0 0 <0x2E> ENUM `enum` `` `enum()` 0 {} 0 0 0 <0x2F> ADDSV `addsv\t[%1]` `\t\t\t;` `UcMessage(var%1)` 2 {varoffset} 0 0 0 <0x30> IN `in` `\t\t\t\t;` `in(%p2, %p1)` 0 {} 2 1 0 <0x31> SMTH `smth\t%1 %2` `\t\t\t;` `smth(%p2, %p1)` 4 {short,offset} 0 0 0 <0x32> RTS `rts` `` `return rr` 0 {} 0 0 0 <0x33> SAY `say` `` `UcSay` 0 {} 0 0 0 <0x38> CALLIS `callis\t%i1@%b2` `\t\t; %1` `UI_%i1(%p,)` 3 {short,byte} 0xFE 1 0 <0x39> CALLI `calli\t%i1@%b2` `\t\t; %1, %d2` `UI_%i1(%p,)` 3 {short,byte} 0xFE 0 0 <0x3E> PUSHITM `push\titemref` `\t\t\t;` `item` 0 {} 0 1 0 <0x3F> ABRT `abrt` `` `abrt()` 0 {} 0 0 0 <0x40> END_CONV `end_conv` `` `end_conv()` 0 {} 0 0 0 <0x42> PUSHF `pushf\tflag:[%1]` `\t\t\t;` `gflags[%1]` 2 {flag} 0 1 0 <0x43> POPF `popf\tflag:[%1]` `\t\t;` `gflags[%1] = %p1` 2 {flag} 1 0 0 <0x44> PUSHB `pushb\t%b1H` `\t\t\t; %d1` `0x%b1` 1 {byte} 0 1 0 <0x46> APUT `aput\t[%1]` `\t\t\t;` `var%1[%p1] = %p2` 2 {varoffset} 2 0 0 <0x47> CALLE `calle\t%1H` `\t\t\t;` `calle()` 2 {short} 0 0 0 A <0x48> PUSHEID `push\teventid` `` `event` 0 {} 0 1 0 <0x4A> ARRA `arra` `\t\t\t\t;` `%p2 & %p1` 0 {} 2 1 0 <0x4B> POPEID `pop\teventid` `` `event = %p1` 0 {} 1 0 0 <0x4C> DBGLINE `dbgline %1` `` `// Line: %1` 2 {short} 0 0 0 <0x4D> DBGFUNC `dbgfunc %1 %2 ` `; %t1` `// Function: %t1 %2` 4 {short,dataoffset} 0 0 0 <0x82> LOOP `next32\t[%1], [%2], [%3], [%4], %5` `\t\t\t;` `for (var%3 in var%4 with var%1 to var%2 atend label%f*_%n5)` 12 {short,short,short,varoffset,offset32} 0 0 0 <0x84> CONV32 `ask32\t%1` `` `UcAsk32` 4 {offset32} 0 0 0 <0x85> JNE32 `jne32\t%1` `` `if(!%p1) goto label%f*_%n1` 4 {offset32} 1 0 0 <0x86> JMP32 `jmp32\t%1` `` `goto label%f*_%n1` 4 {offset32} 0 0 0 <0x87> CMPS32 `cmps32\t%1H, %n2` `\t\t;` `cmps32(%p,)` 6 {short,offset32} 0xFF 0 0 <0x9C> ADDSI32 `addsi32\t%n1H` `\t\t\t; %tc1` `UcMessage(\"%t1\")` 4 {dataoffset32} 0 0 0 <0x9D> PUSHS32 `pushs32\t%n1H` `\t\t\t; %tc1` `\"%t1\"` 4 {dataoffset32} 0 1 0 <0x9F> PUSHI32 `pushi32\t%n1H` `\t\t\t; %d1` `0x%1` 4 {long} 0 1 0 <0xAE> ENUM32 `enum32` `` `enum32()` 0 {} 0 0 0 <0xB2> RTS32 `rts32` `` `return rr` 0 {} 0 0 0 <0x101> LABEL `(invalid)` `` `label%f*_%1` 2 {offset} 1 0 0 exult-1.2/usecode/ucxt/data/u7misc.data0000644000175000001440000000040607451606103013561 2 2 2 2 2 2 4 1 4 4 exult-1.2/usecode/ucxt/data/opcodes.txt0000644000175000001440000003147307420275302013723 # Yet another Random Datafile format: only lines with '>' in the # 0th column are considered data, the rest is comments. # Probabially wants to be conf/ed sometime in the future. # UPDATE: Really, REALLY needs to be conf/ed, or something. # Column 1: hex opcode # Column 2: assembler opcode nmonic # Column 3: assembler output format # Column 4: assembler comment output format # Column 5: script function output format # Column 6: number of data bytes # Column 7: data types of bytes # Column 8: number of elements it pops from the stack # Column 9: number of elements it pushes to the stack # Column 10: the 'call effect' true false (1/0) if this is a 'call type' opcode # Column 11: Flags. Each 0/1 reperesents a false/true condition for each of the # flags listed below: # Flag 1: Return flag. If true, it signifises that the function this # opcode is found in, returns a variable on the stack. # Flag 2: Paren output flag. If true, we output a pair of parenthesis # around the usecode script output. # The following flags are specific only to the usecode script output. # Flag 3: Increment indent. If true, output the opcode, then increment # the indent level by 1. # Flag 4: Decrement indent. If true, decrement the indent level by 1, # then output the opcode. # Flag 5: Temporarly increment indent. If true, increment the indent # level by 1, output the opcode, then decrement the indent level # by 1. # Flag 6: Temporarly decrement indent. If trye, decrement the indent # level by 1, output the opcode, then increment the indent level # by 1. # DataType Notes: # long == 4 bytes # flag == extoffset == dataoffset == varoffset == offset == short == 2 bytes # byte == 1 byte # offset is calculated from the relative offset it # A "false" value is defined as integer 0, a null string, or an empty array. # (stateing obvious) Logically a "true" value would be the opposite of this. # "Truth value"s pushed on the stack are integer 1 for true, and integer 0 # for false. # REMEMBER: All arrays are indexed with as 1 based rather then 0 based. # Notes on number of bytes poped/pushed: # All numbers are the number of bytes poped/pushed from the stack, with the # exception of 0xFF, which currently means the number of bytes in the first # opcode parameter (see opcode 0x07). and 0xFE means the second parameter. # Logic: parameter referenced is abs(0x100 - value) # NOTE: Description of function appears below the relevant function. > 0x00 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x01 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x02 NEXT "next\t[%1], [%2], [%3], [%4], %5" "\t\t\t;" "for (var%3 in var%4 with var%1 to var%2 atend label%f*_%5)" 10 {short,short,short,varoffset,offset} 0 0 0 000000 TODO: To be done... * {varoffset} is the array to loop over. * {short}(1st) is used to store the "counter". * {short}(2nd) is used to store the "max" value. Which is the number of elements stored in {varoffset} or 1 if it's a string or integer. * {offset} is the relative offset to jump to after the loop is completed. > 0x03 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x04 ASK "ask\t%1" "" "UcAsk" 2 {offset} 0 0 0 000000 Display the Avatar's conversation options and ask for the user's input. It jumps to {offset} if there is no conversation answers available. > 0x05 JNE "jne\t%1" "" "if(!%p1) goto label%f*_%1" 2 {offset} 1 0 0 000000 Pops a value from the stack, tests if it's false, if it's false jumps to the relative {offset}. > 0x06 JMP "jmp\t%1" "" "goto label%f*_%1" 2 {offset} 0 0 0 000000 Jumps to the relative {offset} provided. > 0x07 CMPS "cmps\t%1H, %2" "\t\t;" "cmps(%p,)" 4 {short,offset} 0xFF 0 0 000000 Pop {short} number of values from the stack, compare each one to the last response from the user, and jumps to the {offset} if it's not found, else continue as normal. NOTE: only do this comparing if we haven't found a correct answer on any of the previous CMPSs since the last ASK. > 0x08 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x09 ADD "add" "" "%p2 + %p1" 0 {} 2 1 0 010000 Adds %p1 to %p2. > 0x0A SUB "sub" "" "%p2 - %p1" 0 {} 2 1 0 010000 Subtracts %p1 from %p2. > 0x0B DIV "div" "" "%p2 / %p1" 0 {} 2 1 0 010000 Divides %p2 by %p1. > 0x0C MUL "mul" "" "%p2 * %p1" 0 {} 2 1 0 010000 Multiplies %p1 by %p2. > 0x0D MOD "mod" "" "%p2 %% %p1" 0 {} 2 1 0 010000 Mods %p2 by %p1. > 0x0E AND "and" "" "%p2 && %p1" 0 {} 2 1 0 010000 Pops two elements from the stack, converts them to true/false, logically "and"s the values, and pushes the resulting truth value back on the stack as a 1/0(true/false). > 0x0F OR "or" "" "%p2 || %p1" 0 {} 2 1 0 010000 The "logical or" counterpart the the "logical and" (opcode 0x0E). Refer to that opcode for more information. > 0x10 NOT "not" "" "!%p1" 0 {} 1 1 0 010000 Pops one element from the stack converts it to a truth value, logically "not"s it, and then pushes the resulting truth value on the stack. > 0x11 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x12 POP "pop\t[%1]" "\t\t\t;" "var%1 = %p1" 2 {varoffset} 1 0 0 000000 Pops one element from the stack and assigns it to the local varitable pointed to by {varoffset}. MENTAL NOTE: assert(varoffset>=0 && varoffset 0x13 PUSHT "push\ttrue" "" "true" 0 {} 0 1 0 000000 Pushes true onto the stack. > 0x14 PUSHF "push\tfalse" "" "false" 0 {} 0 1 0 000000 Pushes false onto the stack. > 0x15 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x16 CMPGT "cmpgt" "" "%p2 > %p1" 0 {} 2 1 0 010000 Tests if %p2 is greater then %p1. > 0x17 CMPLT "cmplt" "" "%p2 < %p1" 0 {} 2 1 0 010000 Tests if %p2 is less then %p1. > 0x18 CMPGE "cmpge" "" "%p2 >= %p1" 0 {} 2 1 0 010000 Tests if %p2 is greater then or equal to %p1. > 0x19 CMPLE "cmple" "" "%p2 <= %p1" 0 {} 2 1 0 010000 Tests if %p2 is less then or equal to %p1. > 0x1A CMPNE "cmpne" "" "%p2 != %p1" 0 {} 2 1 0 010000 Tests if %p2 is not equal to %p1. > 0x1B NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x1C ADDSI "addsi\t%1H" "\t\t\t; %tc1" "UcMessage(\"%t1\")" 2 {dataoffset} 0 0 0 000000 Appends a string from the data segment {dataoffset} to the string register. > 0x1D PUSHS "pushs\t%1H" "\t\t\t; %tc1" "\"%t1\"" 2 {dataoffset} 0 1 0 000000 Pushes the string at {dataoffset} onto the stack. > 0x1E ARRC "arrc\t%1H" "\t\t\t;" "[%p,]" 2 {short} 0xFF 1 0 000000 Pops {short} number of elements from the stack, and creates an array of them, first off the stack is the first appended to the end of the array (ie. the elements were appended originally to the stack in the order 3, 2, 1 would create an array of the form {1, 2, 3}). The created array is then appended to the stack. > 0x1F PUSHI "pushi\t%1H" "\t\t\t; %d1" "0x%1" 2 {short} 0 1 0 000000 Pushes the element {short} to the stack as a signed 16bit integer. > 0x20 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x21 PUSH "push\t[%1]" "\t\t\t;" "var%1" 2 {varoffset} 0 1 0 000000 Pushes the variable stored at {varoffset} onto the stack. > 0x22 CMPEQ "cmpeq" "" "%p2 == %p1" 0 {} 2 1 0 010000 Tests if %p2 is equal to %p1. > 0x23 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x24 CALL "call\textern:[%1]" "\t\t;" "%f1(%p,)" 2 {extoffset} 0 0 1 000000 References the "external usecode function table" (Exult code calls this "externals"), with the {extoffset} value passed in the opcode call (eg: external_table[extoffset]), then "calls" that function to continue execution. > 0x25 RET "ret" "" "return" 0 {} 0 0 0 000000 Returns to the "caller" function, after showing any text remaining in the string buffer (Exult: say_string() buffer). Does not return any elements on the stack (ie: returns "void"). > 0x26 AIDX "aid\t[%1]" "\t\t\t;" "var%1[%p1]" 2 {varoffset} 1 1 0 000000 Pops one (pop v1) element off the stack (the array index), and uses it as an index of the local variable {varoffset}. (varoffset[v1]) The element obtained is then pushed onto the stack. TODO: NOTE: This opcode has been changed... need to redocument. > 0x27 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x28 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x29 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x2A NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x2B NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x2C EXIT2 "exit2" "" "exit2()" 0 {} 0 0 0 000000 Yet Another Return. Exult implements this identically to the RET opcode (0x25). > 0x2D SETR "setr" "" "rr = %p1" 0 {} 1 0 0 000000 Pops the top most element off the stack and stores it in the return register. > 0x2E ENUM "enum" "" "enum()" 0 {} 0 0 0 000000 Part one of the two opcode for...each opcode loop. Details under opcode 0x02. > 0x2F ADDSV "addsv\t[%1]" "\t\t\t;" "UcMessage(var%1)" 2 {varoffset} 0 0 0 000000 Appends the local variable pointed to by {varoffset} onto the end of the string register. > 0x30 IN "in" "\t\t\t\t;" "in(%p2, %p1)" 0 {} 2 1 0 000000 Tests if a value is in an array. Pops two elements from the stack (pop v1, then pop v2) test if any of the elements inside the array v1 are equal to the element v2 (v2 cannot be an array), and pushes the resulting truth value on the stack. > 0x31 SMTH "smth\t%1 %2" "\t\t\t;" "smth()" 4 {short,offset} 0 0 0 000000 Does something related to conversations. Only occurs (2x) in the usecode function handling the 'audition' in Britain. Current implementation produces same result as original, although we're unsure of the exact function of this opcode. (Doesn't push or pop anything) > 0x32 RTS "rts" "" "return rr" 0 {} 0 0 0 100000 (ucdump calls this "retr") Same as RET except pushes the return register onto the stack before returning. EXULT NOTE: unlike ret, it doesn't show any remaining text in the string buffer. Bug? > 0x33 SAY "say" "" "UcSay" 0 {} 0 0 0 000000 Displays the string register to the screen (as appropriate talk, sign, scroll, book, whatever). Has the side effect of clearing the string register. > 0x34 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x35 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x36 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x37 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x38 CALLIS "callis\t%i1@%b2" "\t\t; %1" "UI_%i1(%p,)" 3 {short,byte} 0xFE 1 0 000000 Calls the intrinsic {short} with {byte} number of parameters popped from the stack passed to it. Eg: if you were calling intrinsic 23 (short) with 3 (byte) parameters, and the stack looked like this: {4, 3, 2, 1} (4 was the first element pushed upon the stack), the intrinsic function call in a c-like form would look like: intrinsic23( 1, 2, 3); The intrinsic called will return a value on the stack. The intrinsic called also has the same "event" flag as the caller function. > 0x39 CALLI "calli\t%i1@%b2" "\t\t; %1, %d2" "UI_%i1(%p,)" 3 {short,byte} 0xFE 0 0 000000 Same as opcode CALLIS (0x38), except no return value. > 0x3A NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x3B NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x3C NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x3D NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x3E PUSHITM "push\titemref" "\t\t\t;" "item" 0 {} 0 1 0 000000 (ucdump & exult call this "push itemref") Pushes the identifier of the item (for which the usecode event handler is called) onto the stack. > 0x3F ABRT "abrt" "" "abrt()" 0 {} 0 0 0 000000 (ucdump calles this "exit") (exult says this is "really like a throw") Shows any text in the string register, and exits the function immediatly. ABRT also exits all calling functions, effectively stopping the usecode interpreter. > 0x40 END_CONV "end_conv" "" "end_conv()" 0 {} 0 0 0 000000 Always seems to be called right before a "goodbye", so guessing it means 'end conversation'. > 0x41 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x42 PUSHF "pushf\tflag:[%1]" "\t\t\t;" "gflags[%1]" 2 {flag} 0 1 0 000000 TODO: document > 0x43 POPF "popf\tflag:[%1]" "\t\t;" "gflags[%1] = %p1" 2 {flag} 1 0 0 000000 TODO: document > 0x44 PUSHB "pushb\t%b1H" "\t\t\t; %d1" "0x%b1" 1 {byte} 0 1 0 000000 (ucdump calls this "pushbi") TODO: document > 0x45 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x46 APUT "aput\t[%1]" "\t\t\t;" "var%1[%p1] = %p2" 2 {varoffset} 2 0 0 000000 TODO: document > 0x47 CALLE "calle\t%1H" "\t\t\t;" "calle()" 2 {short} 0 0 0 000000 # TODO: Needs more documenting, need to find the pop/push numbers. {short} == usecode function number to call TODO: document > 0x48 PUSHEID "push\teventid" "" "event" 0 {} 0 1 0 000000 (ucdump & exult calles this "push eventid") TODO: document > 0x49 NULL "null" "" "null()" 0 {} 0 0 0 000000 > 0x4a ARRA "arra" "\t\t\t\t;" "%p2 & %p1" 0 {} 2 1 0 010000 Appends second param. to the list in first param. > 0x4b POPEID "pop\teventid" "" "event = %p1" 0 {} 1 0 0 000000 # TODO: Needs more documenting (ucdump & exult calls this "pop eventid") TODO: document # Debug opcodes -- currently only found in the .es version of SI > 0x4c DBGLINE "dbgline %1" "" "// Line: %1" 2 {short} 0 0 0 000000 > 0x4d DBGFUNC "dbgfunc %1 %2 " "; %t1" "// Function: %t1 %2" 4 {short,dataoffset} 0 0 0 000000 # Fake opcodes for use with optimsations in ucxt > 0x101 LABEL "(invalid)" "" "label%f*_%1" 2 {offset} 1 0 0 000001 exult-1.2/usecode/ucxt/data/events.data0000644000175000001440000000024007225441075013656 # value:Mnemonic:Description 0 NPCProximity "" 1 DoubleClick "" 2 InternalExec "Internal call via intr. 1 or 2." 3 EggProximity "" 4 Weapon "From weapons.dat" exult-1.2/usecode/ucxt/data/Makefile.am0000644000175000001440000000057407744302712013565 ucxtdir = $(datadir)/exult if BUILD_TOOLS u7bgintrinsics.data u7siinstrics.data: ../head2data ../../bgintrinsics.h ../../siintrinsics.h ../head2data u7bgintrinsics.data u7siintrinsics.data endif ucxt_DATA = \ u7opcodes.data \ u7misc.data \ u7bgintrinsics.data \ u7siintrinsics.data EXTRA_DIST = \ events.data \ flags.data \ opcodes.txt \ u7opcodes.data \ u7misc.data exult-1.2/usecode/ucxt/data/Makefile.in0000644000175000001440000001562510061527064013574 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ ucxtdir = $(datadir)/exult ucxt_DATA = \ u7opcodes.data \ u7misc.data \ u7bgintrinsics.data \ u7siintrinsics.data EXTRA_DIST = \ events.data \ flags.data \ opcodes.txt \ u7opcodes.data \ u7misc.data subdir = usecode/ucxt/data mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(ucxt_DATA) DIST_COMMON = Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/ucxt/data/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: install-ucxtDATA: $(ucxt_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(ucxtdir) @list='$(ucxt_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(ucxtdir)/$$f"; \ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(ucxtdir)/$$f; \ done uninstall-ucxtDATA: @$(NORMAL_UNINSTALL) @list='$(ucxt_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(ucxtdir)/$$f"; \ rm -f $(DESTDIR)$(ucxtdir)/$$f; \ done tags: TAGS TAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(ucxtdir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-ucxtDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-ucxtDATA .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip install-ucxtDATA \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool uninstall uninstall-am uninstall-info-am \ uninstall-ucxtDATA @BUILD_TOOLS_TRUE@u7bgintrinsics.data u7siinstrics.data: ../head2data ../../bgintrinsics.h ../../siintrinsics.h @BUILD_TOOLS_TRUE@ ../head2data u7bgintrinsics.data u7siintrinsics.data # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/ucxt/data/flags.data0000644000175000001440000000061107225441075013450 # value:Mnemonic:Description 0x3B DidFirstScene "Went through 1st scene with Iolo" 0x3D HaveTrinsicPassword "Does the Avatar have the Trinsic Password?" 0x48 FoundStableKey "Did the Avatar find the Trinsic Stable Key?" 0x57 LeftTrinsic "???" 0x2EB AvatarIsThief "The Avatar is a thief." 0x0CC _ "Avatar's talked to LB about Weston." 0x222 _ "Avatar's talked to Alina (Weston's Wife)" exult-1.2/usecode/ucxt/head2data.cc0000644000175000001440000000405407716452216012745 #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include using std::cout; using std::cerr; using std::endl; using std::ostream; using std::string; using std::setfill; using std::setbase; using std::vector; using std::setw; using std::ios; using std::ofstream; #ifndef __STRING #if defined __STDC__ && __STDC__ #define __STRING(x) #x #else #define __STRING(x) "x" #endif #endif void bg_out(const string &fname) { ofstream o; o.open(fname.c_str()); if(o.fail()) { cerr << "error: could not open `" << fname << "` for writing" << endl; exit(1); } o << setfill('0') << setbase(16); o.setf(ios::uppercase); #define USECODE_INTRINSIC_PTR(NAME) std::string(__STRING(NAME)) std::string bgut[] = { #include "bgintrinsics.h" }; #undef USECODE_INTRINSIC_PTR o << "" << endl; for(unsigned int i=0; i<0x100; i++) o << "\t<0x" << setw(2) << i << "> " << bgut[i] << "_" << setw(2) << i << " " << endl; o << "" << endl; o.close(); } void si_out(const string &fname) { ofstream o; o.open(fname.c_str()); if(o.fail()) { cerr << "error: could not open `" << fname << "` for writing" << endl; exit(1); } o << setfill('0') << setbase(16); o.setf(ios::uppercase); #define USECODE_INTRINSIC_PTR(NAME) std::string(__STRING(NAME)) std::string siut[] = { #include "siintrinsics.h" }; #undef USECODE_INTRINSIC_PTR o << "" << endl; for(unsigned int i=0; i<0x100; i++) o << "\t<0x" << setw(2) << i << "> " << siut[i] << "_" << setw(2) << i << " " << endl; o << "" << endl; o.close(); } int main(int argc, char **argv) { if(argc!=3) { cout << "usage:" << endl << "\thead2data " << endl << endl << "\tWhere the output files are the relative pathnames to the datafiles" << endl << "\tto be output." << endl << "\teg. head2data data/u7bgintrinsics.data data/u7siintrinsics.data" << endl; return 1; } bg_out(string(argv[1])); si_out(string(argv[2])); return 0; } exult-1.2/usecode/ucxt/Makefile.am0000644000175000001440000000055607514634106012654 INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/../include -I$(srcdir)/../../../conf -I$(srcdir)/../.. \ -I$(srcdir)/../../.. -I$(srcdir)/.. $(INCDIRS) $(DEBUG_FLAGS) \ $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" $(WARNINGS) if BUILD_TOOLS SUBDIRS = . src include data Docs noinst_PROGRAMS = head2data endif head2data_SOURCES = head2data.cc exult-1.2/usecode/ucxt/Makefile.in0000644000175000001440000003143610061527062012657 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/../include -I$(srcdir)/../../../conf -I$(srcdir)/../.. \ -I$(srcdir)/../../.. -I$(srcdir)/.. $(INCDIRS) $(DEBUG_FLAGS) \ $(CPPFLAGS) -DEXULT_DATADIR=\"$(EXULT_DATADIR)\" $(WARNINGS) @BUILD_TOOLS_TRUE@SUBDIRS = . src include data Docs @BUILD_TOOLS_TRUE@noinst_PROGRAMS = head2data head2data_SOURCES = head2data.cc subdir = usecode/ucxt mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @BUILD_TOOLS_TRUE@noinst_PROGRAMS = head2data$(EXEEXT) @BUILD_TOOLS_FALSE@noinst_PROGRAMS = PROGRAMS = $(noinst_PROGRAMS) am_head2data_OBJECTS = head2data.$(OBJEXT) head2data_OBJECTS = $(am_head2data_OBJECTS) head2data_LDADD = $(LDADD) head2data_DEPENDENCIES = head2data_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/head2data.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ DIST_SOURCES = $(head2data_SOURCES) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = Makefile.am Makefile.in DIST_SUBDIRS = . src include data Docs SOURCES = $(head2data_SOURCES) all: all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/ucxt/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) head2data$(EXEEXT): $(head2data_OBJECTS) $(head2data_DEPENDENCIES) @rm -f head2data$(EXEEXT) $(CXXLINK) $(head2data_LDFLAGS) $(head2data_OBJECTS) $(head2data_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/head2data.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done for subdir in $(DIST_SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-recursive distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ clean-generic clean-libtool clean-noinstPROGRAMS \ clean-recursive distclean distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-recursive \ distclean-tags distdir dvi dvi-am dvi-recursive info info-am \ info-recursive install install-am install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive tags tags-recursive uninstall \ uninstall-am uninstall-info-am uninstall-info-recursive \ uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/ucxt/include/0000777000175000001440000000000010062225333012307 5exult-1.2/usecode/ucxt/include/ops.h0000644000175000001440000001644707724430454013226 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OPCODES_H #define OPCODES_H #include #include #include #include #include #include "Configuration.h" #include "ucc.h" std::vector qnd_ocsplit(const std::string &s); void map_type_size(const std::vector ¶m_types, std::vector > ¶m_sizes); static inline std::string strip_backticks(const std::string &s) { if(s.size()==2 && s[0]=='`' && s[1]=='`') return std::string(); else if(s[0]=='`' && s[s.size()-1]=='`') return s.substr(1, s.size()-2); return s; } /* Just a basic class to tie together half a dozen initialisation routines. */ class ucxtInit { public: ucxtInit(const std::string &new_ucxtdata=std::string("ucxt.data")) : ucxtdata(new_ucxtdata) { }; void init(const Configuration &config, const UCOptions &options); private: std::string get_datadir(const Configuration &config, const UCOptions &options); void misc(); void opcodes(); void intrinsics(const std::string &intrinsics_data, const std::string &intrinsics_root); const std::string ucxtdata; std::string datadir; std::string opcodes_data; std::string opcodes_root; std::string misc_data; std::string misc_root; std::string bg_intrinsics_data; std::string bg_intrinsics_root; std::string si_intrinsics_data; std::string si_intrinsics_root; }; class UCOpcodeData { public: UCOpcodeData() : opcode(0x00), num_bytes(0), num_pop(0), num_push(0), call_effect(0), flag_return(false), flag_paren(false), flag_indent_inc(false), flag_indent_dec(false), flag_indent_tmpinc(false), flag_indent_tmpdec(false) {}; UCOpcodeData(unsigned int op, const Configuration::KeyTypeList &ktl) : opcode(op), num_bytes(0), num_pop(0), num_push(0), call_effect(0), flag_return(false), flag_paren(false), flag_indent_inc(false), flag_indent_dec(false), flag_indent_tmpinc(false), flag_indent_tmpdec(false) { for(Configuration::KeyTypeList::const_iterator k=ktl.begin(); k!=ktl.end(); ++k) { switch(k->first[0]) { case 'a': if(k->first=="asm_nmo") asm_nmo = strip_backticks(k->second); else if(k->first=="asm_comment") asm_comment = strip_backticks(k->second); break; case 'c': if(k->first=="call_effect") call_effect = strtol(k->second.c_str(), 0, 0); break; case 'i': if(k->first=="indent_inc/") flag_indent_inc=true; else if(k->first=="indent_dec/") flag_indent_dec=true; else if(k->first=="indent_tmpinc/") flag_indent_tmpinc=true; else if(k->first=="indent_tmpdec/") flag_indent_tmpdec=true; break; case 'n': if(k->first=="name") name = strip_backticks(k->second); else if(k->first=="num_bytes") num_bytes = strtol(k->second.c_str(), 0, 0); else if(k->first=="num_pop") num_pop = strtol(k->second.c_str(), 0, 0); else if(k->first=="num_push") num_push = strtol(k->second.c_str(), 0, 0); break; case 'p': if(k->first=="param_types") param_types = qnd_ocsplit(k->second); else if(k->first=="paren/") flag_paren=true; break; case 'r': if(k->first=="return/") flag_return=true; break; case 'u': if(k->first=="ucs_nmo") ucs_nmo = strip_backticks(k->second); break; case '!': // ignore, it's a comment or something. break; default: std::cerr << "invalid key `" << k->first << "` value `" << k->second << "`" << std::endl; } } map_type_size(param_types, param_sizes); }; UCOpcodeData(const std::vector &v) { if((v.size()==12)==false) { std::cerr << "Error in opcodes file:" << std::endl; for(unsigned int i=0; i=6); flag_return = (v[11][0]=='0') ? false : true; flag_paren = (v[11][1]=='0') ? false : true; flag_indent_inc = (v[11][2]=='0') ? false : true; flag_indent_dec = (v[11][3]=='0') ? false : true; flag_indent_tmpinc = (v[11][4]=='0') ? false : true; flag_indent_tmpdec = (v[11][5]=='0') ? false : true; map_type_size(param_types, param_sizes); }; void dump(std::ostream &o) { o << "opcode: " << opcode << std::endl; o << "name: " << name << std::endl; o << "asm_nmo: " << asm_nmo << std::endl; o << "asm_comment: " << asm_comment << std::endl; o << "ucs_nmo: " << ucs_nmo << std::endl; o << "num_bytes: " << num_bytes << std::endl; o << "param_types: "; for(typeof(param_types.begin()) i=param_types.begin(); i!=param_types.end(); i++) o << *i << ','; o << std::endl; o << "num_pop: " << num_pop << std::endl; o << "num_push: " << num_push << std::endl; o << "call_effect: " << call_effect << std::endl; o << "flag_return: " << flag_return << std::endl; o << "flag_paren: " << flag_paren << std::endl; o << "flag_indent_inc: " << flag_indent_inc << std::endl; o << "flag_indent_dec: " << flag_indent_dec << std::endl; o << "flag_indent_tmpinc: " << flag_indent_tmpinc << std::endl; o << "flag_indent_tmpdec: " << flag_indent_tmpdec << std::endl; }; unsigned int opcode; std::string name; std::string asm_nmo; std::string asm_comment; std::string ucs_nmo; unsigned int num_bytes; unsigned int num_pop; unsigned int num_push; unsigned int call_effect; bool flag_return; bool flag_paren; bool flag_indent_inc; bool flag_indent_dec; bool flag_indent_tmpinc; bool flag_indent_tmpdec; std::vector param_types; // values caluclated from param_types std::vector > param_sizes; // .first==size of parameter in bytes .second==whether to treat it as a relative offset and calculate for it }; extern std::vector opcode_table_data; extern std::vector > opcode_jumps; extern std::map uc_intrinsics; #endif exult-1.2/usecode/ucxt/include/ucc.h0000644000175000001440000000557107724430454013173 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UCC_H #define UCC_H #include #include class UCc; class UCc { public: UCc(const unsigned int offset=0, const unsigned int id=0, const std::vector ¶ms=std::vector()) : _id(id), _offset(offset), _params(params), _tagged(false) {}; UCc(const unsigned int id, const std::string &miscstr) : _id(id), _miscstr(miscstr) {}; //UCc() : _id(0), _offset(0), _tagged(false) {}; unsigned int _id; std::string _miscstr; unsigned int _offset; std::vector _params; std::vector _params_parsed; bool _tagged; std::vector _jump_offsets; /* A temporary array to hold the items this opcode theoretically popped from the stack. This should probably go in it's own wrapper class with the current UCc. */ std::vector _popped; }; class UCOptions { public: UCOptions() : output_extern_header(false), noconf(false), rawops(false), autocomment(false), uselesscomment(false), verbose(false), very_verbose(false), ucdebug(false), basic(false), output_list(false), output_asm(false), output_ucs(false), output_flag(false), output_trans_table(false), mode_all(false), mode_dis(false), force_ext32(false), _game(GAME_BG) {}; bool game_bg() const { return _game==GAME_BG; }; bool game_si() const { return _game==GAME_SI; }; bool game_u8() const { return _game==GAME_U8; }; bool output_extern_header; bool noconf; bool rawops; bool autocomment; bool uselesscomment; bool verbose; bool very_verbose; bool ucdebug; bool basic; bool output_list; bool output_asm; bool output_ucs; bool output_flag; bool output_trans_table; bool mode_all; bool mode_dis; bool force_ext32; // force ext32 function format output for all functions //private: unsigned int _game; enum { GAME_BG=1, GAME_SI=2, GAME_U8=3 }; }; #endif exult-1.2/usecode/ucxt/include/ucdata.h0000644000175000001440000000441007724430454013651 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UCDATA_H #define UCDATA_H #include #include #include #include #include "ucfunc.h" class UCData { public: UCData(); ~UCData(); void dump_unknown_opcodes(); void dump_unknown_intrinsics(); void parse_params(const unsigned int argc, char **argv); void open_usecode(const std::string &filename); void load_funcs(); void disassamble(); void dump_flags(std::ostream &o); void output_extern_header(std::ostream &o); std::string output_redirect() const { return _output_redirect; }; std::string input_usecode_file() const { return _input_usecode_file; }; bool fail() const { return _file.fail(); }; const std::map &funcmap() { return _funcmap; }; const UCOptions &opt() { return options; }; UCOptions options; private: void file_open(const std::string &filename); void file_seek_start() { _file.seekg(0, std::ios::beg); }; void file_seek_end() { _file.seekg(0, std::ios::end); }; std::ifstream _file; std::string _output_redirect; std::string _input_usecode_file; unsigned int _funcid; std::vector _codes; std::vector _funcs; /* Just a quick mapping between funcs and basic data on them. Just something we can quickly pass to the parsing functions so we don't have to give them an entire function to play with. */ FuncMap _funcmap; long _search_opcode; long _search_intrinsic; std::vector search_funcs; }; #endif exult-1.2/usecode/ucxt/include/ucfunc.h0000644000175000001440000002261407724430454013701 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UCFUNC_H #define UCFUNC_H #include #include #include #include #include #include "ucc.h" class UCFuncSet { public: UCFuncSet(unsigned int new_funcid, unsigned int new_num_args, bool new_return_var, const std::string &new_funcname) : funcid(new_funcid), num_args(new_num_args), return_var(new_return_var), funcname(new_funcname) {}; ~UCFuncSet() {}; unsigned int funcid; // the id of the function unsigned int num_args; // the number of arguments bool return_var; // if true, the function returns a variable std::string funcname; // the name of the function, if it has one }; typedef std::map FuncMap; typedef std::pair FuncMapPair; //#define DEBUG_GOTOSET const unsigned int SIZEOF_USHORT = 2; class FlagData { public: enum { SETFLAG=false, GETFLAG=true }; /* SETFLAG=UCC_POPF, GETFLAG=UCC_PUSHF */ enum { POP=false, PUSH=true}; FlagData(const long func, const unsigned int offset, const unsigned int flag, const bool access) : _func(func), _offset(offset), _flag(flag), _access(access) {}; long func() const { return _func; }; unsigned int offset() const { return _offset; }; unsigned int flag() const { return _flag; }; bool access() const { return _access; }; private: long _func; unsigned int _offset; unsigned int _flag; bool _access; }; class SortFlagDataLessFlag { public: bool operator()(const FlagData &fd1, const FlagData &fd2) const { return (fd1.flag()fd2.flag()) ? false : (fd1.func()fd2.func()) ? false : (fd1.offset()flag()flag()) ? true : (fd1->flag()>fd2->flag()) ? false : (fd1->func()func()) ? true : (fd1->func()>fd2->func()) ? false : (fd1->offset()offset()); }; }; class SortFlagDataLessFunc { public: bool operator()(const FlagData &fd1, const FlagData &fd2) const { return (fd1.func()fd2.func()) ? false : (fd1.flag()fd2.flag()) ? false : (fd1.offset()func()func()) ? true : (fd1->func()>fd2->func()) ? false : (fd1->flag()flag()) ? true : (fd1->flag()>fd2->flag()) ? false : (fd1->offset()offset()); }; }; class UCNode; class UCNode { public: UCNode(UCc *newucc=0) : ucc(newucc) { }; ~UCNode() { }; UCc *ucc; std::vector nodelist; }; #include "ops.h" class GotoSet { public: GotoSet() : _offset(0) {}; GotoSet(const unsigned int offset, UCc *ucc) : _offset(offset) { add(ucc); }; GotoSet(UCc *ucc) : _offset(ucc->_offset) { add(ucc); }; std::vector > &operator()() { return _uccs; }; UCc &operator[](const unsigned int i) { return *(_uccs[i].first); }; unsigned int size() const { return _uccs.size(); }; void add(UCc *ucc, bool gc=false) { _uccs.push_back(std::pair(ucc, gc)); }; /* Just a quick function to remove all the Uccs in _uccs marked for garbage collection. */ void gc() { for(GotoSet::iterator j=_uccs.begin(); j!=_uccs.end();) { #ifdef DEBUG_GOTOSET std::cout << "OP: " << opcode_table_data[j->first->_id].ucs_nmo << '\t' << j->second; #endif if(j->second==true) { /* ok, we need to take into consideration that the iterator we're removing might ==_uccs.begin() */ bool begin=false; if(j==_uccs.begin()) begin=true; #ifdef DEBUG_GOTOSET std::cout << "\tremoved"; #endif GotoSet::iterator rem(j); if(begin==false) j--; _uccs.erase(rem); if(begin==true) j=_uccs.begin(); else j++; if(j==_uccs.end()) std::cout << "POTENTIAL PROBLEM" << std::endl; } else j++; #ifdef DEBUG_GOTOSET std::cout << std::endl; #endif } }; unsigned int offset() const { return _offset; }; typedef std::vector >::iterator iterator; private: unsigned int _offset; std::vector > _uccs; }; class UCOpcodeData; class UCFunc { public: UCFunc() : _offset(0), _funcid(0), _funcsize(0), _bodyoffset(0), _datasize(0), _codeoffset(0), _num_args(0), _num_locals(0), _num_externs(0), return_var(false), debugging_info(false), debugging_offset(0), ext32(false) {}; bool output_list(std::ostream &o, unsigned int funcno, const UCOptions &options); bool output_ucs(std::ostream &o, const FuncMap &funcmap, const std::map &intrinsics, const UCOptions &options); std::ostream &UCFunc::output_ucs_funcname(std::ostream &o, const FuncMap &funcmap); std::ostream &output_ucs_funcname(std::ostream &o, const FuncMap &funcmap, unsigned int funcid, unsigned int numargs, bool return_var); void output_ucs_node(std::ostream &o, const FuncMap &funcmap, UCNode* ucn, const std::map &intrinsics, unsigned int indent, const UCOptions &options); void output_ucs_data(std::ostream &o, const FuncMap &funcmap, const std::map &intrinsics, const UCOptions &options, unsigned int indent); void output_ucs_opcode(std::ostream &o, const FuncMap &funcmap, const std::vector &optab, const UCc &op, const std::map &intrinsics, unsigned int indent); void parse_ucs(const FuncMap &funcmap, const std::map &intrinsics, const UCOptions &options); void parse_ucs_pass1(std::vector &nodes); void parse_ucs_pass2(std::vector &gotoset, const FuncMap &funcmap, const std::map &intrinsics); std::vector parse_ucs_pass2a(std::vector >::reverse_iterator current, std::vector > &vec, unsigned int opsneeded, const FuncMap &funcmap, const std::map &intrinsics); void parse_ucs_pass3(std::vector &gotoset, const std::map &intrinsics); bool output_asm(std::ostream &o, const FuncMap &funcmap, const std::map &intrinsics, const UCOptions &options); void output_asm_data(std::ostream &o); void output_asm_opcode(std::ostream &o, const FuncMap &funcmap, const std::vector &optab, const std::map &intrinsics, const UCc &op, const UCOptions &options); void output_raw_opcodes(std::ostream &o, const UCc &op); bool output_tt(std::ostream &o); // private: std::vector gotoset; std::streampos _offset; // offset to start of function unsigned int _funcid; // the id of the function unsigned int _funcsize; // the size of the function (bytes) std::streampos _bodyoffset; // the file position after the header is read unsigned int _datasize; // the size of the data block std::map > _data; // contains the entire data segment in offset from start of segment, and string data pairs std::streampos _codeoffset; // the offset to the start of the code segment unsigned int _num_args; // the number of arguments unsigned int _num_locals; // the number of local variables unsigned int _num_externs; // the number of external function id's std::vector _externs; // the external function id's std::vector _opcodes; bool return_var; // does the function return a variable? bool debugging_info; unsigned int debugging_offset; std::string funcname; bool ext32; // is this function an extended function? unsigned int codesize() const { return _funcsize - _datasize; }; UCNode node; }; void readbin_U7UCFunc(std::ifstream &f, UCFunc &ucf, const UCOptions &options); void readbin_U8UCFunc(std::ifstream &f, UCFunc &ucf); #endif exult-1.2/usecode/ucxt/include/Makefile.am0000644000175000001440000000007407500351776014276 noinst_HEADERS = \ ops.h \ ucc.h \ ucdata.h \ ucfunc.h exult-1.2/usecode/ucxt/include/Makefile.in0000644000175000001440000001561710061527063014306 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ noinst_HEADERS = \ ops.h \ ucc.h \ ucdata.h \ ucfunc.h subdir = usecode/ucxt/include mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = HEADERS = $(noinst_HEADERS) DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in all: all-am .SUFFIXES: mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/ucxt/include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am info info-am install \ install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool tags uninstall \ uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/ucsched.h0000644000175000001440000000566707730475633011444 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UCSCHED_H #define _UCSCHED_H class Game_object; class Usecode_value; class Usecode_internal; #include "tqueue.h" /* * A class for executing usecode at a scheduled time: */ class Usecode_script : public Time_sensitive { static int count; // Total # of these around. static Usecode_script *first;// ->chain of all of them. Usecode_script *next, *prev; // Next/prev. in global chain. Game_object *obj; // From objval. Usecode_value *code; // Array of code to execute. int cnt; // Length of arrval. int i; // Current index. int frame_index; // For taking steps. bool no_halt; // 1 to ignore halt(). bool must_finish; // 1 to finish before deleting. int delay; // Used for restoring. // For restore: Usecode_script(Game_object *item, Usecode_value *cd, int findex, int nhalt, int del); public: Usecode_script(Game_object *o, Usecode_value *cd = 0); ~Usecode_script(); void start(long delay = 1); // Start after 'delay' msecs. long get_delay() const { return delay; } void halt(); // Stop executing. bool is_no_halt() const // Is the 'no_halt' flag set? { return no_halt; } int is_activated() // Started already? { return i > 0; } void add(int v1); // Append new instructions: void add(int v1, int v2); void add(int v1, const char *str); void add(int *vals, int cnt); Usecode_script& operator<<(int v) { add(v); return *this; } inline void activate_egg(Usecode_internal *usecode, Game_object *e); static int get_count() { return count; } // Find for given item. static Usecode_script *find(Game_object *srch, Usecode_script *last_found = 0); static void terminate(Game_object *obj); static void clear(); // Delete all. // Remove all whose objs. are too far. static void purge(Tile_coord pos, int dist); virtual void handle_event(unsigned long curtime, long udata); int exec(Usecode_internal *usecode, bool finish); // Move object in given direction. void step(Usecode_internal *usecode, int dir); // Save/restore. int save(unsigned char *buf, int buflen); static Usecode_script *restore(Game_object *item, unsigned char *buf, int buflen); void print(std::ostream& out); // Print values. }; #endif exult-1.2/usecode/siintrinsics.h0000644000175000001440000003332407776726135012544 /* * Siintrinsics.h - Intrinsic table for Serpent Isle. * * Note: This is used in the virtual machine and the Usecode compiler. * * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ USECODE_INTRINSIC_PTR(get_random), // 0 USECODE_INTRINSIC_PTR(execute_usecode_array), // 1 USECODE_INTRINSIC_PTR(delayed_execute_usecode_array), // 2 USECODE_INTRINSIC_PTR(show_npc_face), // Guess // 3 USECODE_INTRINSIC_PTR(remove_npc_face), // Guess // 4 USECODE_INTRINSIC_PTR(show_npc_face0), // 5 USECODE_INTRINSIC_PTR(show_npc_face1), // 6 USECODE_INTRINSIC_PTR(remove_npc_face0), // Guess! // 7 USECODE_INTRINSIC_PTR(remove_npc_face1), // 8 USECODE_INTRINSIC_PTR(set_conversation_slot), // 9 USECODE_INTRINSIC_PTR(UNKNOWN), // UNUSED // 0xa USECODE_INTRINSIC_PTR(UNKNOWN), // UNUSED // 0xb USECODE_INTRINSIC_PTR(add_answer), // 0xc USECODE_INTRINSIC_PTR(remove_answer), // 0xd USECODE_INTRINSIC_PTR(push_answers), // 0xe USECODE_INTRINSIC_PTR(pop_answers), // 0xf USECODE_INTRINSIC_PTR(clear_answers), // 0x10 USECODE_INTRINSIC_PTR(select_from_menu), // 0x11 USECODE_INTRINSIC_PTR(select_from_menu2), // 0x12 USECODE_INTRINSIC_PTR(input_numeric_value), // 0x13 USECODE_INTRINSIC_PTR(set_item_shape), // 0x14 USECODE_INTRINSIC_PTR(find_nearest), // 0x15 USECODE_INTRINSIC_PTR(play_sound_effect), // 0x16 USECODE_INTRINSIC_PTR(die_roll), // 0x17 USECODE_INTRINSIC_PTR(get_item_shape), // 0x18 USECODE_INTRINSIC_PTR(get_item_usability), // 0x19 USECODE_INTRINSIC_PTR(get_item_frame), // 0x1a USECODE_INTRINSIC_PTR(set_item_frame), // 0x1b USECODE_INTRINSIC_PTR(get_item_quality), // 0x1c USECODE_INTRINSIC_PTR(set_item_quality), // 0x1d USECODE_INTRINSIC_PTR(get_item_quantity), // 0x1e USECODE_INTRINSIC_PTR(set_item_quantity), // 0x1f USECODE_INTRINSIC_PTR(get_object_position), // 0x20 USECODE_INTRINSIC_PTR(get_distance), // 0x21 USECODE_INTRINSIC_PTR(find_direction), // 0x22 USECODE_INTRINSIC_PTR(get_npc_object), // 0x23 USECODE_INTRINSIC_PTR(get_schedule_type), // 0x24 USECODE_INTRINSIC_PTR(set_schedule_type), // 0x25 USECODE_INTRINSIC_PTR(add_to_party), // 0x26 USECODE_INTRINSIC_PTR(remove_from_party), // 0x27 USECODE_INTRINSIC_PTR(get_npc_prop), // 0x28 USECODE_INTRINSIC_PTR(set_npc_prop), // 0x29 USECODE_INTRINSIC_PTR(get_avatar_ref), // 0x2a USECODE_INTRINSIC_PTR(get_party_list), // 0x2b USECODE_INTRINSIC_PTR(create_new_object), // 0x2c - Known USECODE_INTRINSIC_PTR(create_new_object2), // 0x2d USECODE_INTRINSIC_PTR(set_last_created), // 0x2e USECODE_INTRINSIC_PTR(update_last_created), // 0x2f - Known USECODE_INTRINSIC_PTR(get_npc_name), // 0x30 USECODE_INTRINSIC_PTR(count_objects), // 0x31 USECODE_INTRINSIC_PTR(find_object), // 0x32 USECODE_INTRINSIC_PTR(get_cont_items), // 0x33 - Appears correct USECODE_INTRINSIC_PTR(remove_party_items), // 0x34 USECODE_INTRINSIC_PTR(add_party_items), // 0x35 USECODE_INTRINSIC_PTR(add_cont_items), // 0x36 USECODE_INTRINSIC_PTR(remove_cont_items), // 0x37 - SI Only ??? USECODE_INTRINSIC_PTR(UNKNOWN), // 0x38 - Si Only USECODE_INTRINSIC_PTR(play_music), // 0x39 - Known USECODE_INTRINSIC_PTR(npc_nearby), // 0x3a USECODE_INTRINSIC_PTR(npc_nearby2), // 0x3b Guess. USECODE_INTRINSIC_PTR(find_nearby_avatar), // 0x3c USECODE_INTRINSIC_PTR(is_npc), // 0x3d - Known USECODE_INTRINSIC_PTR(display_runes), // 0x3e USECODE_INTRINSIC_PTR(click_on_item), // 0x3f USECODE_INTRINSIC_PTR(error_message), // 0x40 - Error Message USECODE_INTRINSIC_PTR(find_nearby), // 0x41 - Known // Yes, these both seem to be 'give_last_created': USECODE_INTRINSIC_PTR(give_last_created), // 0x42 USECODE_INTRINSIC_PTR(give_last_created), // 0x43 USECODE_INTRINSIC_PTR(is_dead), // 0x44 USECODE_INTRINSIC_PTR(game_hour), // 0x45 - Correct USECODE_INTRINSIC_PTR(game_minute), // 0x46 - Correct USECODE_INTRINSIC_PTR(get_npc_number), // 0x47 - Guess USECODE_INTRINSIC_PTR(part_of_day), // 0x48 USECODE_INTRINSIC_PTR(get_alignment), // 0x49 USECODE_INTRINSIC_PTR(set_alignment), // 0x4a USECODE_INTRINSIC_PTR(move_object), // 0x4b USECODE_INTRINSIC_PTR(remove_npc), // 0x4c USECODE_INTRINSIC_PTR(item_say), // 0x4d USECODE_INTRINSIC_PTR(clear_item_say), // 0x4e USECODE_INTRINSIC_PTR(projectile_effect), // 0x4f USECODE_INTRINSIC_PTR(get_lift), // 0x50 USECODE_INTRINSIC_PTR(set_lift), // 0x51 USECODE_INTRINSIC_PTR(get_weather), // 0x52 USECODE_INTRINSIC_PTR(set_weather), // 0x53 USECODE_INTRINSIC_PTR(sit_down), // 0x54 - Known (is it???) // Packing USECODE_INTRINSIC_PTR(summon), // 0x55 USECODE_INTRINSIC_PTR(si_display_map), // 0x56 USECODE_INTRINSIC_PTR(kill_npc), // 0x57 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x58 USECODE_INTRINSIC_PTR(set_attack_mode), // 0x59 USECODE_INTRINSIC_PTR(get_attack_mode), // 0x5a USECODE_INTRINSIC_PTR(set_opponent), // 0x5b // End pack USECODE_INTRINSIC_PTR(get_oppressor), // 0x5c USECODE_INTRINSIC_PTR(get_weapon), // 0x5d USECODE_INTRINSIC_PTR(set_oppressor), // Guess // 0x5e USECODE_INTRINSIC_PTR(UNKNOWN), // 0x5f UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x60 UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x61 UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x62 UNUSED USECODE_INTRINSIC_PTR(resurrect), // Guess // 0x63 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x64 USECODE_INTRINSIC_PTR(get_body_npc), // 0x65 USECODE_INTRINSIC_PTR(add_spell), // 0x66 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x67 Remove all spells???? USECODE_INTRINSIC_PTR(sprite_effect), // 0x68 USECODE_INTRINSIC_PTR(explode), // 0x69 USECODE_INTRINSIC_PTR(book_mode), // 0x6a - Known USECODE_INTRINSIC_PTR(UNKNOWN), // 0x6b USECODE_INTRINSIC_PTR(cause_light), // 0x6c USECODE_INTRINSIC_PTR(get_barge), // 0x6d USECODE_INTRINSIC_PTR(earthquake), // 0x6e USECODE_INTRINSIC_PTR(is_pc_female), // 0x6f - Known USECODE_INTRINSIC_PTR(UNKNOWN), // 0x70 UNUSED USECODE_INTRINSIC_PTR(halt_scheduled), // 0x71 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x72 +++++CauseBlackout (ucdump.c) USECODE_INTRINSIC_PTR(get_array_size), // 0x73 USECODE_INTRINSIC_PTR(save_pos), // 0x74 USECODE_INTRINSIC_PTR(teleport_to_saved_pos), // 0x75 USECODE_INTRINSIC_PTR(apply_damage), // 0x76 USECODE_INTRINSIC_PTR(is_pc_inside), // 0x77 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x78 UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x79 UNUSED USECODE_INTRINSIC_PTR(get_timer), // 0x7a USECODE_INTRINSIC_PTR(set_timer), // 0x7b USECODE_INTRINSIC_PTR(wearing_fellowship), // 0x7c USECODE_INTRINSIC_PTR(mouse_exists), // 0x7d USECODE_INTRINSIC_PTR(get_speech_track), // 0x7e USECODE_INTRINSIC_PTR(flash_mouse), // 0x7f USECODE_INTRINSIC_PTR(get_item_frame_rot), // 0x80 Guess USECODE_INTRINSIC_PTR(set_item_frame_rot), // 0x81 Guess USECODE_INTRINSIC_PTR(on_barge), // 0x82 Guess USECODE_INTRINSIC_PTR(get_container), // 0x83 USECODE_INTRINSIC_PTR(remove_item), // 0x84 - Known USECODE_INTRINSIC_PTR(init_conversation), // 0x85 Guess USECODE_INTRINSIC_PTR(end_conversation), // 0x86 Guess USECODE_INTRINSIC_PTR(reduce_health), // 0x87 Guess USECODE_INTRINSIC_PTR(is_readied), // 0x88 USECODE_INTRINSIC_PTR(restart_game), // 0x89 USECODE_INTRINSIC_PTR(start_speech), // 0x8a USECODE_INTRINSIC_PTR(run_endgame), // 0x8b StartEndGame (ucdump.c) USECODE_INTRINSIC_PTR(UNKNOWN), // 0x8c UNUSED USECODE_INTRINSIC_PTR(nap_time), // 0x8d USECODE_INTRINSIC_PTR(advance_time), // 0x8e USECODE_INTRINSIC_PTR(in_usecode), // 0x8f USECODE_INTRINSIC_PTR(UNKNOWN), // 0x90 USECODE_INTRINSIC_PTR(obj_sprite_effect), // 0x91 USECODE_INTRINSIC_PTR(attack_avatar), // 0x92 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x93 ++++Stop_attacking_avatar()?? USECODE_INTRINSIC_PTR(path_run_usecode), // 0x94 - Known USECODE_INTRINSIC_PTR(UNKNOWN), // 0x95 UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x96 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x97 UNUSED USECODE_INTRINSIC_PTR(close_gumps), // Guess // 0x98 USECODE_INTRINSIC_PTR(item_say), // 0x99 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9a USECODE_INTRINSIC_PTR(in_gump_mode), // Guess // 0x9b // Packing!!! USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9c USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9d UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9e USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9f // End Pack USECODE_INTRINSIC_PTR(is_not_blocked), // 0xa0 USECODE_INTRINSIC_PTR(play_sound_effect2), // 0xA1 - Known USECODE_INTRINSIC_PTR(direction_from), // 0xa2 USECODE_INTRINSIC_PTR(get_item_flag), // 0xA3 - Known USECODE_INTRINSIC_PTR(set_item_flag), // 0xA4 - Known USECODE_INTRINSIC_PTR(clear_item_flag), // 0xA5 - Known USECODE_INTRINSIC_PTR(get_skin_colour), // 0xa6 USECODE_INTRINSIC_PTR(set_path_failure), // 0xa7 USECODE_INTRINSIC_PTR(fade_palette), // 0xa8 // This one is used just for sleeping: USECODE_INTRINSIC_PTR(fade_palette), // 0xa9 // USECODE_INTRINSIC_PTR(get_party_ids), // 0xaa USECODE_INTRINSIC_PTR(get_party_list2), // 0xaa USECODE_INTRINSIC_PTR(in_combat), // 0xab USECODE_INTRINSIC_PTR(is_water), // 0xac USECODE_INTRINSIC_PTR(UNKNOWN), // 0xad UNUSED USECODE_INTRINSIC_PTR(set_camera), // 0xae USECODE_INTRINSIC_PTR(UNKNOWN), // 0xaf UNUSED USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb0 UNUSED USECODE_INTRINSIC_PTR(telekenesis), // 0xb1 USECODE_INTRINSIC_PTR(a_or_an), // 0xb2 Return correct article for argument ('a' or 'an') USECODE_INTRINSIC_PTR(set_polymorph), // 0xb3 Set Polymorph USECODE_INTRINSIC_PTR(revert_schedule), // 0xb4 Reverts to static schedule USECODE_INTRINSIC_PTR(modify_schedule), // 0xb5 Updates the schedule at a specific time USECODE_INTRINSIC_PTR(set_new_schedules), // 0xb6 Set New Schedules USECODE_INTRINSIC_PTR(run_schedule), // 0xb7 Run the scheduled activity USECODE_INTRINSIC_PTR(get_temperature), // 0xb8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb9 UNUSED USECODE_INTRINSIC_PTR(set_temperature), // 0xba USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbb UNUSED USECODE_INTRINSIC_PTR(get_npc_id), // 0xbc - Known USECODE_INTRINSIC_PTR(set_npc_id), // 0xbd - Known USECODE_INTRINSIC_PTR(get_readied), // Guess // 0xbe // USECODE_INTRINSIC_PTR(add_removed_npc), // 0xbf USECODE_INTRINSIC_PTR(approach_avatar), // 0xbf USECODE_INTRINSIC_PTR(set_barge_dir), // 0xc0 USECODE_INTRINSIC_PTR(si_path_run_usecode), // 0xc1 USECODE_INTRINSIC_PTR(is_on_keyring), // 0xc2 USECODE_INTRINSIC_PTR(add_to_keyring), // 0xc3 USECODE_INTRINSIC_PTR(remove_from_area), // 0xc4 USECODE_INTRINSIC_PTR(infravision), // 0xc5 USECODE_INTRINSIC_PTR(set_intercept_item), // 0xc6 (Exult) USECODE_INTRINSIC_PTR(printf), // 0xc7 (Exult) USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xca USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xce USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xda USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xde USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xea USECODE_INTRINSIC_PTR(UNKNOWN), // 0xeb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xec USECODE_INTRINSIC_PTR(UNKNOWN), // 0xed USECODE_INTRINSIC_PTR(UNKNOWN), // 0xee USECODE_INTRINSIC_PTR(UNKNOWN), // 0xef USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfa USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfe USECODE_INTRINSIC_PTR(UNKNOWN), // 0xff exult-1.2/usecode/ucdebugging.h0000644000175000001440000000652207724430454012273 /* * ucdebugging.h - Debugging-related functions for usecode * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UCDEBUGGING_H #define _UCDEBUGGING_H #include class Stack_frame; enum Breakpoint_type { BP_anywhere, BP_location, BP_stepover, BP_finish }; // BP_anywhere: break on any instruction (for "step into") // BP_location: break on a specific code offset (function + ip) // BP_stepover: break on next instruction in same function (or previous func) // BP_finish : finish current function and break in previous function // other (future) possibilities: break on access to local/global vars, // break when usecode is run on a specific object, // break on errors, // break on a special 'break to debugger' opcode, // break on a specific or any intrinsic call class Breakpoint { public: int id; // used to identify breakpoint to remote debugger bool once; // delete when triggered virtual Breakpoint_type get_type() const =0; virtual bool check(Stack_frame *frame) const =0; virtual void serialize(int fd) const =0; protected: Breakpoint(bool once); }; class AnywhereBreakpoint : public Breakpoint { public: AnywhereBreakpoint(); virtual Breakpoint_type get_type() const { return BP_anywhere; } virtual bool check(Stack_frame *frame) const { return true; } virtual void serialize(int fd) const { } // +++++ implement this? }; class LocationBreakpoint : public Breakpoint { public: LocationBreakpoint(int functionid, int ip, bool once = false); virtual Breakpoint_type get_type() const { return BP_location; } virtual bool check(Stack_frame *frame) const; virtual void serialize(int fd) const; private: int functionid; int ip; }; class StepoverBreakpoint : public Breakpoint { public: StepoverBreakpoint(Stack_frame *frame); virtual Breakpoint_type get_type() const { return BP_stepover; } virtual bool check(Stack_frame *frame) const; virtual void serialize(int fd) const { } // +++++ implement this? private: int call_chain; int call_depth; }; class FinishBreakpoint : public Breakpoint { public: FinishBreakpoint(Stack_frame *frame); virtual Breakpoint_type get_type() const { return BP_finish; } virtual bool check(Stack_frame *frame) const; virtual void serialize(int fd) const { } // +++++ implement this? private: int call_chain; int call_depth; }; class Breakpoints { public: Breakpoints(); ~Breakpoints(); void add(Breakpoint* breakpoint); void remove(Breakpoint* breakpoint); bool remove(int id); int check(Stack_frame *frame); void transmit(int fd); static int getNewID() { return lastID++; } private: static int lastID; std::list breaks; }; #endif exult-1.2/usecode/keyring.cc0000644000175000001440000000317407724430454011616 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "keyring.h" #include "utils.h" #include "fnames.h" #include "exceptions.h" using std::ifstream; using std::ofstream; void Keyring::read() { ifstream in; // clear keyring first keys.clear(); try { U7open(in, KEYRINGDAT); } catch(exult_exception &e) { // maybe an old savegame, just leave the keyring empty return; } do { int val = Read2(in); if (in.good()) addkey(val); } while (in.good()); in.close(); } void Keyring::write() { ofstream out; U7open(out, KEYRINGDAT); std::set::iterator iter; for (iter = keys.begin(); iter != keys.end(); ++iter) Write2(out, *iter); out.close(); } void Keyring::clear() { keys.clear(); } void Keyring::addkey(int qual) { keys.insert(qual); } bool Keyring::checkkey(int qual) { return (keys.find(qual) != keys.end()); } exult-1.2/usecode/stackframe.h0000644000175000001440000000351207724430454012124 /* * stackframe.h - a usecode interpreter stack frame * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STACKFRAME_H #define _STACKFRAME_H #include "exult_types.h" #include class Usecode_function; class Game_object; class Usecode_value; class Stack_frame { public: Stack_frame(Usecode_function *fun, int event, Game_object *caller, int chain, int depth); ~Stack_frame(); Usecode_function *function; uint8 *ip; // current IP uint8 *data; // pointer to start of data segment uint8 *externs; // pointer to start of externs uint8 *code; // pointer to (actual) code uint8 *endp; // pointer directly past code segment int line_number; // if debugging info present // should probably add source filename? int call_chain; // unique ID for this call chain int call_depth; // zero for top level function int num_externs; int num_args; int num_vars; Usecode_value *locals; int eventid; Game_object *caller_item; Usecode_value *save_sp; static int LastCallChainID; static int getCallChainID() { return ++LastCallChainID; } }; std::ostream& operator<<(std::ostream& out, Stack_frame& val); #endif exult-1.2/usecode/bgintrinsics.h0000644000175000001440000003051107724430454012501 /* * Bgintrinsics.h - Intrinsic table for Black Gate. * * Note: This is used in the virtual machine and the Usecode compiler. * * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ USECODE_INTRINSIC_PTR(get_random), // 0 USECODE_INTRINSIC_PTR(execute_usecode_array), // 1 USECODE_INTRINSIC_PTR(delayed_execute_usecode_array), // 2 USECODE_INTRINSIC_PTR(show_npc_face), // 3 USECODE_INTRINSIC_PTR(remove_npc_face), // 4 USECODE_INTRINSIC_PTR(add_answer), // 5 USECODE_INTRINSIC_PTR(remove_answer), // 6 USECODE_INTRINSIC_PTR(push_answers), // 7 USECODE_INTRINSIC_PTR(pop_answers), // 8 USECODE_INTRINSIC_PTR(clear_answers), // 9 USECODE_INTRINSIC_PTR(select_from_menu), // 0x0a USECODE_INTRINSIC_PTR(select_from_menu2), // 0x0b USECODE_INTRINSIC_PTR(input_numeric_value), // 0xc USECODE_INTRINSIC_PTR(set_item_shape), // 0xd USECODE_INTRINSIC_PTR(find_nearest), // 0xe USECODE_INTRINSIC_PTR(play_sound_effect), // 0xf - Sound effect USECODE_INTRINSIC_PTR(die_roll), // 0x10 USECODE_INTRINSIC_PTR(get_item_shape), // 0x11 USECODE_INTRINSIC_PTR(get_item_frame), // 0x12 USECODE_INTRINSIC_PTR(set_item_frame), // 0x13 USECODE_INTRINSIC_PTR(get_item_quality), // 0x14 USECODE_INTRINSIC_PTR(set_item_quality), // 0x15 USECODE_INTRINSIC_PTR(get_item_quantity), // 0x16 USECODE_INTRINSIC_PTR(set_item_quantity), // 0x17 USECODE_INTRINSIC_PTR(get_object_position), // 0x18 USECODE_INTRINSIC_PTR(get_distance), // 0x19 USECODE_INTRINSIC_PTR(find_direction), // 0x1a USECODE_INTRINSIC_PTR(get_npc_object), // 0x1b USECODE_INTRINSIC_PTR(get_schedule_type), // 0x1c USECODE_INTRINSIC_PTR(set_schedule_type), // 0x1d USECODE_INTRINSIC_PTR(add_to_party), // 0x1e USECODE_INTRINSIC_PTR(remove_from_party), // 0x1f USECODE_INTRINSIC_PTR(get_npc_prop), // 0x20 USECODE_INTRINSIC_PTR(set_npc_prop), // 0x21 USECODE_INTRINSIC_PTR(get_avatar_ref), // 0x22 USECODE_INTRINSIC_PTR(get_party_list), // 0x23 USECODE_INTRINSIC_PTR(create_new_object), // 0x24 USECODE_INTRINSIC_PTR(set_last_created), // 0x25 USECODE_INTRINSIC_PTR(update_last_created), // 0x26 USECODE_INTRINSIC_PTR(get_npc_name), // 0x27 USECODE_INTRINSIC_PTR(count_objects), // 0x28 USECODE_INTRINSIC_PTR(find_object), // 0x29 USECODE_INTRINSIC_PTR(get_cont_items), // 0x2a USECODE_INTRINSIC_PTR(remove_party_items), // 0x2b USECODE_INTRINSIC_PTR(add_party_items), // 0x2c USECODE_INTRINSIC_PTR(UNKNOWN), // 0x2d UNUSED. - add_cont_items??? - GUESS USECODE_INTRINSIC_PTR(play_music), // 0x2e USECODE_INTRINSIC_PTR(npc_nearby), // 0x2f USECODE_INTRINSIC_PTR(find_nearby_avatar), // 0x30 USECODE_INTRINSIC_PTR(is_npc), // 0x31 USECODE_INTRINSIC_PTR(display_runes), // 0x32 USECODE_INTRINSIC_PTR(click_on_item), // 0x33 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x34 UNUSED USECODE_INTRINSIC_PTR(find_nearby), // 0x35 USECODE_INTRINSIC_PTR(give_last_created), // 0x36 USECODE_INTRINSIC_PTR(is_dead), // 0x37 USECODE_INTRINSIC_PTR(game_hour), // 0x38 USECODE_INTRINSIC_PTR(game_minute), // 0x39 USECODE_INTRINSIC_PTR(get_npc_number), // 0x3a USECODE_INTRINSIC_PTR(part_of_day), // 0x3b USECODE_INTRINSIC_PTR(get_alignment), // 0x3c USECODE_INTRINSIC_PTR(set_alignment), // 0x3d USECODE_INTRINSIC_PTR(move_object), // 0x3e USECODE_INTRINSIC_PTR(remove_npc), // 0x3f USECODE_INTRINSIC_PTR(item_say), // 0x40 USECODE_INTRINSIC_PTR(projectile_effect), // 0x41 USECODE_INTRINSIC_PTR(get_lift), // 0x42 USECODE_INTRINSIC_PTR(set_lift), // 0x43 USECODE_INTRINSIC_PTR(get_weather), // 0x44 USECODE_INTRINSIC_PTR(set_weather), // 0x45 USECODE_INTRINSIC_PTR(sit_down),// 0x46 USECODE_INTRINSIC_PTR(summon), // 0x47 SummonCreature (ucdump.c) USECODE_INTRINSIC_PTR(display_map), // 0x48 USECODE_INTRINSIC_PTR(kill_npc),// 0x49 USECODE_INTRINSIC_PTR(roll_to_win), // 0x4a USECODE_INTRINSIC_PTR(set_attack_mode), // 0x4b USECODE_INTRINSIC_PTR(set_opponent), // 0x4c USECODE_INTRINSIC_PTR(clone), // 0x4d CloneNPC (ucdump.c) USECODE_INTRINSIC_PTR(UNKNOWN), // 0x4e UNUSED USECODE_INTRINSIC_PTR(display_area), // 0x4f// ShowCrystalBall(ucdump) USECODE_INTRINSIC_PTR(wizard_eye), // 0x50 USECODE_INTRINSIC_PTR(resurrect),// 0x51 ResurrectNPC (ucdump.c) USECODE_INTRINSIC_PTR(add_spell),// 0x52 AddSpellToBook (ucdump.c) USECODE_INTRINSIC_PTR(sprite_effect),// 0x53 ExecuteSprite (ucdump.c) USECODE_INTRINSIC_PTR(explode), // 0x54 USECODE_INTRINSIC_PTR(book_mode),// 0x55 USECODE_INTRINSIC_PTR(stop_time), // 0x56 USECODE_INTRINSIC_PTR(cause_light), // 0x57 CauseLight (ucdump.c) USECODE_INTRINSIC_PTR(get_barge),// 0x58 USECODE_INTRINSIC_PTR(earthquake), // 0x59 USECODE_INTRINSIC_PTR(is_pc_female), // 0x5a USECODE_INTRINSIC_PTR(armageddon), // 0x5b USECODE_INTRINSIC_PTR(halt_scheduled), // 0x5c USECODE_INTRINSIC_PTR(lightning), // 0x5d USECODE_INTRINSIC_PTR(get_array_size), // 0x5e USECODE_INTRINSIC_PTR(mark_virtue_stone), // 0x5f USECODE_INTRINSIC_PTR(recall_virtue_stone), // 0x60 USECODE_INTRINSIC_PTR(apply_damage), // 0x61 USECODE_INTRINSIC_PTR(is_pc_inside), // 0x62 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x63 SetOrreryState (ucdump.c) USECODE_INTRINSIC_PTR(UNKNOWN), // 0x64 UNUSED USECODE_INTRINSIC_PTR(get_timer), // 0x65 USECODE_INTRINSIC_PTR(set_timer), // 0x66 USECODE_INTRINSIC_PTR(wearing_fellowship), // 0x67 USECODE_INTRINSIC_PTR(mouse_exists), // 0x68 USECODE_INTRINSIC_PTR(get_speech_track), // 0x69 USECODE_INTRINSIC_PTR(flash_mouse), // 0x6a USECODE_INTRINSIC_PTR(get_item_frame_rot), // 0x6b Guessing USECODE_INTRINSIC_PTR(set_item_frame_rot), // 0x6c Guessing USECODE_INTRINSIC_PTR(on_barge), // 0x6d USECODE_INTRINSIC_PTR(get_container), // 0x6e USECODE_INTRINSIC_PTR(remove_item), // 0x6f USECODE_INTRINSIC_PTR(UNKNOWN), // 0x70 USECODE_INTRINSIC_PTR(reduce_health), // 0x71 USECODE_INTRINSIC_PTR(is_readied), // 0x72 USECODE_INTRINSIC_PTR(restart_game), // 0x73 USECODE_INTRINSIC_PTR(start_speech), // 0x74 USECODE_INTRINSIC_PTR(run_endgame), // 0x75 StartEndGame (ucdump.c) USECODE_INTRINSIC_PTR(fire_cannon), // 0x76 FireCannon (ucdump.c) USECODE_INTRINSIC_PTR(nap_time), // 0x77 USECODE_INTRINSIC_PTR(advance_time), // 0x78 USECODE_INTRINSIC_PTR(in_usecode), // 0x79 USECODE_INTRINSIC_PTR(call_guards), // 0x7a USECODE_INTRINSIC_PTR(obj_sprite_effect),// 0x7b USECODE_INTRINSIC_PTR(attack_avatar), // 0x7c USECODE_INTRINSIC_PTR(path_run_usecode), // 0x7d USECODE_INTRINSIC_PTR(close_gumps), // 0x7e USECODE_INTRINSIC_PTR(item_say), // 0x7f ItemSay in gump. USECODE_INTRINSIC_PTR(UNKNOWN), // 0x80 ++++Close_gump(item)??? USECODE_INTRINSIC_PTR(in_gump_mode), // 0x81 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x82 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x83 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x84 USECODE_INTRINSIC_PTR(is_not_blocked), // 0x85 USECODE_INTRINSIC_PTR(play_sound_effect2), // 0x86 USECODE_INTRINSIC_PTR(direction_from), // 0x87 USECODE_INTRINSIC_PTR(get_item_flag), // 0x88 USECODE_INTRINSIC_PTR(set_item_flag), // 0x89 USECODE_INTRINSIC_PTR(clear_item_flag), // 0x8a USECODE_INTRINSIC_PTR(set_path_failure),// 0x8b USECODE_INTRINSIC_PTR(fade_palette), // 0x8c USECODE_INTRINSIC_PTR(get_party_list2), // 0x8d USECODE_INTRINSIC_PTR(in_combat), // 0x8e USECODE_INTRINSIC_PTR(start_speech), // 0x8f Same as 0x74? USECODE_INTRINSIC_PTR(is_water), // 0x90 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x91 ++++ reset_conv_face??? USECODE_INTRINSIC_PTR(center_view), // 0x92 USECODE_INTRINSIC_PTR(get_dead_party), // 0x93 USECODE_INTRINSIC_PTR(center_view), // 0x94 Guessing: same as 0x92? USECODE_INTRINSIC_PTR(telekenesis), // 0x95 USECODE_INTRINSIC_PTR(a_or_an), // 0x96 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x97 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x98 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x99 USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9a USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9b USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9c USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9d USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9e USECODE_INTRINSIC_PTR(UNKNOWN), // 0x9f USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xa9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xaa USECODE_INTRINSIC_PTR(UNKNOWN), // 0xab USECODE_INTRINSIC_PTR(UNKNOWN), // 0xac USECODE_INTRINSIC_PTR(UNKNOWN), // 0xad USECODE_INTRINSIC_PTR(UNKNOWN), // 0xae USECODE_INTRINSIC_PTR(UNKNOWN), // 0xaf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xb9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xba USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbe USECODE_INTRINSIC_PTR(UNKNOWN), // 0xbf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xc9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xca USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xce USECODE_INTRINSIC_PTR(UNKNOWN), // 0xcf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xd9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xda USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xde USECODE_INTRINSIC_PTR(UNKNOWN), // 0xdf USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xe9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xea USECODE_INTRINSIC_PTR(UNKNOWN), // 0xeb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xec USECODE_INTRINSIC_PTR(UNKNOWN), // 0xed USECODE_INTRINSIC_PTR(UNKNOWN), // 0xee USECODE_INTRINSIC_PTR(UNKNOWN), // 0xef USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf0 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf1 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf2 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf3 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf4 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf5 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf6 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf7 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf8 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xf9 USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfa USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfb USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfc USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfd USECODE_INTRINSIC_PTR(UNKNOWN), // 0xfe USECODE_INTRINSIC_PTR(UNKNOWN), // 0xff exult-1.2/usecode/ucserial.h0000644000175000001440000000256207724430454011617 /* * ucserial.h - Serialization of usecode objects * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UCSERIAL_H #define _UCSERIAL_H #include "objserial.h" class Usecode_value; extern int Stack_frame_out ( int fd, // Socket. int functionid, int ip, int call_chain, int call_depth, int eventid, int caller_item, int num_args, int num_vars, Usecode_value* locals ); extern bool Stack_frame_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. int& functionid, int& ip, int& call_chain, int& call_depth, int& eventid, int& caller_item, int& num_args, int& num_vars, Usecode_value*& locals ); #endif exult-1.2/usecode/ucmachine.cc0000644000175000001440000000264507724430454012104 /* * ucmachine.cc - Interpreter for usecode. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ucmachine.h" #include "keyring.h" #include "conversation.h" Usecode_machine::Usecode_machine ( ) : keyring(0), conv(0) { // Clear global flags. std::memset(gflags, 0, sizeof(gflags)); conv = new Conversation; keyring = new Keyring; } /* * Delete. */ Usecode_machine::~Usecode_machine ( ) { delete conv; delete keyring; } void Usecode_machine::init_conversation() { conv->init_faces(); } int Usecode_machine::get_num_faces_on_screen() const { return conv->get_num_faces_on_screen(); } exult-1.2/usecode/ucscriptop.h0000644000175000001440000000447307724430454012206 /* * Ucscriptop.h - Usecode-script opcode definitions. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _USCRIPTOP_H #define _USCRIPTOP_H /* * Opcodes for Usecode_script's: */ namespace Ucscript { enum Ucscript_ops { cont = 0x01, // Continue without painting. repeat = 0x0b, // Loop(offset, cnt). repeat2 = 0x0c, // Loop(offset, cnt1, cnt2). nop = 0x21, // Not sure about this. dont_halt = 0x23, // Not right? delay_ticks = 0x27, // Delay(ticks). delay_hours = 0x29, // Delay nn game hours. finish = 0x2c, // Finish script if killed. remove = 0x2d, // Remove item & halt. step_n = 0x30, // Step in given direction. step_ne = 0x31, step_e = 0x32, step_se = 0x33, step_s = 0x34, step_sw = 0x35, step_w = 0x36, step_nw = 0x37, descend = 0x38, // Decr. lift. rise = 0x39, // Incr. lift. frame = 0x46, // Set_frame(frnum). egg = 0x48, // Activate egg. next_frame_max =0x4d, // Next frame, but stop at max. next_frame = 0x4e, // Next frame, but wrap. prev_frame_min =0x4f, // Prev frame, but stop at 0. prev_frame = 0x50, // Prev. frame, but wrap. say = 0x52, // Say(string). step = 0x53, // Step(dir). music = 0x54, // Play(track#). usecode = 0x55, // Call usecode(fun). speech = 0x56, // Speech(track#). sfx = 0x58, // Sound_effect(#). face_dir = 0x59, // Face_dir(dir), dir=0-7, 0=north. npc_frame = 0x61, // 61-70: Set frame, but w/ cur. dir. hit = 0x78, // Hit(hps, ??). Item attacked. /* * These are (I think) not in the original: */ usecode2 = 0x80, // Call usecode(fun, eventid). resurrect = 0x81 // Parm. is body. }; } #endif exult-1.2/usecode/conversation.cc0000644000175000001440000003724710054030577012660 /* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "actors.h" #include "conversation.h" #include "exult.h" #include "game.h" #include "gamewin.h" #include "mouse.h" #include "useval.h" #include "data/exult_bg_flx.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::size_t; using std::strcpy; using std::string; using std::vector; #endif //TODO: show_face & show_avatar_choices seem to share code? //TODO: show_avatar_choices shouldn't first convert to char**, probably /* * Store information about an NPC's face and text on the screen during * a conversation: */ class Npc_face_info { public: ShapeID shape; int face_num; // NPC's face shape #. //int frame; bool text_pending; // Text has been written, but user // has not yet been prompted. Rectangle face_rect; // Rectangle where face is shown. Rectangle text_rect; // Rectangle NPC statement is shown in. int last_text_height; // Height of last text painted. string cur_text; // Current text being shown. Npc_face_info(ShapeID &sid, int num) : shape(sid), face_num(num), text_pending(0) { } }; Conversation::Conversation() : num_faces(0), last_face_shown(0), conv_choices(0), avatar_face(0,0,0,0) { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); for (int i = 0; i < max_faces; i++) face_info[i] = 0; } Conversation::~Conversation() { delete [] conv_choices; } void Conversation::clear_answers(void) { answers.clear(); } void Conversation::add_answer(const char *str) { remove_answer(str); string s(str); answers.push_back(s); } /* * Add an answer to the list. */ void Conversation::add_answer(Usecode_value& val) { const char *str; int size = val.get_array_size(); if (size) // An array? { for (int i = 0; i < size; i++) add_answer(val.get_elem(i)); } else if ((str = val.get_str_value()) != 0) add_answer(str); } void Conversation::remove_answer(const char *str) { std::vector::iterator it; for(it=answers.begin(); it!=answers.end(); ++it) if(*it==str) break; if(it!=answers.end()) answers.erase(it); } /* * Remove an answer from the list. */ void Conversation::remove_answer(Usecode_value& val) { const char *str; if (val.is_array()) { int size = val.get_array_size(); for (int i=0; i < size; i++) { str = val.get_elem(i).get_str_value(); if (str) remove_answer(str); } } else { str = val.get_str_value(); remove_answer(str); } } /* * Initialize face list. */ void Conversation::init_faces() { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); for (int i = 0; i < max_faces; i++) { if( face_info[i] ) delete face_info[i]; face_info[i] = 0; } num_faces = 0; last_face_shown = -1; } /* * Get face frame in Serpent Isle. */ static int SI_get_frame ( Actor *main_actor ) { int frame; if (main_actor->get_skin_color() == 0) // WH { frame = 1 - main_actor->get_type_flag(Actor::tf_sex); } else if (main_actor->get_skin_color() == 1) // BN { frame = 3 - main_actor->get_type_flag(Actor::tf_sex); } else if (main_actor->get_skin_color() == 2) // BK { frame = 5 - main_actor->get_type_flag(Actor::tf_sex); } else // None { frame = main_actor->get_type_flag(Actor::tf_sex); } return frame; } /* * Show a "face" on the screen. Npc_text_rect is also set. * If shape < 0, an empty space is shown. */ void Conversation::show_face(int shape, int frame, int slot) { ShapeID face_sid(shape, frame, SF_FACES_VGA); bool SI = Game::get_game_type()==SERPENT_ISLE; Main_actor* main_actor = gwin->get_main_actor(); const int max_faces = sizeof(face_info)/sizeof(face_info[0]); // Make sure mode is set right. Palette *pal = gwin->get_pal(); // Watch for wierdness (lightning). if (pal->get_brightness() >= 300) pal->set(-1, 100); if (SI) // Serpent Isle? { // Petra? ???+++Is this right? if (shape == 28 && main_actor->get_flag(Obj_flags::petra)) { shape = main_actor->get_face_shapenum(); face_sid.set_shape(shape); } if (shape == 0) // In any case, get correct frame. { frame = SI_get_frame(main_actor); if (main_actor->get_flag(Obj_flags::tattooed)) shape = 299; face_sid.set_shape(shape, frame); } } // BG Multiracial Hack else if (shape == 0) { if (main_actor->get_skin_color() != 3) { shape = EXULT_BG_FLX_MR_FACES_SHP; frame = SI_get_frame(main_actor); face_sid.set_file(SF_GAME_FLX); face_sid.set_shape(shape, frame); } } // Get screen dims. int screenw = gwin->get_width(), screenh = gwin->get_height(); Npc_face_info *info = 0; // See if already on screen. for (int i = 0; i < max_faces; i++) if (face_info[i] && face_info[i]->face_num == shape) { info = face_info[i]; last_face_shown = i; break; } if (!info) // New one? { if (num_faces == max_faces) // None free? Steal last one. remove_slot_face(max_faces - 1); info = new Npc_face_info(face_sid, shape); if (slot == -1) // Want next one? slot = num_faces; // Get last one shown. Npc_face_info *prev = slot ? face_info[slot - 1] : 0; last_face_shown = slot; if (!face_info[slot]) num_faces++; // We're adding one (not replacing). else delete face_info[slot]; face_info[slot] = info; // Get text height. int text_height = sman->get_text_height(0); // Figure starting y-coord. // Get character's portrait. Shape_frame *face = shape >= 0 ? face_sid.get_shape() : 0; int face_w = 32, face_h = 32; if (face) { face_w = face->get_width(); face_h = face->get_height(); } int starty; if (prev) { starty = prev->text_rect.y + prev->last_text_height; if (starty < prev->face_rect.y + prev->face_rect.h) starty = prev->face_rect.y + prev->face_rect.h; starty += 2*text_height; if (starty + face_h > screenh - 1) starty = screenh - face_h - 1; } else starty = 1; info->face_rect = gwin->clip_to_win(Rectangle(8, starty, face_w + 4, face_h + 4)); Rectangle& fbox = info->face_rect; // This is where NPC text will go. info->text_rect = gwin->clip_to_win(Rectangle( fbox.x + fbox.w + 3, fbox.y + 3, screenw - fbox.x - fbox.w - 6, 4*text_height)); // No room? (Serpent?) if (info->text_rect.w < 16 || info->text_rect.h < 16) // Show in lower center. info->text_rect = Rectangle(screenw/4, screenh/2, screenw/2, screenh/4); info->last_text_height = info->text_rect.h; } gwin->get_win()->set_clip(0, 0, screenw, screenh); paint_faces(); // Paint all faces. gwin->get_win()->clear_clip(); } /* * Remove face from screen. */ void Conversation::remove_face(int shape) { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); int i; // See if already on screen. for (i = 0; i < max_faces; i++) if (face_info[i] && face_info[i]->face_num == shape) break; if (i == max_faces) return; // Not found. remove_slot_face(i); } /* * Remove face from indicated slot (SI). */ void Conversation::remove_slot_face ( int slot ) { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); if (slot >= max_faces || !face_info[slot]) return; // Invalid. Npc_face_info *info = face_info[slot]; // These are needed in case conversa- // tion is done. gwin->add_dirty(info->face_rect); gwin->add_dirty(info->text_rect); delete face_info[slot]; face_info[slot] = 0; num_faces--; if (last_face_shown == slot) // Just in case. { int j; for (j = max_faces - 1; j >= 0; j--) if (face_info[j]) break; last_face_shown = j; } } /* * Show what the NPC had to say. */ void Conversation::show_npc_message(const char *msg) { if (last_face_shown == -1) return; Npc_face_info *info = face_info[last_face_shown]; info->cur_text = ""; Rectangle& box = info->text_rect; // gwin->paint(box); // Clear what was there before. // paint_faces(); gwin->paint(); int height; // Break at punctuation. while ((height = sman->paint_text_box(0, msg, box.x,box.y,box.w,box.h, -1, 1, gwin->get_text_bg())) < 0) { // More to do? info->cur_text = string(msg, -height); int x, y; char c; gwin->paint(); // Paint scenery beneath. Get_click(x, y, Mouse::hand, &c, false, this); // gwin->paint(box); // Clear area again. gwin->paint(); msg += -height; } // All fit? Store height painted. info->last_text_height = height; info->cur_text = msg; info->text_pending = 1; gwin->set_painted(); // gwin->show(); } /* * Is there NPC text that the user hasn't had a chance to read? */ bool Conversation::is_npc_text_pending() { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); for (int i = 0; i < max_faces; i++) if (face_info[i] && face_info[i]->text_pending) return true; return false; } /* * Clear text-pending flags. */ void Conversation::clear_text_pending() { const int max_faces = sizeof(face_info)/sizeof(face_info[0]); for (int i = 0; i < max_faces; i++) // Clear 'pending' flags. if (face_info[i]) face_info[i]->text_pending = 0; } /* * Show the Avatar's conversation choices (and face). */ void Conversation::show_avatar_choices(int num_choices, char **choices) { bool SI = Game::get_game_type()==SERPENT_ISLE; Main_actor *main_actor = gwin->get_main_actor(); const int max_faces = sizeof(face_info)/sizeof(face_info[0]); // Get screen rectangle. Rectangle sbox = gwin->get_win_rect(); int x = 0, y = 0; // Keep track of coords. in box. int height = sman->get_text_height(0); int space_width = sman->get_text_width(0, " "); // Get main actor's portrait. int shape = main_actor->get_face_shapenum(); int frame; ShapeID face_sid(shape, 0, SF_FACES_VGA); if (SI && (main_actor->get_flag(Obj_flags::petra) || (main_actor->get_skin_color() == 3 && main_actor->get_type_flag(Actor::tf_sex)))) // Petra { shape = 28; frame = 0; face_sid.set_shape(shape, frame); } else if (SI && main_actor->get_skin_color() == 3) // Automaton { shape = 298; frame = 0; face_sid.set_shape(shape, frame); } else if (SI) { frame = SI_get_frame(main_actor); if (shape == 0 && main_actor->get_flag(Obj_flags::tattooed)) { shape = 299; face_sid.set_shape(shape); } } else { // BG Multiracial Hack if (main_actor->get_skin_color() >= 0 && main_actor->get_skin_color() <= 2 && GAME_BG) { shape = EXULT_BG_FLX_MR_FACES_SHP; frame = SI_get_frame(main_actor); face_sid.set_file(SF_GAME_FLX); face_sid.set_shape(shape, frame); } else frame = main_actor->get_type_flag(Actor::tf_sex); } face_sid.set_frame(frame); Shape_frame *face = face_sid.get_shape(); int empty; // Find face prev. to 1st empty slot. for (empty = 0; empty < max_faces; empty++) if (!face_info[empty]) break; // Get last one shown. Npc_face_info *prev = empty ? face_info[empty - 1] : 0; int fx = prev ? prev->face_rect.x + prev->face_rect.w + 4 : 16; int fy; if (SI) { if (num_faces == max_faces) // Remove face #1 if still there. remove_slot_face(max_faces - 1); fy = sbox.h - 2 - face->get_height(); fx = 8; } else if (!prev) fy = sbox.h - face->get_height() - 3*height; else { fy = prev->text_rect.y + prev->last_text_height; if (fy < prev->face_rect.y + prev->face_rect.h) fy = prev->face_rect.y + prev->face_rect.h; fy += height; } Rectangle mbox(fx, fy, face->get_width(), face->get_height()); mbox = mbox.intersect(sbox); avatar_face = mbox; // Repaint entire width. // Set to where to draw sentences. Rectangle tbox(mbox.x + mbox.w + 8, mbox.y + 4, sbox.w - mbox.x - mbox.w - 16, // sbox.h - mbox.y - 16); 5*height);// Try 5 lines. tbox = tbox.intersect(sbox); // gwin->paint(tbox); // Paint background. // Draw portrait. sman->paint_shape(mbox.x + face->get_xleft(), mbox.y + face->get_yabove(), face); delete [] conv_choices; // Set up new list of choices. conv_choices = new Rectangle[num_choices + 1]; for (int i = 0; i < num_choices; i++) { char text[256]; text[0] = 127; // A circle. strcpy(&text[1], choices[i]); int width = sman->get_text_width(0, text); if (x > 0 && x + width >= tbox.w) { // Start a new line. x = 0; y += height - 1; } // Store info. conv_choices[i] = Rectangle(tbox.x + x, tbox.y + y, width, height); conv_choices[i] = conv_choices[i].intersect(sbox); avatar_face = avatar_face.add(conv_choices[i]); sman->paint_text_box(0, text, tbox.x + x, tbox.y + y, width + space_width, height, 0, 0, gwin->get_text_bg()); x += width + space_width; } avatar_face.enlarge(6); // Encloses entire area. avatar_face = avatar_face.intersect(sbox); // Terminate the list. conv_choices[num_choices] = Rectangle(0, 0, 0, 0); clear_text_pending(); gwin->set_painted(); } void Conversation::show_avatar_choices() { char **result; size_t i; // Blame MSVC result=new char *[answers.size()]; for(i=0;ipaint(avatar_face); // Paint over face and answers. gwin->add_dirty(avatar_face); avatar_face.w = 0; } /* * User clicked during a conversation. * * Output: Index (0-n) of choice, or -1 if not on a choice. */ int Conversation::conversation_choice(int x, int y) { int i; for (i = 0; conv_choices[i].w != 0 && !conv_choices[i].has_point(x, y); i++) ; if (conv_choices[i].w != 0) // Found one? return (i); else return (-1); } /* * Repaint everything. */ void Conversation::paint ( ) { paint_faces(true); if (avatar_face.w) // Choices? show_avatar_choices(); } /* * Repaint the faces. Assumes clip has already been set to screen. */ void Conversation::paint_faces ( bool text // Show text too. ) { if (!num_faces) return; const int max_faces = sizeof(face_info)/sizeof(face_info[0]); for (int i = 0; i < max_faces; i++) { Npc_face_info *finfo = face_info[i]; if (!finfo) continue; Shape_frame *face = finfo->face_num >= 0 ? finfo->shape.get_shape() : 0; int face_xleft = 0, face_yabove = 0; if (face) { face_xleft = face->get_xleft(); face_yabove = face->get_yabove(); // Use translucency. sman->paint_shape( finfo->face_rect.x + face_xleft, finfo->face_rect.y + face_yabove, face, 1); } if (text) // Show text too? { Rectangle& box = finfo->text_rect; sman->paint_text_box(0, finfo->cur_text.c_str(), box.x,box.y,box.w,box.h, -1, 1, gwin->get_text_bg()); } } } /* * return nr. of conversation option 'str'. -1 if not found */ int Conversation::locate_answer(const char *str) { int num; std::vector::iterator it; num = 0; for(it=answers.begin(); it!=answers.end(); ++it) { if(*it==str) return num; num++; } return -1; } void Conversation::push_answers() { answer_stack.push_front(answers); answers.clear(); } void Conversation::pop_answers() { answers=answer_stack.front(); answer_stack.pop_front(); gwin->paint(); // Really just need to figure tbox. } exult-1.2/usecode/ucdisasm.cc0000644000175000001440000001431410054030577011744 /* * ucdisasm.cc - Disassembled usecode trace * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #ifndef UNDER_CE using std::strlen; using std::cout; #endif #include "ucinternal.h" #include "uctools.h" #include "utils.h" #include "useval.h" #include "game.h" #include "stackframe.h" int Usecode_internal::get_opcode_length(int opcode) { if (opcode >=0 && opcode < (sizeof(opcode_table)/sizeof(opcode_table[0]))) { return opcode_table[opcode].nbytes + 1; } else { return 0; } } void Usecode_internal::uc_trace_disasm(Stack_frame* frame) { uc_trace_disasm(frame->locals, frame->num_args + frame->num_vars, frame->data, frame->externs, frame->code, frame->ip); } void Usecode_internal::uc_trace_disasm(Usecode_value* locals, int num_locals, uint8* data, uint8* externals, uint8* code, uint8* ip) { int func_ip = (int)(ip - code); int opcode = *ip++; uint8* param_ip = ip; _opcode_desc* pdesc; if (opcode >=0 && opcode < (sizeof(opcode_table)/sizeof(opcode_table[0]))) pdesc = &(opcode_table[opcode]); signed short immed; unsigned short varref; unsigned short func; int immed32; int offset; std::printf(" %04X: ", func_ip); if (pdesc && pdesc->mnemonic) { std::printf("%s", pdesc->mnemonic); if (strlen(pdesc->mnemonic) < 4) std::printf("\t"); } else { std::printf(""); } if (pdesc && pdesc->nbytes > 0) { switch( pdesc->type ) { case BYTE: std::printf("\t%02x", *ip++); break; case IMMED: // Print immediate operand immed = Read2(ip); std::printf("\t%04hXH\t\t; %d", immed, immed); break; case IMMED32: immed32 = (sint32)Read4(ip); std::printf("\t%04hXH\t\t; %d", immed32, immed32); break; case DATA_STRING: case DATA_STRING32: { char* pstr; int len; // Print data string operand if (pdesc->type == DATA_STRING) offset = Read2(ip); else offset = (sint32)Read4(ip); pstr = (char*)data + offset; len = strlen(pstr); if( len > 20 ) len = 20 - 3; std::printf("\tL%04X\t\t; ", offset); for(int i = 0; i < len; i++ ) std::printf("%c", pstr[i]); if( len < strlen(pstr) ) // String truncated std::printf("..."); } break; case RELATIVE_JUMP: // Print jump desination offset = Read2(ip); std::printf("\t%04X", (offset + func_ip+1+pdesc->nbytes)&0xFFFF); break; case RELATIVE_JUMP32: offset = (sint32)Read4(ip); std::printf("\t%04X", offset + func_ip+1+pdesc->nbytes); break; case SLOOP: if (pdesc->nbytes == 11) ip++; Read2(ip); Read2(ip); Read2(ip); varref = Read2(ip); offset = Read2(ip); std::printf("\t[%04X], %04X\t= ", varref, (offset +func_ip+1+pdesc->nbytes)&0xFFFF); locals[varref].print(cout, true); // print value (short format) break; case SLOOP32: if (pdesc->nbytes == 13) ip++; Read2(ip); Read2(ip); Read2(ip); varref = Read2(ip); offset = (sint32)Read4(ip); std::printf("\t[%04X], %04X\t= ", varref, offset +func_ip+1+pdesc->nbytes); locals[varref].print(cout, true); // print value (short format) break; case IMMED_AND_RELATIVE_JUMP: immed = Read2(ip); offset = Read2(ip); std::printf("\t%04hXH, %04X", immed, (offset + func_ip+1+pdesc->nbytes)&0xFFFF); break; case IMMED_RELJUMP32: immed = Read2(ip); offset = (sint32)Read4(ip); std::printf("\t%04hXH, %04X", immed, offset + func_ip+1+pdesc->nbytes); break; case CALL: { func = Read2(ip); immed = *ip++; const char **func_table = bg_intrinsic_table; if (Game::get_game_type() == SERPENT_ISLE) func_table = si_intrinsic_table; std::printf("\t_%s@%d\t; %04X", func_table[func], immed, func); } break; case EXTCALL: { // Print extern call offset = Read2(ip); std::printf("\t[%04X]\t\t; %04XH", offset, externals[2*offset] + 256*externals[2*offset + 1]); } break; case VARREF: // Print variable reference varref = Read2(ip); std::printf("\t[%04X]\t\t= ", varref); locals[varref].print(cout, true); // print value (short) break; case FLGREF: // Print global flag reference offset = Read2(ip); std::printf("\tflag:[%04X]\t= ", offset); if (gflags[offset]) std::printf("set"); else std::printf("unset"); break; default: // Unknown type break; } } ip = param_ip; //restore IP back to opcode parameters // special cases: switch (opcode) { case 0x05: // JNE. { Usecode_value val; if (sp <= stack) val = Usecode_value(0); else val = *(sp - 1); if (val.is_false()) std::printf("\t\t(jump taken)"); else std::printf("\t\t(jump not taken)"); break; } /* maybe predict this? case 0x07: // CMPS. { int cnt = Read2(ip); // # strings. offset = (short) Read2(ip); bool matched = false; // only try to match if we haven't found an answer yet while (!matched && !found_answer && cnt-- > 0) { Usecode_value s = pop(); const char *str = s.get_str_value(); if (str && strcmp(str, user_choice) == 0) { matched = true; found_answer = true; } } while (cnt-- > 0) // Pop rest of stack. pop(); if (!matched) // Jump if no match. ip += offset; } break; */ } std::printf("\n"); } exult-1.2/usecode/debugserver.h0000644000175000001440000000205607724430454012323 /* * debugserver.h: handle usecode debugging messages from client * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DEBUGSERVER_H #define _DEBUGSERVER_H #if (defined(USE_EXULTSTUDIO) && defined(USECODE_DEBUGGER)) void Handle_client_debug_message(int& fd); void Handle_debug_message(unsigned char* data, int datalen); #endif #endif exult-1.2/usecode/ucmachine.h0000644000175000001440000000575507732251221011743 /* * ucmachine.cc - Interpreter for usecode. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UCMACHINE_H #define UCMACHINE_H #ifndef ALPHA_LINUX_CXX # include #endif class Game_window; class Usecode_machine; class Conversation; class Keyring; class Game_object; class Actor; #include "exceptions.h" #include "singles.h" /* * Here's our virtual machine for running usecode. The actual internals * are in Usecode_internal. */ class Usecode_machine : public Game_singletons { UNREPLICATABLE_CLASS(Usecode_machine); protected: unsigned char gflags[1024]; // Global flags. Keyring* keyring; Conversation *conv; // Handles conversations public: friend class Usecode_script; // Create Usecode_internal. static Usecode_machine *create(); Usecode_machine(); virtual ~Usecode_machine(); // Read in usecode functions. virtual void read_usecode(std::istream& file, bool patch = false) = 0; // Possible events: enum Usecode_events { npc_proximity = 0, double_click = 1, internal_exec = 2, // Internal call via intr. 1 or 2. egg_proximity = 3, weapon = 4, // From weapons.dat. readied = 5, // Wear an item. unreadied = 6, // Removed an item. died = 7, // In SI only, I think. chat = 9 // When a NPC wants to talk to you in SI }; enum Global_flag_names { did_first_scene = 0x3b, // Went through 1st scene with Iolo. have_trinsic_password = 0x3d, found_stable_key = 0x48, left_trinsic = 0x57, avatar_is_thief = 0x2eb }; int get_global_flag(int i) // Get/set ith flag. { return gflags[i]; } void set_global_flag(int i, int val = 1) { gflags[i] = (val == 1); } // Start speech, or show text. virtual void do_speech(int num) = 0; virtual int in_usecode() = 0; // Currently in a usecode function? Keyring* getKeyring() const { return keyring; } // Call desired function. virtual int call_usecode(int id, Game_object *obj, Usecode_events event) = 0; virtual void write() = 0; // Write out 'gamedat/usecode.dat'. virtual void read() = 0; // Read in 'gamedat/usecode.dat'. void init_conversation(); int get_num_faces_on_screen() const; // intercept the next click_on_item intrinsic virtual void intercept_click_on_item(Game_object *obj) = 0; }; #endif /* INCL_USECODE */ exult-1.2/usecode/ucinternal.cc0000644000175000001440000020323410054030577012301 /* * ucinternal.cc - Interpreter for usecode. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include /* Debugging. */ # include # include # include #endif #include #ifdef XWIN #include #endif #include // STL function things #include "Gump.h" #include "Gump_manager.h" #include "Text_gump.h" #include "Audio.h" #include "animate.h" #include "barge.h" #include "chunks.h" #include "conversation.h" #include "exult.h" #include "game.h" #include "gamewin.h" #include "gamemap.h" #include "keyring.h" #include "mouse.h" #include "schedule.h" #include "tqueue.h" #include "ucinternal.h" #include "ucsched.h" #include "useval.h" #include "utils.h" #include "vec.h" #include "actors.h" #include "egg.h" #include "actions.h" #include "stackframe.h" #include "ucfunction.h" #include "effects.h" #include "party.h" #if (defined(USE_EXULTSTUDIO) && defined(USECODE_DEBUGGER)) #include "server.h" #include "servemsg.h" #include "debugmsg.h" #include "debugserver.h" #endif #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::istream; using std::ifstream; using std::ofstream; using std::istream; using std::ostream; using std::exit; using std::ios; using std::dec; using std::hex; using std::memset; using std::setfill; using std::setw; using std::size_t; using std::string; using std::strcat; using std::strchr; using std::strcmp; using std::strcpy; using std::strlen; using std::vector; using std::ostream; #endif // External globals.. extern bool intrinsic_trace; extern int usecode_trace; #if 0 && USECODE_DEBUGGER extern bool usecode_debugging; std::vector intrinsic_breakpoints; void initialise_usecode_debugger(void) { // Summon up the configuration file // List all the keys. // Render intrinsic names to numbers (unless already given as // a number (which might be hex. Convert from that. // push them all onto the list } #endif void Usecode_internal::stack_trace(ostream& out) { if (call_stack.empty()) return; std::deque::iterator iter = call_stack.begin(); do { out << *(*iter) << endl; if ((*iter)->call_depth == 0) break; ++iter; } while (true); } bool Usecode_internal::call_function(int funcid, int eventid, Game_object *caller, bool entrypoint, bool orig) { // locate function vector& slot = funs[funcid/0x100]; size_t index = funcid%0x100; Usecode_function *fun = index < slot.size() ? slot[index] : 0; if (!fun) { #ifdef DEBUG cout << "Usecode " << funcid << " not found." << endl; #endif return false; } if (orig) if (!(fun = fun->orig)) { #ifdef DEBUG cout << "Original usecode " << funcid << " not found." << endl; #endif return false; } int depth, oldstack, chain; if (entrypoint) { depth = 0; oldstack = 0; chain = Stack_frame::getCallChainID(); } else { Stack_frame *parent = call_stack.front(); // find new depth depth = parent->call_depth + 1; // find number of elements available to pop from stack (as arguments) oldstack = sp - parent->save_sp; chain = parent->call_chain; if (caller == 0) caller = parent->caller_item; // use parent's } Stack_frame *frame = new Stack_frame(fun, eventid, caller, chain, depth); while (frame->num_args > oldstack) // Not enough args pushed? { pushi(0); // add zeroes oldstack++; } // Store args in first num_args locals int i; for (i = 0; i < frame->num_args; i++) { Usecode_value val = pop(); frame->locals[frame->num_args - i - 1] = val; } // save stack pointer frame->save_sp = sp; // add new stack frame to top of stack call_stack.push_front(frame); #ifdef DEBUG cout << "Running usecode " << hex << setfill((char)0x30) << setw(4) << funcid << dec << setfill(' ') << " ("; for (i = 0; i < frame->num_args; i++) { if (i) cout << ", "; frame->locals[i].print(cout); } cout << ") with event " << eventid << ", depth " << frame->call_depth << endl; #endif return true; } void Usecode_internal::previous_stack_frame() { // remove current frame from stack Stack_frame *frame = call_stack.front(); call_stack.pop_front(); // restore stack pointer sp = frame->save_sp; if (frame->call_depth == 0) { // this was the function called from 'the outside' // push a marker (NULL) for the interpreter onto the call stack, // so it knows it has to return instead of continuing // further up the call stack call_stack.push_front(0); } delete frame; } void Usecode_internal::return_from_function(Usecode_value& retval) { #ifdef DEBUG // store old function ID for debugging output int oldfunction = call_stack.front()->function->id; #endif // back up a stack frame previous_stack_frame(); // push the return value push(retval); #ifdef DEBUG Stack_frame *parent_frame = call_stack.front(); cout << "Returning ("; retval.print(cout); cout << ") from usecode " << hex << setw(4) << setfill((char)0x30) << oldfunction << dec << setfill(' ') << endl; if (parent_frame) { int newfunction = call_stack.front()->function->id; cout << "...back into usecode " << hex << setw(4) << setfill((char)0x30) << newfunction << dec << setfill(' ') << endl; } #endif } void Usecode_internal::return_from_procedure() { #ifdef DEBUG // store old function ID for debugging output int oldfunction = call_stack.front()->function->id; #endif // back up a stack frame previous_stack_frame(); #ifdef DEBUG Stack_frame *parent_frame = call_stack.front(); cout << "Returning from usecode " << hex << setw(4) << setfill((char)0x30) << oldfunction << dec << setfill(' ') << endl; if (parent_frame) { int newfunction = call_stack.front()->function->id; cout << "...back into usecode " << hex << setw(4) << setfill((char)0x30) << newfunction << dec << setfill(' ') << endl; } #endif } void Usecode_internal::abort_function() { #ifdef DEBUG int functionid = call_stack.front()->function->id; cout << "Aborting from usecode " << hex << setw(4) << setfill((char)0x30) << functionid << dec << setfill(' ') << endl; #endif // clear the entire call stack up to the entry point while (call_stack.front() != 0) previous_stack_frame(); } /* * Append a string. */ void Usecode_internal::append_string ( const char *str ) { if (!str) return; // Figure new length. int len = String ? strlen(String) : 0; len += strlen(str); char *newstr = new char[len + 1]; if (String) { strcpy(newstr, String); delete [] String; String = strcat(newstr, str); } else String = strcpy(newstr, str); } // Push/pop stack. inline void Usecode_internal::push(Usecode_value& val) { *sp++ = val; } inline Usecode_value Usecode_internal::pop() { if (sp <= stack) { // Happens in SI #0x939 cerr << "Stack underflow" << endl; return Usecode_value(0); } return *--sp; } inline void Usecode_internal::pushref(Game_object *obj) { Usecode_value v(obj); push(v); } inline void Usecode_internal::pushi(long val) // Push/pop integers. { Usecode_value v(val); push(v); } inline int Usecode_internal::popi() { Usecode_value val = pop(); return val.need_int_value(); } // Push/pop strings. inline void Usecode_internal::pushs(char *s) { Usecode_value val(s); push(val); } /* * Get a game object from an "itemref", which might be the actual * pointer, or might be -(npc number). * * Output: ->game object. */ Game_object *Usecode_internal::get_item ( Usecode_value& itemref ) { // If array, take 1st element. Usecode_value& elemval = itemref.get_elem0(); if (elemval.is_ptr()) return elemval.get_ptr_value(); long val = elemval.get_int_value(); if (!val) return NULL; Game_object *obj = NULL; if (val == -356) // Avatar. return gwin->get_main_actor(); if (val < 0 && val > -356) obj = gwin->get_npc(-val); else if (val >= 0 && val < gwin->get_num_npcs()) { obj = gwin->get_npc(val); CERR("Warning: interpreting positive integer as NPCnum"); // Special case: palace guards. } else if (val >= 0 && val < 0x400) // Looks like a shape #? { if (!itemref.is_array() && caller_item && val == caller_item->get_shapenum()) obj = caller_item; else return 0; // Can't be an object. } return obj; } /* * Check for an actor. */ Actor *Usecode_internal::as_actor ( Game_object *obj ) { if (!obj) return 0; return (obj->as_actor()); } /* * Get a position. */ Tile_coord Usecode_internal::get_position ( Usecode_value& itemval ) { Game_object *obj; // An object? if ((itemval.get_array_size() == 1 || !itemval.get_array_size()) && (obj = get_item(itemval))) return obj->get_outermost()->get_tile(); else if (itemval.get_array_size() == 3) // An array of coords.? return Tile_coord(itemval.get_elem(0).get_int_value(), itemval.get_elem(1).get_int_value(), itemval.get_elem(2).get_int_value()); else if (itemval.get_array_size() == 4) // Result of click_on_item() with // array = (null, tx, ty, tz)? return Tile_coord(itemval.get_elem(1).get_int_value(), itemval.get_elem(2).get_int_value(), itemval.get_elem(3).get_int_value()); else // Else assume caller_item. return caller_item->get_tile(); } /* * Make sure pending text has been seen. */ void Usecode_internal::show_pending_text ( ) { if (book) // Book mode? { int x, y; while (book->show_next_page() && Get_click(x, y, Mouse::hand, 0, false, book)) ; gwin->paint(); } // Normal conversation: else if (conv->is_npc_text_pending()) click_to_continue(); } /* * Show book or scroll text. */ void Usecode_internal::show_book ( ) { char *str = String; book->add_text(str); delete [] String; String = 0; } /* * Say the current string and empty it. */ void Usecode_internal::say_string ( ) { // user_choice = 0; // Clear user's response. if (!String) return; if (book) // Displaying a book? { show_book(); return; } show_pending_text(); // Make sure prev. text was seen. char *str = String; while (*str) // Look for stopping points ("~~"). { if (*str == '*') // Just gets an extra click. { click_to_continue(); str++; continue; } char *eol = strchr(str, '~'); if (!eol) // Not found? { conv->show_npc_message(str); break; } *eol = 0; conv->show_npc_message(str); click_to_continue(); str = eol + 1; if (*str == '~') str++; // 2 in a row. } delete [] String; String = 0; } /* * Stack error. */ void Usecode_internal::stack_error ( int under // 1 if underflow. ) { if (under) cerr << "Stack underflow." << endl; else cerr << "Stack overflow." << endl; exit(1); } /* * Show an NPC's face. */ void Usecode_internal::show_npc_face ( Usecode_value& arg1, // Shape (NPC #). Usecode_value& arg2, // Frame. int slot // 0, 1, or -1 to find free spot. ) { show_pending_text(); Actor *npc = as_actor(get_item(arg1)); if (!npc) return; int shape = npc->get_face_shapenum(); int frame = arg2.get_int_value(); if (Game::get_game_type() == BLACK_GATE) { if (npc->get_npc_num() != -1) npc->set_flag (Obj_flags::met); } else if (Game::get_game_type() == SERPENT_ISLE) { // Special case: Nightmare Smith. if (npc->get_npc_num() == 296) shape = -1; } if (!conv->get_num_faces_on_screen()) gwin->get_effects()->remove_text_effects(); // Only non persistent if (gumpman->showing_gumps(true)) { gumpman->close_all_gumps(); gwin->set_all_dirty(); init_conversation(); // jsf-Added 4/20/01 for SI-Lydia. } gwin->paint_dirty(); conv->show_face(shape, frame, slot); // user_choice = 0; // Seems like a good idea. // Also seems to create a conversation bug in Test of Love :-( } /* * Remove an NPC's face. */ void Usecode_internal::remove_npc_face ( Usecode_value& arg1 // Shape (NPC #). ) { show_pending_text(); Actor *npc = as_actor(get_item(arg1)); if (!npc) return; int shape = npc->get_face_shapenum(); conv->remove_face(shape); } /* * Set an item's shape. */ void Usecode_internal::set_item_shape ( Usecode_value& item_arg, Usecode_value& shape_arg ) { int shape = shape_arg.get_int_value(); Game_object *item = get_item(item_arg); if (!item) return; // See if light turned on/off. int light_changed = item->get_info().is_light_source() != ShapeID::get_info(shape).is_light_source(); if (item->get_owner()) // Inside something? { item->get_owner()->change_member_shape(item, shape); if (light_changed) // Maybe we should repaint all. gwin->paint(); // Repaint finds all lights. else { Gump *gump = gumpman->find_gump(item); if (gump) gump->paint(); } return; } // Figure area to repaint. // Rectangle rect = gwin->get_shape_rect(item); gwin->add_dirty(item); // Get chunk it's in. Map_chunk *chunk = item->get_chunk(); chunk->remove(item); // Remove and add to update cache. item->set_shape(shape); chunk->add(item); gwin->add_dirty(item); // rect = gwin->get_shape_rect(item).add(rect); // rect.enlarge(8); // rect = gwin->clip_to_win(rect); if (light_changed) gwin->paint(); // Complete repaint refigures lights. // else // gwin->paint(rect); // Not sure... // gwin->show(); // Not sure if this is needed. } /* * Set an item's frame. */ void Usecode_internal::set_item_frame ( Game_object *item, int frame, int check_empty, // If 1, don't set empty frame. int set_rotated // Set 'rotated' bit to one in 'frame'. ) { if (!item) return; // Added 9/16/2001: if (!set_rotated) // Leave bit alone? frame = (item->get_framenum()&32)|(frame&31); if (frame == item->get_framenum()) return; // Already set to that. // Check for empty frame. ShapeID sid(item->get_shapenum(), frame, item->get_shapefile()); Shape_frame *shape = sid.get_shape(); if (!shape || (check_empty && shape->is_empty())) return; // cout << "Set_item_frame: " << item->get_shapenum() // << ", " << frame << endl; // (Don't mess up rotated frames.) if ((frame&0xf) < item->get_num_frames()) { if (item->get_owner()) // Inside a container? { item->set_frame(frame); Gump *gump = gumpman->find_gump(item); if (gump) gwin->set_all_dirty(); } else item->change_frame(frame); } gwin->set_painted(); // Make sure paint gets done. } /* * Set to repaint an object. */ void Usecode_internal::add_dirty ( Game_object *obj ) { if (obj->get_owner()) // Inside a container? { // Paint gump if open. Gump *gump = gumpman->find_gump(obj); if (gump) gwin->add_dirty(gump->get_shape_rect(obj)); } else gwin->add_dirty(obj); } /* * Remove an item from the world. */ void Usecode_internal::remove_item ( Game_object *obj ) { if (!obj) return; if (!last_created.empty() && obj == last_created.back()) last_created.pop_back(); add_dirty(obj); obj->remove_this(); } /* * Return an array containing the party, with the Avatar first. */ Usecode_value Usecode_internal::get_party ( ) { int cnt = partyman->get_count(); Usecode_value arr(1 + cnt, 0); // Add avatar. Usecode_value aval(gwin->get_main_actor()); arr.put_elem(0, aval); int num_added = 1; for (int i = 0; i < cnt; i++) { Game_object *obj = gwin->get_npc(partyman->get_member(i)); if (!obj) continue; Usecode_value val(obj); arr.put_elem(num_added++, val); } // cout << "Party: "; arr.print(cout); cout << endl; return arr; } /* * Put text near an item. */ void Usecode_internal::item_say ( Usecode_value& objval, Usecode_value& strval ) { Game_object *obj = get_item(objval); const char *str = strval.get_str_value(); if (obj && str && *str) { Effects_manager *eman = gwin->get_effects(); // Added Nov01,01 to fix 'locate': eman->remove_text_effect(obj); eman->add_text(str, obj); } } /* * Activate all cached-in usecode eggs near a given spot. */ void Usecode_internal::activate_cached ( Tile_coord pos ) { if (Game::get_game_type() != BLACK_GATE) return; // ++++Since we're not sure about it. const int dist = 16; Egg_vector vec; // Find all usecode eggs. Game_object::find_nearby(vec, pos, 275, dist, 16, c_any_qual, 7); for (Egg_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Egg_object *egg = *it; if (egg->get_criteria() == Egg_object::cached_in) egg->activate(); } } /* * For sorting up-to-down, right-to-left, and near-to-far: */ class Object_reverse_sorter { public: bool operator()(const Game_object *o1, const Game_object *o2) { Tile_coord t1 = o1->get_tile(), t2 = o2->get_tile(); if (t1.ty > t2.ty) return true; else if (t1.ty == t2.ty) { if (t1.tx > t2.tx) return true; else return t1.tx == t2.tx && t1.tz > t2.tz; } else return false; } }; /* * Return an array of nearby objects. */ Usecode_value Usecode_internal::find_nearby ( Usecode_value& objval, // Find them near this. Usecode_value& shapeval, // Shape to find, or -1 for any, // c_any_shapenum for any npc. Usecode_value& distval, // Distance in tiles? Usecode_value& mval // Some kind of mask? Guessing: // 4 == party members only. // 8 == non-party NPC's only. // 16 == something with eggs??? // 32 == monsters? invisible? ) { Game_object_vector vec; // Gets list. int shapenum; if (shapeval.is_array()) { // fixes 'lightning whip sacrifice' in Silver Seed shapenum = shapeval.get_elem(0).get_int_value(); if (shapeval.get_array_size() > 1) cerr << "Calling find_nearby with an array > 1 !!!!" << endl; } else shapenum = shapeval.get_int_value(); // It might be (tx, ty, tz). int arraysize = objval.get_array_size(); if (arraysize == 4) // Passed result of click_on_item. { Game_object::find_nearby(vec, Tile_coord(objval.get_elem(1).get_int_value(), objval.get_elem(2).get_int_value(), objval.get_elem(3).get_int_value()), shapenum, distval.get_int_value(), mval.get_int_value()); } else if (arraysize == 3 || arraysize == 5) { // Coords(x,y,z) [qual, frame] // Qual is 4th if there. int qual = arraysize == 5 ? objval.get_elem(3).get_int_value() : c_any_qual; // Frame is 5th if there. int frnum = arraysize == 5 ? objval.get_elem(4).get_int_value() : c_any_framenum; Game_object::find_nearby(vec, Tile_coord(objval.get_elem(0).get_int_value(), objval.get_elem(1).get_int_value(), objval.get_elem(2).get_int_value()), shapenum, distval.get_int_value(), mval.get_int_value(), qual, frnum); } else { Game_object *obj = get_item(objval); if (!obj) return Usecode_value(0, 0); obj = obj->get_outermost(); // Might be inside something. obj->find_nearby(vec, shapenum, distval.get_int_value(), mval.get_int_value()); } if (vec.size() > 1) // Sort right-left, near-far to fix // SI/SS cask bug. std::sort(vec.begin(), vec.end(), Object_reverse_sorter()); Usecode_value nearby(vec.size(), 0); // Create return array. int i = 0; for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Game_object *each = *it; Usecode_value val(each); nearby.put_elem(i++, val); } return (nearby); } /* * Look for a barge that an object is a part of, or on, using the same * sort (right-left, front-back) as ::find_nearby(). If there are more * than one beneath 'obj', the highest is returned. * * Output: ->barge if found, else 0. */ Barge_object *Get_barge ( Game_object *obj ) { // Check object itself. Barge_object *barge = obj->as_barge(); if (barge) return barge; Game_object_vector vec; // Find it within 20 tiles (egglike). obj->find_nearby(vec, 961, 20, 0x10); if (vec.size() > 1) // Sort right-left, near-far. std::sort(vec.begin(), vec.end(), Object_reverse_sorter()); // Object must be inside it. Tile_coord pos = obj->get_tile(); Barge_object *best = 0; for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); it++) { barge = (*it)->as_barge(); if (barge && barge->get_tile_footprint().has_point( pos.tx, pos.ty)) { int lift = barge->get_lift(); if (!best || // First qualifying? // First beneath obj.? (best->get_lift() > pos.tz && lift <= pos.tz) || // Highest beneath? (lift <= pos.tz && lift > best->get_lift())) best = barge; } } return best; } /* * Return object of given shape nearest given obj. */ Usecode_value Usecode_internal::find_nearest ( Usecode_value& objval, // Find near this. Usecode_value& shapeval, // Shape to find Usecode_value& distval // Guessing it's distance. ) { Game_object *obj = get_item(objval); if (!obj) return Usecode_value((Game_object*) NULL); Game_object_vector vec; // Gets list. obj = obj->get_outermost(); // Might be inside something. int dist = distval.get_int_value(); int shnum = shapeval.get_int_value(); // Kludge for Test of Courage: if (frame->function->id == 0x70a && shnum == 0x9a && dist == 0) dist = 16; // Mage may have wandered. obj->find_nearby(vec, shnum, dist, 0); Game_object *closest = 0; uint32 bestdist = 100000;// Distance-squared in tiles. Tile_coord t1 = obj->get_tile(); for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Game_object *each = *it; Tile_coord t2 = each->get_tile(); int dx = t1.tx - t2.tx, dy = t1.ty - t2.ty, dz = t1.tz - t2.tz; uint32 dist = dx*dx + dy*dy + dz*dz; if (dist < bestdist) { bestdist = dist; closest = each; } } return Usecode_value(closest); } /* * Find the angle (0-7) from one object to another. */ Usecode_value Usecode_internal::find_direction ( Usecode_value& from, Usecode_value& to ) { unsigned angle; // Gets angle 0-7 (north - northwest) Tile_coord t1 = get_position(from); Tile_coord t2 = get_position(to); // Treat as cartesian coords. angle = (int) Get_direction(t1.ty - t2.ty, t2.tx - t1.tx); return Usecode_value(angle); } /* * Count objects of a given shape in a container, or in the whole party. */ Usecode_value Usecode_internal::count_objects ( Usecode_value& objval, // The container, or -357 for party. Usecode_value& shapeval, // Object shape to count (c_any_shapenum=any). Usecode_value& qualval, // Quality (c_any_qual=any). Usecode_value& frameval // Frame (c_any_framenum=any). ) { long oval = objval.get_int_value(); int shapenum = shapeval.get_int_value(); int qualnum = qualval.get_int_value(); int framenum = frameval.get_int_value(); if (oval != -357) { Game_object *obj = get_item(objval); return (!obj ? 0 : obj->count_objects( shapenum, qualnum, framenum)); } // Look through whole party. Usecode_value party = get_party(); int cnt = party.get_array_size(); int total = 0; for (int i = 0; i < cnt; i++) { Game_object *obj = get_item(party.get_elem(i)); if (obj) total += obj->count_objects(shapenum, qualnum, framenum); } return (total); } /* * Get objects of a given shape in a container. */ Usecode_value Usecode_internal::get_objects ( Usecode_value& objval, // The container. Usecode_value& shapeval, // Object shape to get or c_any_shapenum for any. Usecode_value& qualval, // Quality (c_any_qual=any). Usecode_value& frameval // Frame (c_any_framenum=any). ) { Game_object *obj = get_item(objval); if (!obj) return Usecode_value((Game_object*) NULL); int shapenum = shapeval.get_int_value(); int framenum = frameval.get_int_value(); int qual = qualval.get_int_value(); Game_object_vector vec; // Gets list. obj->get_objects(vec, shapenum, qual, framenum); // cout << "Container objects found: " << cnt << << endl; Usecode_value within(vec.size(), 0); // Create return array. int i = 0; for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Game_object *each = *it; Usecode_value val(each); within.put_elem(i++, val); } return (within); } /* * Remove a quantity of an item from the party. * * Output: 1 (or the object) if successful, else 0. */ Usecode_value Usecode_internal::remove_party_items ( Usecode_value& quantval, // Quantity to remove. Usecode_value& shapeval, // Shape. Usecode_value& qualval, // Quality?? Usecode_value& frameval, // Frame. Usecode_value& flagval // Flag?? ) { int quantity = quantval.need_int_value(); int shapenum = shapeval.get_int_value(); int framenum = frameval.get_int_value(); int quality = qualval.get_int_value(); Usecode_value party = get_party(); int cnt = party.get_array_size(); if (quantity == -359 && Game::get_game_type() == SERPENT_ISLE) { // Special case. (Check party.) Game_object *obj = 0; for (int i = 0; i < cnt && !obj; i++) { Game_object *actor = get_item(party.get_elem(i)); if (actor) obj = actor->find_item(shapenum, quality, framenum); } if (!obj) return Usecode_value(0); // Problem: we need to really delete this object, but // it also has to remain long enough to be processed by the // calling usecode function... // for now: use temp_to_be_deleted to store the object and // delete it afterwards (end of Usecode_internal::run) temp_to_be_deleted = obj; obj->remove_this(1); return Usecode_value(obj); } Usecode_value all(-357); // See if they exist. Usecode_value avail = count_objects(all, shapeval, qualval, frameval); if (avail.get_int_value() < quantity) return Usecode_value(0); // Look through whole party. for (int i = 0; i < cnt && quantity > 0; i++) { Game_object *obj = get_item(party.get_elem(i)); if (obj) quantity = obj->remove_quantity(quantity, shapenum, quality, framenum); } return Usecode_value(quantity == 0); } /* * Add a quantity of an item to the party. * * Output: List of members who got objects. */ Usecode_value Usecode_internal::add_party_items ( Usecode_value& quantval, // Quantity to add. Usecode_value& shapeval, // Shape. Usecode_value& qualval, // Quality. Usecode_value& frameval, // Frame. Usecode_value& flagval // Flag?? ) { int quantity = quantval.get_int_value(); // ++++++First see if there's room. int shapenum = shapeval.get_int_value(); int framenum = frameval.get_int_value(); unsigned int quality = (unsigned int) qualval.get_int_value(); // Look through whole party. Usecode_value party = get_party(); int cnt = party.get_array_size(); Usecode_value result(0, 0); // Start with empty array. for (int i = 0; i < cnt && quantity > 0; i++) { Game_object *obj = get_item(party.get_elem(i)); if (!obj) continue; int prev = quantity; quantity = obj->add_quantity(quantity, shapenum, quality, framenum); if (quantity < prev) // Added to this NPC. result.concat(party.get_elem(i)); } if (GAME_BG) // Black gate? Just return result. return result; int todo = quantity; // SI: Put remaining on the ground. if (framenum == c_any_framenum) framenum = 0; while (todo > 0) { Tile_coord pos = Map_chunk::find_spot( gwin->get_main_actor()->get_tile(), 3, shapenum, framenum, 2); if (pos.tx == -1) // Hope this rarely happens. break; Shape_info& info = ShapeID::get_info(shapenum); // Create and place. Game_object *newobj = gmap->create_ireg_object( info, shapenum, framenum, 0, 0, 0); if (quality != c_any_qual) newobj->set_quality(quality); // set quality newobj->set_flag(Obj_flags::okay_to_take); newobj->move(pos); todo--; if (todo > 0) // Create quantity if possible. todo = newobj->modify_quantity(todo); } // SI? Append # left on ground. Usecode_value ground(quantity - todo); result.concat(ground); return result; } /* * Add a quantity of an item to a container * * Output: Num created */ Usecode_value Usecode_internal::add_cont_items ( Usecode_value& container, // What do we add to Usecode_value& quantval, // Quantity to add. Usecode_value& shapeval, // Shape. Usecode_value& qualval, // Quality. Usecode_value& frameval, // Frame. Usecode_value& flagval // Flag?? ) { int quantity = quantval.get_int_value(); int shapenum = shapeval.get_int_value(); int framenum = frameval.get_int_value(); unsigned int quality = (unsigned int) qualval.get_int_value(); Game_object *obj = get_item(container); if (obj) return Usecode_value (obj->add_quantity(quantity, shapenum, quality, framenum)); return Usecode_value(0); } /* * Remove a quantity of an item to a container * * Output: Num removed */ Usecode_value Usecode_internal::remove_cont_items ( Usecode_value& container, // What do we add to Usecode_value& quantval, // Quantity to add. Usecode_value& shapeval, // Shape. Usecode_value& qualval, // Quality. Usecode_value& frameval, // Frame. Usecode_value& flagval // Flag?? ) { int quantity = quantval.get_int_value(); int shapenum = shapeval.get_int_value(); int framenum = frameval.get_int_value(); unsigned int quality = (unsigned int) qualval.get_int_value(); Game_object *obj = get_item(container); if (obj) return Usecode_value (quantity - obj->remove_quantity(quantity, shapenum, quality, framenum)); return Usecode_value(0); } /* * Have an NPC walk somewhere and then execute usecode. * * Output: 1 if successful, else 0. */ int Usecode_internal::path_run_usecode ( Usecode_value& npcval, // # or ref. Usecode_value& locval, // Where to walk to. Usecode_value& useval, // Usecode #. Usecode_value& itemval, // Use as itemref in Usecode fun. Usecode_value& eventval, // Eventid. int find_free, // Not sure. For SI. int always // Always run function, even if failed. ) { Actor *npc = as_actor(get_item(npcval)); if (!npc) return 0; path_npc = npc; int usefun = useval.get_elem0().get_int_value(); Game_object *obj = get_item(itemval); int sz = locval.get_array_size(); if (!npc || sz < 2) { CERR("Path_run_usecode: bad inputs"); return 0; } Tile_coord src = npc->get_tile(); Tile_coord dest(locval.get_elem(0).get_int_value(), locval.get_elem(1).get_int_value(), sz == 3 ? locval.get_elem(2).get_int_value() : 0); if (dest.tz < 0) // ++++Don't understand this. dest.tz = 0; if (find_free) { /* Now works with SI lightning platform */ // Allow rise of 3 (for SI lightning). Tile_coord d = Map_chunk::find_spot(dest, 3, npc, 3); if (d.tx == -1) // No? Try at source level. d = Map_chunk::find_spot( Tile_coord(dest.tx, dest.ty, src.tz), 3, npc, 0); if (d.tx != -1) // Found it? dest = d; if (usefun == 0x60a && // ++++Added 7/21/01 to fix Iron src.distance(dest) <= 1) return 1; // Maiden loop in SI. Kludge+++++++ } if (!obj) // Just skip the usecode part. return npc->walk_path_to_tile(dest, gwin->get_std_delay(), 0); // Walk there and execute. If_else_path_actor_action *action = new If_else_path_actor_action(npc, dest, new Usecode_actor_action(usefun, obj, eventval.get_int_value())); if (always) // Set failure to same thing. action->set_failure( new Usecode_actor_action(usefun, obj, eventval.get_int_value())); npc->set_action(action); // Get into time queue. npc->start(gwin->get_std_delay(), 0); return !action->done_and_failed(); } /* * Schedule a script. */ void Usecode_internal::create_script ( Usecode_value& objval, Usecode_value& codeval, long delay // Delay from current time. ) { Game_object *obj = get_item(objval); // Pure kludge for SI wells: if (objval.get_array_size() == 2 && Game::get_game_type() == SERPENT_ISLE && obj && obj->get_shapenum() == 470 && obj->get_lift() == 0) { // We want the TOP of the well. Usecode_value v2 = objval.get_elem(1); Game_object *o2 = get_item(v2); if (o2->get_shapenum() == obj->get_shapenum() && o2->get_lift() == 2) { objval = v2; obj = o2; } } if (!obj) { cerr << "Can't create script for NULL object" << endl; return; } // ++++Better to 'steal' array; this // ends up making a copy. Usecode_value *code = new Usecode_value(codeval); Usecode_script *script = new Usecode_script(obj, code); script->start(delay); } /* * Report unhandled intrinsic. */ static void Usecode_Trace ( const char *name, int intrinsic, int num_parms, Usecode_value parms[12] ) { cout << hex << " [0x" << setfill((char)0x30) << setw(2) << intrinsic << "]: " << name << "("; for (int i = 0; i < num_parms; i++) { parms[i].print(cout); if(i!=num_parms-1) cout << ", "; } cout <<") = "; cout << dec; } static void Usecode_TraceReturn(Usecode_value &v) { v.print(cout); cout << dec << endl; } #if 0 /* Not used at the moment. */ static void Unhandled ( int intrinsic, int num_parms, Usecode_value parms[12] ) { Usecode_Trace("UNKNOWN",intrinsic,num_parms,parms); } #endif Usecode_value no_ret; Usecode_value Usecode_internal::Execute_Intrinsic(UsecodeIntrinsicFn func,const char *name,int event,int intrinsic,int num_parms,Usecode_value parms[12]) { #ifdef XWIN #if 0 && USECODE_DEBUGGER if(usecode_debugging) { // Examine the list of intrinsics for function breakpoints. if(std::find(intrinsic_breakpoints.begin(),intrinsic_breakpoints.end(),intrinsic)!=intrinsic_breakpoints.end()) { raise(SIGIO); // Breakpoint } } #endif #endif #ifdef DEBUG if(intrinsic_trace) { Usecode_Trace(name,intrinsic,num_parms,parms); cout.flush(); Usecode_value u=((*this).*func)(event,intrinsic,num_parms,parms); Usecode_TraceReturn(u); return (u); } else #endif return ((*this).*func)(event,intrinsic,num_parms,parms); } typedef Usecode_value (Usecode_internal::*UsecodeIntrinsicFn)(int event,int intrinsic,int num_parms,Usecode_value parms[12]); // missing from mingw32 header files, so included manually #ifndef __STRING #if defined __STDC__ && __STDC__ #define __STRING(x) #x #else #define __STRING(x) "x" #endif #endif #define USECODE_INTRINSIC_PTR(NAME) { &Usecode_internal::UI_ ## NAME, __STRING(NAME) } struct Usecode_internal::IntrinsicTableEntry Usecode_internal::intrinsic_table[]= { #include "bgintrinsics.h" }; // Serpent Isle Intrinsic Function Tablee // It's different to the Black Gate one. struct Usecode_internal::IntrinsicTableEntry Usecode_internal::serpent_table[]= { #include "siintrinsics.h" }; int max_bundled_intrinsics=0xff; // Index of the last intrinsic in this table /* * Call an intrinsic function. */ Usecode_value Usecode_internal::call_intrinsic ( int event, // Event type. int intrinsic, // The ID. int num_parms // # parms on stack. ) { Usecode_value parms[12]; // Get parms. for (int i = 0; i < num_parms; i++) { Usecode_value val = pop(); parms[i] = val; } if (intrinsic<=max_bundled_intrinsics) { struct Usecode_internal::IntrinsicTableEntry *table_entry; if (Game::get_game_type() == SERPENT_ISLE) table_entry = serpent_table+intrinsic; else table_entry = intrinsic_table+intrinsic; UsecodeIntrinsicFn func=(*table_entry).func; const char *name=(*table_entry).name; return Execute_Intrinsic(func,name,event,intrinsic, num_parms,parms); } return(no_ret); } /* * Wait for user to click inside a conversation. */ void Usecode_internal::click_to_continue ( ) { int xx, yy; char c; if (!gwin->get_pal()->is_faded_out())// If black screen, skip! { gwin->paint(); // Repaint scenery. Get_click(xx, yy, Mouse::hand, &c, false, conv); } conv->clear_text_pending(); // user_choice = 0; // Clear it. } /* * Set book/scroll to display. */ void Usecode_internal::set_book ( Text_gump *b // Book/scroll. ) { delete book; book = b; } /* * Get user's choice from among the possible responses. * * Output: ->user choice string. * 0 if no possible choices or user quit. */ const char *Usecode_internal::get_user_choice ( ) { if (!conv->get_num_answers()) return (0); // This does happen (Emps-honey). // if (!user_choice) // May have already been done. // (breaks conversation with Cyclops on Dagger Isle ('foul magic' option)) get_user_choice_num(); return (user_choice); } /* * Get user's choice from among the possible responses. * * Output: User choice is set, with choice # returned. * -1 if no possible choices. */ int Usecode_internal::get_user_choice_num ( ) { user_choice = 0; conv->show_avatar_choices(); int x, y; // Get click. int choice_num; do { char chr; // Allow '1', '2', etc. gwin->paint(); // Paint scenery. int result=Get_click(x, y, Mouse::hand, &chr, false, conv); if (result<=0) { // ESC pressed, select 'bye' if poss. choice_num = conv->locate_answer("bye"); } else if (chr) { // key pressed if (chr>='1' && chr <='0'+conv->get_num_answers()) { choice_num = chr - '1'; } else choice_num = -1; //invalid key } else choice_num = conv->conversation_choice(x, y); } // Wait for valid choice. while (choice_num < 0 || choice_num >= conv->get_num_answers()); conv->clear_avatar_choices(); // Store ->answer string. user_choice = conv->get_answer(choice_num); return (choice_num); // Return choice #. } /* * Create for the outside world. */ Usecode_machine *Usecode_machine::create ( ) { return new Usecode_internal(); } /* * Create machine from a 'usecode' file. */ Usecode_internal::Usecode_internal ( ) : Usecode_machine(), book(0), caller_item(0), path_npc(0), user_choice(0), saved_pos(-1, -1, -1), String(0), stack(new Usecode_value[1024]), intercept_item(0), temp_to_be_deleted(0), telekenesis_fun(-1), modified_map(false) #ifdef USECODE_DEBUGGER , on_breakpoint(false) #endif { // Clear timers. memset((char *) &timers[0], 0, sizeof(timers)); sp = stack; ifstream file; // Read in usecode. try { U7open(file, USECODE); read_usecode(file); file.close(); } catch(const file_exception & f) { if (!Game::is_editing()) // Ok if map-editing. throw f; std::cerr << "Warning (map-editing): Couldn't open '" << USECODE << "'" << endl; } // Get custom usecode functions. if (is_system_path_defined("") && U7exists(PATCH_USECODE)) { U7open(file, PATCH_USECODE); read_usecode(file, true); file.close(); } // set_breakpoint(); } /* * Read in usecode functions. These may override previously read * functions. */ void Usecode_internal::read_usecode ( istream &file, bool patch // True if reading from 'patch'. ) { file.seekg(0, ios::end); int size = file.tellg(); // Get file size. file.seekg(0); // Read in all the functions. while (file.tellg() < size) { Usecode_function *fun = new Usecode_function(file); Exult_vector & vec = funs[fun->id/0x100]; int i = fun->id%0x100; if (i < vec.size() && vec[i]) { // Already have one there. if (patch) // Patching? { if (vec[i]->orig) { // Patching a patch. fun->orig = vec[i]->orig; delete vec[i]; } else // Patching fun. from static. fun->orig = vec[i]; } else { delete vec[i]->orig; delete vec[i]; } } vec.put(i, fun); } } /* * Delete. */ Usecode_internal::~Usecode_internal ( ) { delete [] stack; delete [] String; int num_slots = sizeof(funs)/sizeof(funs[0]); for (int i = 0; i < num_slots; i++) { vector& slot = funs[i]; int cnt = slot.size(); for (int j = 0; j < cnt; j++) delete slot[j]; } delete book; } #ifdef DEBUG int debug = 2; // 2 for more stuff. static int ucbp_fun = -1, ucbp_ip = -1; // Breakpoint. void Setbreak(int fun, int ip) { ucbp_fun = fun; ucbp_ip = ip; } void Clearbreak() { ucbp_fun = ucbp_ip = -1; } #endif #define CERR_CURRENT_IP()\ cerr << " (at function = " << hex << setw(4) << setfill('0')\ << frame->function->id << ", ip = " \ << current_IP << dec << setfill(' ') << ")" << endl #define LOCAL_VAR_ERROR(x)\ cerr << "Local variable #" << (x) << " out of range!";\ CERR_CURRENT_IP() #define DATA_SEGMENT_ERROR()\ cerr << "Data pointer out of range!";\ CERR_CURRENT_IP() #define EXTERN_ERROR()\ cerr << "Extern offset out of range!";\ CERR_CURRENT_IP() #define FLAG_ERROR(x)\ cerr << "Global flag #" << (x) << " out of range!";\ CERR_CURRENT_IP() /* * The main usecode interpreter * * Output: */ int Usecode_internal::run() { bool aborted = false; bool initializing_loop = false; while (frame = call_stack.front()) { int num_locals = frame->num_vars + frame->num_args; int offset; int sval; bool frame_changed = false; // set some variables for use in other member functions caller_item = frame->caller_item; /* * Main loop. */ while (!frame_changed) { if ((frame->ip >= frame->endp) || (frame->ip < frame->code)) { cerr << "Usecode: jumped outside of code segment of " << "function " << hex << setw(4) << setfill('0') << frame->function->id << dec << setfill(' ') << " ! Aborting." << endl; abort_function(); frame_changed = true; continue; } int current_IP = frame->ip - frame->code; int opcode = *(frame->ip); if (frame->ip + get_opcode_length(opcode) > frame->endp) { cerr << "Operands lie outside of code segment. "; CERR_CURRENT_IP(); continue; } #ifdef DEBUG if (usecode_trace == 2) { uc_trace_disasm(frame); } #endif #ifdef USECODE_DEBUGGER // check breakpoints int bp = breakpoints.check(frame); if (bp != -1) { // we hit a breakpoint // allow handling extra debugging messages on_breakpoint = true; cout << "On breakpoint" << endl; // signal remote client that we hit a breakpoint unsigned char c=(unsigned char)Exult_server::dbg_on_breakpoint; if (client_socket >= 0) Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, &c, 1); #ifdef XWIN raise(SIGUSR1); // to allow trapping it in gdb too #endif #if 0 // little console mode "debugger" (if you can call it that...) bool done = false; while (!done) { char userinput; cout << "s=step into, o=step over, f=finish, c=continue, " << "b=stacktrace: "; cin >> userinput; if (userinput == 's') { breakpoints.add(new AnywhereBreakpoint()); cout << "Stepping into..." << endl; done = true; } else if (userinput == 'o') { breakpoints.add(new StepoverBreakpoint(frame)); cout << "Stepping over..." << endl; done = true; } else if (userinput == 'f') { breakpoints.add(new FinishBreakpoint(frame)); cout << "Finishing function..." << endl; done = true; } else if (userinput == 'c') { done = true; } else if (userinput == 'b') { stack_trace(cout); } } #elif (defined(USE_EXULTSTUDIO)) breakpoint_action = -1; while (breakpoint_action == -1) { SDL_Delay(20); Server_delay(Handle_client_debug_message); } #endif c = (unsigned char)Exult_server::dbg_continuing; if (client_socket >= 0) Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, &c, 1); // disable extra debugging messages again on_breakpoint = false; } #endif frame->ip++; switch (opcode) { case 0x04: // start conversation case 0x84: // (32 bit version) { if (opcode < 0x80) offset = (short) Read2(frame->ip); else offset = (sint32) Read4(frame->ip); found_answer = false; if (!get_user_choice()) // Exit conv. if no choices. frame->ip += offset; // (Emps and honey.) break; } case 0x05: // JNE. { offset = (short) Read2(frame->ip); Usecode_value val = pop(); if (val.is_false()) frame->ip += offset; break; } case 0x85: // JNE32 { offset = (sint32) Read4(frame->ip); Usecode_value val = pop(); if (val.is_false()) frame->ip += offset; break; } case 0x06: // JMP. offset = (short) Read2(frame->ip); frame->ip += offset; break; case 0x86: // JMP32 offset = (sint32) Read4(frame->ip); frame->ip += offset; break; case 0x07: // CMPS. case 0x87: // (32 bit version) { int cnt = Read2(frame->ip); // # strings. if (opcode < 0x80) offset = (short) Read2(frame->ip); else offset = (sint32) Read4(frame->ip); bool matched = false; // only try to match if we haven't found an answer yet while (!matched && !found_answer && cnt-- > 0) { Usecode_value s = pop(); const char *str = s.get_str_value(); if (str && strcmp(str, user_choice) == 0) { matched = true; found_answer = true; } } while (cnt-- > 0) // Pop rest of stack. pop(); if (!matched) // Jump if no match. frame->ip += offset; } break; case 0x09: // ADD. { Usecode_value v2 = pop(); Usecode_value v1 = pop(); Usecode_value sum = v1 + v2; push(sum); break; } case 0x0a: // SUB. sval = popi(); pushi(popi() - sval); break; case 0x0b: // DIV. sval = popi(); pushi(popi()/sval); break; case 0x0c: // MUL. pushi(popi()*popi()); break; case 0x0d: // MOD. sval = popi(); pushi(popi() % sval); break; case 0x0e: // AND. { Usecode_value v1 = pop(); Usecode_value v2 = pop(); int result = v1.is_true() && v2.is_true(); pushi(result); break; } case 0x0f: // OR. { Usecode_value v1 = pop(); Usecode_value v2 = pop(); int result = v1.is_true() || v2.is_true(); pushi(result); break; } case 0x10: // NOT. pushi(!pop().is_true()); break; case 0x12: // POP into a variable. { offset = Read2(frame->ip); // Get value. Usecode_value val = pop(); if (offset < 0 || offset >= num_locals) { LOCAL_VAR_ERROR(offset); } else { frame->locals[offset] = val; } } break; case 0x13: // PUSH true. pushi(1); break; case 0x14: // PUSH false. pushi(0); break; case 0x16: // CMPGT. sval = popi(); pushi(popi() > sval); // Order? break; case 0x17: // CMPL. sval = popi(); pushi(popi() < sval); break; case 0x18: // CMPGE. sval = popi(); pushi(popi() >= sval); break; case 0x19: // CMPLE. sval = popi(); pushi(popi() <= sval); break; case 0x1a: // CMPNE. { Usecode_value val1 = pop(); Usecode_value val2 = pop(); pushi(!(val1 == val2)); break; } case 0x1c: // ADDSI. offset = Read2(frame->ip); if (offset < 0 || frame->data + offset >= frame->externs-6) { DATA_SEGMENT_ERROR(); break; } append_string((char*)(frame->data + offset)); break; case 0x9c: // ADDSI32 offset = (sint32)Read4(frame->ip); if (offset < 0 || frame->data + offset >= frame->externs-6) { DATA_SEGMENT_ERROR(); break; } append_string((char*)(frame->data + offset)); break; case 0x1d: // PUSHS. offset = Read2(frame->ip); if (offset < 0 || frame->data + offset >= frame->externs-6) { DATA_SEGMENT_ERROR(); break; } pushs((char*)(frame->data + offset)); break; case 0x9d: // PUSHS32 offset = (sint32)Read4(frame->ip); if (offset < 0 || frame->data + offset >= frame->externs-6) { DATA_SEGMENT_ERROR(); break; } pushs((char*)(frame->data + offset)); break; case 0x1e: // ARRC. { // Get # values to pop into array. int num = Read2(frame->ip); int cnt = num; Usecode_value arr(num, 0); int to = 0; // Store at this index. while (cnt--) { Usecode_value val = pop(); to += arr.add_values(to, val); } if (to < num)// 1 or more vals empty arrays? arr.resize(to); push(arr); } break; case 0x1f: // PUSHI. { // Might be negative. short ival = Read2(frame->ip); pushi(ival); break; } case 0x9f: // PUSHI32 { int ival = (sint32)Read4(frame->ip); pushi(ival); break; } case 0x21: // PUSH. offset = Read2(frame->ip); if (offset < 0 || offset >= num_locals) { LOCAL_VAR_ERROR(offset); pushi(0); } else { push(frame->locals[offset]); } break; case 0x22: // CMPEQ. { Usecode_value val1 = pop(); Usecode_value val2 = pop(); pushi(val1 == val2); break; } case 0x24: // CALL. { offset = Read2(frame->ip); if (offset < 0 || offset >= frame->num_externs) { EXTERN_ERROR(); break; } uint8 *tempptr = frame->externs + 2*offset; int funcid = Read2(tempptr); call_function(funcid, frame->eventid); frame_changed = true; break; } case 0x25: // RET. (End of procedure reached) case 0x2C: // RET. (Return from procedure) show_pending_text(); return_from_procedure(); frame_changed = true; break; case 0x26: // AIDX. { sval = popi(); // Get index into array. sval--; // It's 1 based. // Get # of local to index. offset = Read2(frame->ip); if (offset < 0 || offset >= num_locals) { LOCAL_VAR_ERROR(offset); pushi(0); break; } if (sval < 0) { cerr << "AIDX: Negative array index: " << sval << endl; pushi(0); break; } Usecode_value& val = frame->locals[offset]; if (val.is_array()) { push(val.get_elem(sval)); } else if (sval == 0) { push(val); // needed for SS keyring (among others) } else { pushi(0); // guessing... probably unnecessary } break; } case 0x2d: // RET. (Return from function) { Usecode_value r = pop(); return_from_function(r); frame_changed = true; break; } case 0x2e: // INITLOOP (1st byte of loop) case 0xae: // (32 bit version) { int nextopcode = *(frame->ip); if ((opcode == 0x2e && nextopcode != 0x02) || (opcode == 0xae && nextopcode != 0x82)) { cerr << "2nd byte in loop isn't a 0x02 (or 0x82)!"<ip); // Total count. int local2 = Read2(frame->ip); // Current value of loop var. int local3 = Read2(frame->ip); // Array of values to loop over. int local4 = Read2(frame->ip); // Get offset to end of loop. if (opcode < 0x80) offset = (short) Read2(frame->ip); else offset = (sint32) Read4(frame->ip); // 32 bit offset if (local1 < 0 || local1 >= num_locals) { LOCAL_VAR_ERROR(local1); break; } if (local2 < 0 || local2 >= num_locals) { LOCAL_VAR_ERROR(local1); break; } if (local3 < 0 || local3 >= num_locals) { LOCAL_VAR_ERROR(local1); break; } if (local4 < 0 || local4 >= num_locals) { LOCAL_VAR_ERROR(local1); break; } // Get array to loop over. Usecode_value& arr = frame->locals[local4]; int next = frame->locals[local1].get_int_value(); if (initializing_loop) { // Initialize loop. initializing_loop = false; int cnt = arr.is_array() ? arr.get_array_size() : 1; frame->locals[local2] = Usecode_value(cnt); frame->locals[local1] = Usecode_value(0); next = 0; } else if (GAME_SI) { // in SI, the loop-array can be modified in-loop, it seems // (conv. with Spektran, 044D:00BE) // so, check for changes of the array size, and adjust // total count and next value accordingly. int cnt = arr.is_array() ? arr.get_array_size() : 1; if (cnt != frame->locals[local2].get_int_value()) { // update new total count frame->locals[local2] = Usecode_value(cnt); if (std::abs(cnt-frame->locals[local2].get_int_value())==1) { // small change... we can fix this Usecode_value& curval = arr.is_array() ? arr.get_elem(next - 1) : arr; if (curval != frame->locals[local3]) { if (cnt>frame->locals[local2].get_int_value()){ //array got bigger, it seems //addition occured before the current value next++; } else { //array got smaller //deletion occured before the current value next--; } } else { //addition/deletion was after the current value //so don't need to update 'next' } } else { // big change... // just update total count to make sure // we don't crash } } if (cnt != frame->locals[local2].get_int_value()) { // update new total count frame->locals[local2] = Usecode_value(cnt); Usecode_value& curval = arr.is_array() ? arr.get_elem(next - 1) : arr; if (curval != frame->locals[local3]) { if (cnt > frame->locals[local2].get_int_value()) { // array got bigger, it seems // addition occured before the current value next++; } else { // array got smaller // deletion occured before the current value next--; } } else { // addition/deletion was after the current value // so don't need to update 'next' } } } // End of loop? if (next >= frame->locals[local2].get_int_value()) { frame->ip += offset; } else // Get next element. { frame->locals[local3] = arr.is_array() ? arr.get_elem(next) : arr; frame->locals[local1] = Usecode_value(next + 1); } break; } case 0x2f: // ADDSV. { offset = Read2(frame->ip); if (offset < 0 || offset >= num_locals) { LOCAL_VAR_ERROR(offset); break; } const char *str = frame->locals[offset].get_str_value(); if (str) append_string(str); else // Convert integer. { // 25-09-2001 - Changed to >= 0 to fix money-counting in SI. // if (locals[offset].get_int_value() != 0) { if (frame->locals[offset].get_int_value() >= 0) { char buf[20]; snprintf(buf, 20, "%ld", frame->locals[offset].get_int_value()); append_string(buf); } } break; } case 0x30: // IN. Is a val. in an array? { Usecode_value arr = pop(); // If an array, use 1st elem. Usecode_value val = pop().get_elem0(); pushi(arr.find_elem(val) >= 0); break; } case 0x31: // Unknown. case 0xB1: // (32 bit version) // this opcode only occurs in the 'audition' usecode function (BG) // not sure what it's supposed to do, but this function results // in the same behaviour as the original frame->ip += 2; if (opcode < 0x80) offset = (short)Read2(frame->ip); else offset = (sint32)Read4(frame->ip); if (!found_answer) found_answer = true; else frame->ip += offset; break; case 0x32: // RET. (End of function reached) { show_pending_text(); Usecode_value zero(0); return_from_function(zero); frame_changed = true; break; } case 0x33: // SAY. say_string(); break; case 0x38: // CALLIS. { offset = Read2(frame->ip); sval = *(frame->ip)++; // # of parameters. Usecode_value ival = call_intrinsic(frame->eventid, offset, sval); push(ival); frame_changed = true; break; } case 0x39: // CALLI. offset = Read2(frame->ip); sval = *(frame->ip)++; // # of parameters. call_intrinsic(frame->eventid, offset, sval); frame_changed = true; break; case 0x3e: // PUSH ITEMREF. pushref(frame->caller_item); break; case 0x3f: // ABRT. show_pending_text(); abort_function(); frame_changed = true; aborted = true; break; case 0x40: // end conversation found_answer = true; break; case 0x42: // PUSHF. offset = Read2(frame->ip); if (offset < 0 || offset >= 1024) { FLAG_ERROR(offset); pushi(0); } pushi(gflags[offset]); break; case 0x43: // POPF. offset = Read2(frame->ip); if (offset < 0 || offset >= 1024) { FLAG_ERROR(offset); } gflags[offset] = (unsigned char) popi(); // ++++KLUDGE for Monk Isle: if (offset == 0x272 && Game::get_game_type() == SERPENT_ISLE) gflags[offset] = 0; break; case 0x44: // PUSHB. pushi(*(frame->ip)++); break; case 0x46: // Set array element. { // Get # of local array. offset = Read2(frame->ip); if (offset < 0 || offset >= num_locals) { LOCAL_VAR_ERROR(offset); break; } Usecode_value& arr = frame->locals[offset]; short index = popi(); index--; // It's 1-based. Usecode_value val = pop(); int size = arr.get_array_size(); if (index >= 0 && (index < size || arr.resize(index + 1))) arr.put_elem(index, val); break; } case 0x47: // CALLE. Stack has caller_item. { Usecode_value ival = pop(); Game_object *caller = get_item(ival); push(ival); // put caller_item back on stack offset = Read2(frame->ip); call_function(offset, frame->eventid, caller); frame_changed = true; break; } case 0x48: // PUSH EVENTID. pushi(frame->eventid); break; case 0x4a: // ARRA. { Usecode_value val = pop(); Usecode_value arr = pop(); push(arr.concat(val)); break; } case 0x4b: // POP EVENTID. frame->eventid = popi(); break; case 0x4c: // debugging opcode from spanish SI (line number) { frame->line_number = Read2(frame->ip); break; } case 0x4d: // debugging opcode from spanish SI (function init) { int funcname = Read2(frame->ip); int paramnames = Read2(frame->ip); break; } case 0x50: // PUSH static. offset = Read2(frame->ip); if (offset < 0) // Global static. if (-offset < statics.size()) push(statics[-offset]); else pushi(0); else if (offset < frame->function->statics.size()) push(frame->function->statics[offset]); else pushi(0); break; case 0x51: // POP static. { offset = Read2(frame->ip); // Get value. Usecode_value val = pop(); if (offset < 0) statics.put(-offset, val); else frame->function->statics.put( offset, val); } break; case 0x52: // CALLO (call original). { // Otherwise, like CALLE. Usecode_value ival = pop(); Game_object *caller = get_item(ival); push(ival); // put caller_item back on stack offset = Read2(frame->ip); call_function(offset, frame->eventid, caller, false, true); frame_changed = true; break; } case 0xcd: // 32 bit debugging function init { int funcname = (sint32)Read4(frame->ip); int paramnames = (sint32)Read4(frame->ip); break; } default: cerr << "Opcode " << opcode << " not known. "; CERR_CURRENT_IP(); break; } } } if (call_stack.front() == 0) { // pop the NULL frame from the stack call_stack.pop_front(); } if (aborted) return 0; return 1; } /* * This is the main entry for outside callers. * * Output: -1 if not found. * 0 if can't execute now or if aborted. * 1 otherwise. */ int Usecode_internal::call_usecode ( int id, // Function #. Game_object *obj, // Item ref. Usecode_events event ) { // Avoid these when already execing. if (!call_stack.empty() && event == npc_proximity && Game::get_game_type() == BLACK_GATE) return (0); conv->clear_answers(); int ret; if (call_function(id, event, obj, true)) ret = run(); else ret = -1; // failed to call the function set_book(0); // Left hanging (BG)? if (conv->get_num_faces_on_screen() > 0) { conv->init_faces(); // Remove them. gwin->set_all_dirty(); // Force repaint. } if (modified_map) { // On a barge, and we changed the map. Barge_object *barge = gwin->get_moving_barge(); if (barge) barge->set_to_gather(); // Refigure what's on barge. modified_map = false; } return ret; } /* * Start speech, or show text if speech isn't enabled. */ void Usecode_internal::do_speech ( int num ) { speech_track = num; // Used in Usecode function. if (!Audio::get_ptr()->start_speech(num)) // No speech? Call text function. call_usecode(0x614, gwin->get_main_actor(), double_click); } /* * Write out one usecode value. */ static void Write_useval ( ostream& out, Usecode_value& val ) { unsigned char buf[1024]; int len = val.save(buf, sizeof(buf)); if (len < 0) throw file_exception("Static usecode value overflows buf"); else out.write((char *) buf, len); } /* * Write out global data to 'gamedat/usecode.dat'. * (and 'gamedat/keyring.dat') * * Output: 0 if error. */ void Usecode_internal::write ( ) { // Assume new games will have keyring. if (Game::get_game_type() != BLACK_GATE) keyring->write(); // write keyring data ofstream out; U7open(out, FLAGINIT); // Write global flags. out.write((char*)gflags, sizeof(gflags)); out.close(); U7open(out, USEDAT); Write2(out, partyman->get_count()); // Write party. int i; // Blame MSVC for (i = 0; i < EXULT_PARTY_MAX; i++) Write2(out, partyman->get_member(i)); // Timers. for (size_t t = 0; t < sizeof(timers)/sizeof(timers[0]); t++) Write4(out, timers[t]); Write2(out, saved_pos.tx); // Write saved pos. Write2(out, saved_pos.ty); Write2(out, saved_pos.tz); out.flush(); if( !out.good() ) throw file_write_exception(USEDAT); out.close(); U7open(out, USEVARS); // Static variables. 1st, globals. Write4(out, statics.size()); // # globals. Exult_vector::iterator it; for (it = statics.begin(); it != statics.end(); ++it) Write_useval(out, *it); // Now do the local statics. int num_slots = sizeof(funs)/sizeof(funs[0]); for (i = 0; i < num_slots; i++) { vector& slot = funs[i]; for (std::vector::iterator fit = slot.begin(); fit != slot.end(); ++fit) { Usecode_function *fun = *fit; if (!fun || fun->statics.empty()) continue; Write4(out, fun->id); Write4(out, fun->statics.size()); for (it = fun->statics.begin(); it != fun->statics.end(); ++it) Write_useval(out, *it); } } Write4(out, 0xffffffffU); // End with -1. out.flush(); if( !out.good() ) throw file_write_exception(USEVARS); out.close(); } /* * Read in global data from 'gamedat/usecode.dat'. * (and 'gamedat/keyring.dat') * * Output: 0 if error. */ void Usecode_internal::read ( ) { if (Game::get_game_type() == SERPENT_ISLE) keyring->read(); // read keyring data ifstream in; try { U7open(in, FLAGINIT); // Read global flags. in.read((char*)gflags, sizeof(gflags)); in.close(); } catch(exult_exception &e) { if (!Game::is_editing()) throw e; memset(&gflags[0], 0, sizeof(gflags)); } try { U7open(in, USEVARS); read_usevars(in); in.close(); } catch(exult_exception &e) { ; // Okay if this doesn't exist. // ++++Maybe we should clear them all. } try { U7open(in, USEDAT); } catch(exult_exception &e) { partyman->set_count(0); partyman->link_party(); // Still need to do this. return; // Not an error if no saved game yet. } partyman->set_count(Read2(in)); // Read party. size_t i; // Blame MSVC for (i = 0; i < EXULT_PARTY_MAX; i++) partyman->set_member(i, Read2(in)); partyman->link_party(); // Timers. for (size_t t = 0; t < sizeof(timers)/sizeof(timers[0]); t++) timers[t] = Read4(in); if (!in.good()) throw file_read_exception(USEDAT); saved_pos.tx = Read2(in); // Read in saved position. saved_pos.ty = Read2(in); saved_pos.tz = Read2(in); if (!in.good() || // Failed.+++++Can remove this later. saved_pos.tz < 0 || saved_pos.tz > 13) saved_pos = Tile_coord(-1, -1, -1); } /* * Read in static variables from USEVARS. */ void Usecode_internal::read_usevars ( std::istream& in ) { in.seekg(0, ios::end); int size = in.tellg(); // Get file size. in.seekg(0); if (!size) return; unsigned char *buf = new unsigned char[size]; // Get the whole thing. in.read((char *) buf, size); unsigned char *ptr = buf; unsigned char *ebuf = buf + size; int cnt = Read4(ptr); // Global statics. statics.resize(cnt); int i; for (i = 0; i < cnt; i++) statics[i].restore(ptr, ebuf - ptr); unsigned long funid; while (ptr < ebuf && (funid = Read4(ptr)) != 0xffffffffU) { int cnt = Read4(ptr); vector& slot = funs[funid/0x100]; size_t index = funid%0x100; Usecode_function *fun = index < slot.size() ? slot[index] : 0; if (!fun) { cerr << "Usecode " << funid << " not found" << endl; continue; } fun->statics.resize(cnt); for (i = 0; i < cnt; i++) fun->statics[i].restore(ptr, ebuf - ptr); } delete [] buf; } #ifdef USECODE_DEBUGGER int Usecode_internal::get_callstack_size() const { return call_stack.size(); } Stack_frame* Usecode_internal::get_stackframe(int i) { if (i >= 0 && i < call_stack.size()) return call_stack[i]; else return 0; } // return current size of the stack int Usecode_internal::get_stack_size() const { return (int)(sp - stack); } // get an(y) element from the stack. (depth == 0 is top element) Usecode_value* Usecode_internal::peek_stack(int depth) const { if (depth < 0 || depth >= get_stack_size()) return 0; return (sp - depth - 1); } // modify an(y) element on the stack. (depth == 0 is top element) void Usecode_internal::poke_stack(int depth, Usecode_value& val) { if (depth < 0 || (sp - depth) < stack) return; *(sp - depth) = val; } void Usecode_internal::set_breakpoint() { breakpoints.add(new AnywhereBreakpoint()); } void Usecode_internal::dbg_stepover() { if (on_breakpoint) breakpoints.add(new StepoverBreakpoint(call_stack.front())); } void Usecode_internal::dbg_finish() { if (on_breakpoint) breakpoints.add(new FinishBreakpoint(call_stack.front())); } int Usecode_internal::set_location_breakpoint(int funcid, int ip) { Breakpoint *bp = new LocationBreakpoint(funcid, ip); breakpoints.add(bp); return bp->id; } #endif exult-1.2/usecode/ucserial.cc0000644000175000001440000000564107724430454011756 /* * ucserial.cc - Serialization of usecode objects * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "servemsg.h" #include "ucserial.h" #include "useval.h" #include "utils.h" #include "debugmsg.h" /* /* * Read/write out data common to all objects. * * Output: 1 if successful, else 0. */ template void Stack_frame_io ( Serial& io, int& functionid, int& ip, int& call_chain, int& call_depth, int& eventid, int& caller_item, int& num_args, int& num_vars ) { unsigned char c = (unsigned char)Exult_server::dbg_stackframe; io << c << functionid << ip << call_chain << call_depth << eventid << caller_item << num_args << num_vars; // locals! } int Stack_frame_out ( int fd, // Socket. int functionid, int ip, int call_chain, int call_depth, int eventid, int caller_item, int num_args, int num_vars, Usecode_value* locals ) { static unsigned char buf[Exult_server::maxlength]; unsigned char *ptr = &buf[0]; Serial_out io(ptr); Stack_frame_io(io, functionid, ip, call_chain, call_depth, eventid, caller_item, num_args, num_vars); int remaining = Exult_server::maxlength - (ptr - buf); for (int i = 0; i < num_args + num_vars; i++) { int vallen = locals[i].save(ptr, remaining); // error checking... ptr += vallen; remaining -= vallen; } return Exult_server::Send_data(fd, Exult_server::usecode_debugging, buf, ptr - buf); // locals! } bool Stack_frame_in ( unsigned char *data, // Data that was read. int datalen, // Length of data. int& functionid, int& ip, int& call_chain, int& call_depth, int& eventid, int& caller_item, int& num_args, int& num_vars, Usecode_value*& locals ) { unsigned char *ptr = data; Serial_in io(ptr); Stack_frame_io(io, functionid, ip, call_chain, call_depth, eventid, caller_item, num_args, num_vars); int remaining = datalen - (ptr - data); locals = new Usecode_value[num_args + num_vars]; for (int i = 0; i < num_args + num_vars; i++) { unsigned char *tmpptr = ptr; locals[i].restore(ptr, remaining); // error checking... remaining -= (ptr - tmpptr); } return (ptr - data) == datalen; // locals! } exult-1.2/usecode/compiler/0000777000175000001440000000000010062225333011513 5exult-1.2/usecode/compiler/uclabel.h0000644000175000001440000000303707414703447013230 /* Copyright (C) 2002 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCLABEL #define INCL_UCLABEL #include #include class Uc_label { private: std::string name; // This will be the key. std::vector references; // jumps in the output to this label // contains absolute offsets int offset; // location of the label bool valid; public: Uc_label(std::string n) : name(n), offset(0), valid(false) { } Uc_label(std::string n, int o) : name(n), offset(o), valid(true) { } std::string& get_name() { return name; } std::vector& get_references() { return references; } int get_offset() const { return offset; } bool is_valid() const { return valid; } bool set_offset(int o) { if (valid) return false; valid = true; offset = o; } void add_reference(int offset) { references.push_back(offset); } }; #endif exult-1.2/usecode/compiler/ucmain.cc0000644000175000001440000000574607732251221013233 /** ** Ucmain.cc - Usecode Compiler ** ** Written: 12/30/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "ucloc.h" #include "ucfun.h" #ifndef ALPHA_LINUX_CXX # include #endif using std::strcpy; using std::strrchr; using std::strlen; using std::ios; // THIS is what the parser produces. extern std::vector functions; std::vector include_dirs; // -I directories. /* * MAIN. */ int main ( int argc, char **argv ) { extern int yyparse(); extern FILE *yyin; char *src; char outbuf[256]; char *outname = 0; static char *optstring = "o:I:s"; extern int optind, opterr, optopt; extern char *optarg; Uc_function::Intrinsic_type ty = Uc_function::bg; opterr = 0; // Don't let getopt() print errs. int optchr; while ((optchr = getopt(argc, argv, optstring)) != -1) switch (optchr) { case 'o': // Output to write. outname = optarg; break; case 'I': // Include dir. include_dirs.push_back(optarg); break; case 's': ty = Uc_function::si; break; } if (optind < argc) // Filename? { src = argv[optind]; yyin = fopen(argv[optind], "r"); if (!outname) // No -o option? { // Set up output name. outname = strncpy(outbuf, src, sizeof(outbuf) - 5); outbuf[sizeof(outbuf) - 5] = 0; char *dot = strrchr(outname, '.'); if (!dot) dot = outname + strlen(outname); strcpy(dot, ".uco"); } } else { src = ""; yyin = stdin; if (!outname) outname = strcpy(outbuf, "a.ucout"); } Uc_location::set_cur(src, 0); // For now, use black gate. Uc_function::set_intrinsics(ty); #if 0 //++++TESTING int tok; extern int yylex(); while ((tok = yylex()) != EOF) printf("%d\n", tok); #endif yyparse(); int errs = Uc_location::get_num_errors(); if (errs > 0) // Check for errors. return errs; // Open output. std::ofstream out(outname, ios::binary|ios::out); for (std::vector::iterator it = functions.begin(); it != functions.end(); it++) { Uc_function *fun = *it; fun->gen(out); // Generate function. } return Uc_location::get_num_errors(); } /* * Report error. */ void yyerror ( char *s ) { Uc_location::yyerror(s); } exult-1.2/usecode/compiler/opcodes.h0000644000175000001440000000344407732251221013246 /** ** Opcodes.h - Opcode definitions for Usecode. ** ** Written: 1/1/01 - JSF **/ #ifndef INCL_OPCODES #define INCL_OPCODES 1 const char UC_LOOPTOP = 0x02; const char UC_CONVERSE = 0x04; const char UC_JNE = 0x05; const char UC_JMP = 0x06; const char UC_CMPS = 0x07; const char UC_ADD = 0x09; const char UC_SUB = 0x0a; const char UC_DIV = 0x0b; const char UC_MUL = 0x0c; const char UC_MOD = 0x0d; const char UC_AND = 0x0e; const char UC_OR = 0x0f; const char UC_NOT = 0x10; const char UC_POP = 0x12; const char UC_PUSHTRUE = 0x13; const char UC_PUSHFALSE = 0x14; const char UC_CMPG = 0x16; const char UC_CMPL = 0x17; const char UC_CMPGE = 0x18; const char UC_CMPLE = 0x19; const char UC_CMPNE = 0x1a; const char UC_ADDSI = 0x1c; const char UC_PUSHS = 0x1d; const char UC_ARRC = 0x1e; const char UC_PUSHI = 0x1f; const char UC_PUSH = 0x21; const char UC_CMPEQ = 0x22; const char UC_CALL = 0x24; const char UC_RET = 0x25; const char UC_AIDX = 0x26; const char UC_RET2 = 0x2c; const char UC_SETR = 0x2d; // ?? const char UC_LOOP = 0x2e; const char UC_ADDSV = 0x2f; const char UC_IN = 0x30; const char UC_RTS = 0x32; const char UC_SAY = 0x33; const char UC_CALLIS = 0x38; const char UC_CALLI = 0x39; const char UC_PUSHITEMREF = 0x3e; const char UC_ABRT = 0x3f; const char UC_CONVERSELOC = 0x40; // CONVERSE jmps here. const char UC_PUSHF = 0x42; // PUSH global flag. const char UC_POPF = 0x43; // POP global flag. const char UC_PUSHB = 0x44; // Push byte that follows. const char UC_POPARR = 0x46; // Pop into array elem. const char UC_CALLE = 0x47; const char UC_PUSHEVENTID = 0x48; const char UC_ARRA = 0x4a; const char UC_POPEVENTID = 0x4b; // Added for Exult: const char UC_PUSHSTATIC = 0x50; // Push static. const char UC_POPSTATIC = 0x51; // Pop static. const char UC_CALLO = 0x52; // Call original. #endif exult-1.2/usecode/compiler/ucstmt.cc0000644000175000001440000002776707471600176013314 /** ** Ucstmt.cc - Usecode compiler statements. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "ucstmt.h" #include "ucexpr.h" #include "ucsym.h" #include "opcodes.h" #include "utils.h" #include "ucfun.h" using std::vector; using std::string; int Uc_converse2_statement::nest = 0; /* * Delete. */ Uc_block_statement::~Uc_block_statement ( ) { // Delete all the statements. for (std::vector::const_iterator it = statements.begin(); it != statements.end(); it++) delete (*it); } /* * Generate code. */ void Uc_block_statement::gen ( vector& out, Uc_function *fun ) { for (std::vector::const_iterator it = statements.begin(); it != statements.end(); it++) { Uc_statement *stmt = *it; stmt->gen(out, fun); } } /* * Delete. */ Uc_assignment_statement::~Uc_assignment_statement ( ) { delete target; delete value; } /* * Generate code. */ void Uc_assignment_statement::gen ( vector& out, Uc_function * /* fun */ ) { value->gen_value(out); // Get value on stack. target->gen_assign(out); } /* * Generate code. */ void Uc_if_statement::gen ( vector& out, Uc_function *fun ) { // Gen JNE (or CMPS) past IF code. int jne_offset = expr->gen_jmp_if_false(out, 0); if (if_stmt) if_stmt->gen(out, fun); int jmp_past_else_offset = -1; // Where following JMP offset is. if (else_stmt) // JMP past ELSE code. { out.push_back((char) UC_JMP); jmp_past_else_offset = out.size(); Write2(out, 0); // Write place-holder for offset. } int if_end = out.size(); // Fixup JNE at start. Write2(out, jne_offset, if_end - (jne_offset + 2)); if (else_stmt) // Generate ELSE. { else_stmt->gen(out, fun); int else_end = out.size(); Write2(out, jmp_past_else_offset, else_end - (jmp_past_else_offset + 2)); } } /* * Delete. */ Uc_if_statement::~Uc_if_statement ( ) { delete expr; delete if_stmt; delete else_stmt; } /* * Delete. */ Uc_while_statement::~Uc_while_statement ( ) { delete expr; delete stmt; } /* * Generate code. */ void Uc_while_statement::gen ( vector& out, Uc_function *fun ) { int top = out.size(); // Get current position. expr->gen_value(out); // Generate expr. value. vector stmt_code; stmt_code.reserve(4000); fun->start_breakable(this); if (stmt) { fun->adjust_reloffset(out.size() + 3); stmt->gen(stmt_code, fun); // Generate statement's code. fun->adjust_reloffset(-out.size() - 3); } int stmtlen = stmt_code.size(); // Get distance back to top, including // a JNE and a JMP. long dist = stmtlen + (out.size() - top) + 3 + 3; // Generate JMP back to top. stmt_code.push_back((char) UC_JMP); Write2(stmt_code, -dist); stmtlen = stmt_code.size(); // Get total length. fun->end_breakable(this, stmt_code); out.push_back((char) UC_JNE); // Put cond. jmp. after test. Write2(out, stmtlen); // Skip around body if false. // out.append(stmt_code); // Append code to end. out.insert(out.end(), stmt_code.begin(), stmt_code.end()); } /* * Delete. */ Uc_arrayloop_statement::~Uc_arrayloop_statement ( ) { delete stmt; } /* * Finish up creation. */ void Uc_arrayloop_statement::finish ( Uc_function *fun ) { char buf[100]; if (!index) // Create vars. if not given. { sprintf(buf, "_%s_index", array->get_name()); index = fun->add_symbol(buf); } if (!array_size); { sprintf(buf, "_%s_size", array->get_name()); array_size = fun->add_symbol(buf); } } /* * Generate code. */ void Uc_arrayloop_statement::gen ( vector& out, Uc_function *fun ) { if (!stmt) return; // Nothing useful to do. out.push_back((char) UC_LOOP); // Start of loop. int top = out.size(); // This is where to jump back to. out.push_back((char) UC_LOOPTOP); Write2(out, index->get_offset());// Counter, total-count variables. Write2(out, array_size->get_offset()); Write2(out, var->get_offset()); // Loop variable, than array. Write2(out, array->get_offset()); // Still need to write offset to end. int testlen = out.size() + 2 - top; vector stmt_code; stmt_code.reserve(4000); fun->start_breakable(this); fun->adjust_reloffset(out.size() + 2); stmt->gen(stmt_code, fun); // Generate statement's code. fun->adjust_reloffset(-out.size() - 2); // Back to top includes JMP at end. int dist = testlen + stmt_code.size() + 3; stmt_code.push_back((char) UC_JMP); // Generate JMP back to top. Write2(stmt_code, -dist); int stmtlen = stmt_code.size(); // Get total length. Write2(out, stmtlen); // Finally, offset past loop stmt. fun->end_breakable(this, stmt_code); // Write out body. out.insert(out.end(), stmt_code.begin(), stmt_code.end()); } /* * Delete. */ Uc_return_statement::~Uc_return_statement ( ) { delete expr; } /* * Generate code. */ void Uc_return_statement::gen ( vector& out, Uc_function *fun ) { if (expr) // Returning something? { expr->gen_value(out); // Put value on stack. out.push_back((char) UC_SETR);// Pop into ret_value. out.push_back((char) UC_RTS); } else out.push_back((char) UC_RET); } /* * Generate code. */ void Uc_break_statement::gen ( vector& out, Uc_function *fun ) { // Store our location. fun->add_break(out.size()); //+++++if in an IF??? out.push_back((char) UC_JMP); Write2(out, 0); // To be filled in at end of loop. } void Uc_label_statement::gen ( vector& out, Uc_function *fun ) { // use reloffset to compensate for jumps to points in separately // generated blocks of code label->set_offset(out.size() + fun->get_reloffset()); // no code } void Uc_goto_statement::gen ( vector& out, Uc_function *fun ) { Uc_label *l = fun->search_label(label); if (l) { // use reloffset to compensate for jumps to points in separately // generated blocks of code l->add_reference(out.size() + fun->get_reloffset()); out.push_back((char) UC_JMP); Write2(out, 0); // will be filled in later } else { char buf[255]; snprintf(buf, 255, "Undeclared label: '%s'", label); error(buf); } } /* * Delete. */ Uc_converse_statement::~Uc_converse_statement ( ) { delete stmt; } /* * Generate code. */ void Uc_converse_statement::gen ( vector& out, Uc_function *fun ) { long top = out.size(); // Get current position. vector stmt_code; fun->start_breakable(this); if (stmt) { fun->adjust_reloffset(out.size() + 3); stmt->gen(stmt_code, fun); // Generate statement's code. fun->adjust_reloffset(-out.size() - 3); } int stmtlen = stmt_code.size(); // Get distance back to top, including // a CONVERSE & JMP back to top. long dist = stmtlen + 3 + 3; stmt_code.push_back((char) UC_JMP); // Generate JMP back to top. Write2(stmt_code, -dist); stmtlen = stmt_code.size(); // Get total length. fun->end_breakable(this, stmt_code); out.push_back((char) UC_CONVERSE); // Put CONVERSE at top. Write2(out, stmtlen); // Skip around body if no choices. // Write out body. out.insert(out.end(), stmt_code.begin(), stmt_code.end()); out.push_back((char) UC_CONVERSELOC); // Past CONVERSE loop. } /* * Generate a call to an intrinsic with 0 or 1 parameter. */ static void Call_intrinsic ( vector& out, Uc_function *fun, // Function we're in. Uc_intrinsic_symbol *intr, // What to call. Uc_expression *parm0 = 0 // Parm, or null. ) { // Create parms. list. Uc_array_expression *parms = new Uc_array_expression; if (parm0) parms->add(parm0); Uc_call_expression *fcall = new Uc_call_expression(intr, parms, fun); Uc_call_statement fstmt(fcall); fstmt.gen(out, fun); parms->clear(); // DON'T want to delete parm0. } /* * Generate code. */ void Uc_converse_case_statement::gen ( vector& out, // Contains all CASE statements up to // this point. Uc_function *fun ) { out.push_back((char) UC_PUSHS); // Gen. string comparison. Write2(out, string_offset); out.push_back((char) UC_CMPS); // Generate comparison. Write2(out, 1); // # strings on stack. int to_top_index = out.size(); // Remember this spot to fill in. Write2(out, 0); // Place holder. if (remove) // Remove answer? { Uc_string_expression str(string_offset); Call_intrinsic(out, fun, Uc_function::get_remove_answer(), &str); } if (statements) // Generate statement's code. statements->gen(out, fun); // Get distance back to top, including // this JMP // and the CONVERSE above 'out' code. long dist = out.size() + 3 + 3; // Generate JMP to start of conv. out.push_back((char) UC_JMP); Write2(out, -dist); // Fill in offset in CMPS. Write2(out, to_top_index, out.size() - (to_top_index + 2)); } /* * Delete. */ Uc_converse2_statement::~Uc_converse2_statement ( ) { delete answers; delete cases; } /* * Generate code. */ void Uc_converse2_statement::gen ( vector& out, Uc_function *fun ) { if (nest++ > 0) // Not the outermost? // Generate a 'push_answers()'. Call_intrinsic(out, fun, Uc_function::get_push_answers()); if (answers) // Add desired answers. Call_intrinsic(out, fun, Uc_function::get_add_answer(), answers); vector stmt_code; fun->start_breakable(this); if (cases) { fun->adjust_reloffset(out.size() + 3); cases->gen(stmt_code, fun); // Generate statement's code. fun->adjust_reloffset(-out.size() - 3); } int stmtlen = stmt_code.size(); // Get distance back to top, including // a CONVERSE & JMP back to top. long dist = stmtlen + 3 + 3; stmt_code.push_back((char) UC_JMP); // Generate JMP back to top. Write2(stmt_code, -dist); stmtlen = stmt_code.size(); // Get total length. fun->end_breakable(this, stmt_code); out.push_back((char) UC_CONVERSE); // Put CONVERSE at top. Write2(out, stmtlen); // Skip around body if no choices. // Write out body. out.insert(out.end(), stmt_code.begin(), stmt_code.end()); out.push_back((char) UC_CONVERSELOC); // Past CONVERSE loop. if (--nest > 0) // Not the outermost? // Generate a 'pop_answers()'. Call_intrinsic(out, fun, Uc_function::get_pop_answers()); } /* * Generate code. */ void Uc_message_statement::gen ( vector& out, Uc_function *fun ) { if (!msgs) return; const std::vector& exprs = msgs->get_exprs(); for (std::vector::const_iterator it = exprs.begin(); it != exprs.end(); ++it) { Uc_expression *msg = *it; // A known string? int offset = msg->get_string_offset(); if (offset >= 0) { out.push_back((char) UC_ADDSI); Write2(out, offset); } else { Uc_var_symbol *var = msg->need_var(out, fun); if (var) // Shouldn't fail. { out.push_back((char) UC_ADDSV); Write2(out, var->get_offset()); } } } } /* * Generate code. */ void Uc_say_statement::gen ( vector& out, Uc_function *fun ) { // Add the messages. Uc_message_statement::gen(out, fun); out.push_back((char) UC_SAY); // Show on screen. } /* * Create. */ Uc_call_statement::Uc_call_statement ( Uc_call_expression *f ) : function_call(f) { if (function_call) function_call->set_no_return(); } /* * Delete. */ Uc_call_statement::~Uc_call_statement ( ) { delete function_call; } /* * Generate code. */ void Uc_call_statement::gen ( vector& out, Uc_function *fun ) { function_call->gen_value(out); // (We set 'no_return'.) } exult-1.2/usecode/compiler/ucexpr.cc0000644000175000001440000002252007732251221013252 /** ** Ucexpr.cc - Expressions for Usecode compiler. ** ** Written: 1/0/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "ucexpr.h" #include "ucsym.h" #include "utils.h" #include "opcodes.h" #include "ucfun.h" /* * Default. Just push the one value. * * Output: # pushed */ int Uc_expression::gen_values ( vector& out ) { gen_value(out); // Gen. result on stack. return 1; } /* * Default jmp-if-false generation. * * Output: offset where offset is stored. */ int Uc_expression::gen_jmp_if_false ( vector& out, int offset // Offset to jmp (relative). ) { gen_value(out); // Gen. result on stack. out.push_back((char) UC_JNE); // Pop and jmp if false. Write2(out, offset); return out.size() - 2; } /* * Default assignment generation. */ void Uc_expression::gen_assign ( vector& out ) { error("Can't assign to this expression"); } /* * Need a variable whose value is this expression. */ Uc_var_symbol *Uc_expression::need_var ( vector& out, Uc_function *fun ) { static int cnt = 0; char buf[50]; sprintf(buf, "_tmpval_%d", cnt++); // Create a 'tmp' variable. Uc_var_symbol *var = fun->add_symbol(buf); if (!var) return 0; // Shouldn't happen. Err. reported. gen_value(out); // Want to assign this value to it. var->gen_assign(out); return var; } /* * Evaluate constant. * * Output: true if successful, with result returned in 'val'. */ bool Uc_expression::eval_const ( int& val // Value returned here. ) { val = 0; error("Integer constant expected."); return false; } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_var_expression::gen_value ( vector& out ) { char buf[150]; if (!var->gen_value(out)) { sprintf(buf, "Can't use value of '%s'", var->get_name()); error(buf); } } /* * Generate assignment to this variable. */ void Uc_var_expression::gen_assign ( vector& out ) { char buf[150]; if (!var->gen_assign(out)) { sprintf(buf, "Can't assign to '%s'", var->get_name()); error(buf); } } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_arrayelem_expression::gen_value ( vector& out ) { if (!index || !array) return; index->gen_value(out); // Want index on stack. out.push_back((char) UC_AIDX); // Opcode, var #. Write2(out, array->get_offset()); } /* * Generate assignment to this variable. */ void Uc_arrayelem_expression::gen_assign ( vector& out ) { if (!index || !array) return; index->gen_value(out); // Want index on stack. out.push_back((char) UC_POPARR); // Opcode, var #. Write2(out, array->get_offset()); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_flag_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHF); // Opcode, flag #. Write2(out, index); } /* * Generate assignment to this variable. */ void Uc_flag_expression::gen_assign ( vector& out ) { out.push_back((char) UC_POPF); Write2(out, index); } /* * Get offset in function's text_data. * * Output: Offset. */ int Uc_var_expression::get_string_offset ( ) { return var->get_string_offset(); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_binary_expression::gen_value ( vector& out ) { left->gen_value(out); // First the left. right->gen_value(out); // Then the right. out.push_back((char) opcode); } /* * Evaluate constant. * * Output: true if successful, with result returned in 'val'. */ bool Uc_binary_expression::eval_const ( int& val // Value returned here. ) { int val1, val2; // Get each side. if (!left->eval_const(val1) || !right->eval_const(val2)) return false; switch (opcode) { case UC_ADD: val = val1 + val2; return true; case UC_SUB: val = val1 - val2; return true; case UC_MUL: val = val1*val2; return true; case UC_DIV: if (!val2) { error("Division by 0"); return false; } val = val1/val2; return true; } val = 0; error("This operation not supported for integer constants"); return false; } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_unary_expression::gen_value ( vector& out ) { operand->gen_value(out); out.push_back((char) opcode); } /* * Can't use this expression just anywhere. */ void Uc_response_expression::gen_value ( vector& out ) { error("Must use UcResponse in 'if (UcResponse == ...)'"); } /* * Jmp-if-false generation for getting conversation response & comparing * to a string or strings. * * Output: offset where offset is stored. */ int Uc_response_expression::gen_jmp_if_false ( vector& out, int offset // Offset to jmp (relative). ) { // Push string(s) on stack. int cnt = operand->gen_values(out); out.push_back((char) UC_CMPS); Write2(out, cnt); // # strings on stack. Write2(out, offset); // Offset to jmp if false. return out.size() - 2; } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_int_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHI); Write2(out, value); } /* * Evaluate constant. * * Output: true if successful, with result returned in 'val'. */ bool Uc_int_expression::eval_const ( int& val // Value returned here. ) { val = value; return true; } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_bool_expression::gen_value ( vector& out ) { if (tf) out.push_back((char) UC_PUSHTRUE); else out.push_back((char) UC_PUSHFALSE); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_event_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHEVENTID); } /* * Generate assignment to this variable. */ void Uc_event_expression::gen_assign ( vector& out ) { out.push_back((char) UC_POPEVENTID); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_item_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHITEMREF); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_string_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHS); Write2(out, offset); } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_string_prefix_expression::gen_value ( vector& out ) { out.push_back((char) UC_PUSHS); Write2(out, get_string_offset()); } /* * Get offset in function's text_data. * * Output: Offset. */ int Uc_string_prefix_expression::get_string_offset ( ) { if (offset < 0) // First time? // Look up & print errors. offset = fun->find_string_prefix(*this, prefix.c_str()); return offset; } /* * Delete a list of expressions. */ Uc_array_expression::~Uc_array_expression ( ) { for (std::vector::iterator it = exprs.begin(); it != exprs.end(); it++) delete (*it); } /* * Concatenate another expression, or its values if an array, onto this. * If the expression is an array, it's deleted after its elements are * taken. */ void Uc_array_expression::concat ( Uc_expression *e ) { Uc_array_expression *arr = dynamic_cast (e); if (!arr) add(e); // Singleton? Just add it. else { for (std::vector::iterator it = arr->exprs.begin(); it != arr->exprs.end(); it++) add(*it); arr->exprs.clear(); // Don't want to delete elements. delete arr; // But this array is history. } } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_array_expression::gen_value ( vector& out ) { int actual = Uc_array_expression::gen_values(out); out.push_back((char) UC_ARRC); Write2(out, actual); } /* * Push all values onto the stack. * * Output: # pushed */ int Uc_array_expression::gen_values ( vector& out ) { int actual = 0; // (Just to be safe.) // Push backwards, so #0 pops first. for (std::vector::reverse_iterator it = exprs.rbegin(); it != exprs.rend(); it++) { Uc_expression *expr = *it; if (expr) { actual++; expr->gen_value(out); } } return actual; } /* * Generate code to evaluate expression and leave result on stack. */ void Uc_call_expression::gen_value ( vector& out ) { if (!sym) return; // Already failed once. if (!sym->gen_call(out, function, original, itemref, parms, return_value)) { char buf[150]; sprintf(buf, "'%s' isn't a function or intrinsic", sym->get_name()); sym = 0; // Avoid repeating error if in loop. error(buf); } } exult-1.2/usecode/compiler/ucexpr.h0000644000175000001440000002026307732251221013116 /** ** Ucexpr.h - Expressions for Usecode compiler. ** ** Written: 1/0/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCEXPR #define INCL_UCEXPR 1 #include #include #include "ucloc.h" using std::vector; class Uc_symbol; class Uc_var_symbol; class Uc_function; /* * Base class for expressions. */ class Uc_expression : public Uc_location { public: // Use current location. Uc_expression() : Uc_location() { } virtual ~Uc_expression() { } // Gen. code to put result on stack. virtual void gen_value(vector& out) = 0; // Gen code to push value(s). virtual int gen_values(vector& out); // Gen. code to jmp if this is false. virtual int gen_jmp_if_false(vector& out, int offset); // Gen. to assign from stack. virtual void gen_assign(vector& out); virtual int get_string_offset() // Get offset in text_data. { return -1; } // Get/create var == this. virtual Uc_var_symbol *need_var(vector& out, Uc_function *fun); // Evaluate constant. virtual bool eval_const(int& val); }; /* * A variable. */ class Uc_var_expression : public Uc_expression { Uc_var_symbol *var; public: // Use current location. Uc_var_expression(Uc_var_symbol *v) : var(v) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen. to assign from stack. virtual void gen_assign(vector& out); virtual int get_string_offset();// Get offset in text_data. virtual Uc_var_symbol *need_var(vector& , Uc_function *) { return var; } }; /* * An array element. */ class Uc_arrayelem_expression : public Uc_expression { Uc_var_symbol *array; Uc_expression *index; public: Uc_arrayelem_expression(Uc_var_symbol *a, Uc_expression *i) : array(a), index(i) { } ~Uc_arrayelem_expression() { delete index; } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen. to assign from stack. virtual void gen_assign(vector& out); }; /* * Global flag. */ class Uc_flag_expression : public Uc_expression { int index; public: Uc_flag_expression(int i) : index(i) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen. to assign from stack. virtual void gen_assign(vector& out); }; /* * Binary expressions. */ class Uc_binary_expression : public Uc_expression { int opcode; // Should be the UC_ Uc_expression *left, *right; // Operands to add, sub, etc. public: Uc_binary_expression(int o, Uc_expression *l, Uc_expression *r) : opcode(o), left(l), right(r) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Evaluate constant. virtual bool eval_const(int& val); }; /* * Unary expressions. */ class Uc_unary_expression : public Uc_expression { int opcode; // Should be the UC_ Uc_expression *operand; public: Uc_unary_expression(int o, Uc_expression *r) : opcode(o), operand(r) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); }; /* * Compare user conversation response to a given string (or list of * strings. */ class Uc_response_expression : public Uc_expression { Uc_expression *operand; public: Uc_response_expression(Uc_expression *r) : operand(r) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen. code to jmp if this is false. virtual int gen_jmp_if_false(vector& out, int offset); }; /* * Integer value. */ class Uc_int_expression : public Uc_expression { int value; public: Uc_int_expression(int v) : value(v) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Evaluate constant. virtual bool eval_const(int& val); }; /* * Boolean value. */ class Uc_bool_expression : public Uc_expression { bool tf; public: Uc_bool_expression(bool t) : tf(t) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); }; /* * Eventid (a special int variable passed to each function): */ class Uc_event_expression : public Uc_expression { public: Uc_event_expression() { } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen. to assign from stack. virtual void gen_assign(vector& out); }; /* * Item (a special ptr. variable passed to each function): */ class Uc_item_expression : public Uc_expression { public: Uc_item_expression() { } // Gen. code to put result on stack. virtual void gen_value(vector& out); }; /* * String value. */ class Uc_string_expression : public Uc_expression { int offset; // Offset in function's data area. public: Uc_string_expression(int o) : offset(o) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); virtual int get_string_offset() // Get offset in text_data. { return offset; } }; /* * String value given by a prefix (i.e. "Jo"* for "Job"). */ class Uc_string_prefix_expression : public Uc_expression { Uc_function *fun; // Needed to look up prefix. std::string prefix; // What to look up. int offset; // Offset in function's data area. // This is -1 if not found yet. public: Uc_string_prefix_expression(Uc_function *f, char *pre) : fun(f), prefix(pre), offset(-1) { } // Gen. code to put result on stack. virtual void gen_value(vector& out); virtual int get_string_offset();// Get offset in text_data. }; /* * A concatenation, which generates an array: */ class Uc_array_expression : public Uc_expression { std::vector exprs; public: Uc_array_expression() { } Uc_array_expression(Uc_expression *e0) { add(e0); } // Create with 1st expression. Uc_array_expression(Uc_expression *e0, Uc_expression *e1) { add(e0); add(e1); } ~Uc_array_expression(); void add(Uc_expression *e) // Append an expression. { exprs.push_back(e); } void clear() // Remove, but DON'T delete, elems. { exprs.clear(); } void concat(Uc_expression *e); // Concat e's elements onto this. const std::vector& get_exprs() { return exprs; } // Gen. code to put result on stack. virtual void gen_value(vector& out); // Gen code to push value(s). virtual int gen_values(vector& out); }; /* * A function or intrinsic call. */ class Uc_call_expression : public Uc_expression { Uc_symbol *sym; // Function or intrinsic. bool original; // Call original function instead of // the one from 'patch'. Uc_expression *itemref; // Non-null for CALLE. Uc_array_expression *parms; Uc_function *function; // May need function this is in. bool return_value; // True for a function (to return // its value). public: Uc_call_expression(Uc_symbol *s, Uc_array_expression *prms, Uc_function *fun, bool orig = false) : sym(s), itemref(0), parms(prms), function(fun), original(orig), return_value(true) { } ~Uc_call_expression() { delete parms; delete itemref; } void set_itemref(Uc_expression *iexpr) { itemref = iexpr; } void set_no_return() { return_value = false; } // Gen. code to put result on stack. virtual void gen_value(vector& out); }; /* * Write a 2-byte value to the end/position of a character stream. */ inline void Write2(vector& out, unsigned short val) { out.push_back((char) (val&0xff)); out.push_back((char) ((val>>8)&0xff)); } inline void Write2(vector& out, int pos, unsigned short val) { out[pos] = (char) (val&0xff); out[pos + 1] = (char) ((val>>8)&0xff); } #endif exult-1.2/usecode/compiler/ucfun.cc0000644000175000001440000002615307676104167013107 /** ** Ucfun.cc - Usecode compiler function. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "ucfun.h" #include "ucstmt.h" #include "utils.h" #include "opcodes.h" #include "ucexpr.h" /* Needed only for Write2(). */ using std::strlen; using std::memcpy; Uc_scope Uc_function::globals(0); // Stores intrinic symbols. vector Uc_function::intrinsics; int Uc_function::num_global_statics = 0; int Uc_function::add_answer = -1, Uc_function::remove_answer = -1, Uc_function::push_answers = -1, Uc_function::pop_answers = -1, Uc_function::show_face = -1, Uc_function::remove_face = -1; /* * Create function, and add to global symbol table. */ Uc_function::Uc_function ( Uc_function_symbol *p ) : top(0), proto(p), cur_scope(&top), num_parms(0), num_locals(0), num_statics(0), text_data(0), text_data_size(0), statement(0), reloffset(0) { char *nm = (char *) proto->get_name(); add_global_function_symbol(proto);// Add prototype to globals. #if 0 if (!globals.search(nm)) globals.add(proto); else { char buf[100]; sprintf(buf, "Name '%s' already defined", nm); Uc_location::yyerror(buf); } #endif const std::vector& parms = proto->get_parms(); for (std::vector::const_iterator it = parms.begin(); it != parms.end(); it++) add_symbol(*it); num_parms = num_locals; // Set counts. num_locals = 0; } /* * Delete. */ Uc_function::~Uc_function ( ) { delete statement; delete proto; std::map::iterator iter; for (iter = labels.begin(); iter != labels.end(); ++iter) delete iter->second; } /* * Check for a duplicate symbol and print an error. * * Output: true if dup., with error printed. */ bool Uc_function::is_dup ( Uc_scope *scope, char *nm ) { Uc_symbol *sym = scope->search(nm); if (sym) // Already in scope? { char msg[180]; sprintf(msg, "Symbol '%s' already declared", nm); Uc_location::yyerror(msg); return true; } return false; } /* * Find a label in this function * * Output: label, or 0 if not found */ Uc_label *Uc_function::search_label(char *nm) { std::map::iterator iter; iter = labels.find(nm); if (iter != labels.end()) return iter->second; return 0; } /* * Add a new variable to the current scope. * * Output: New sym, or 0 if already declared. */ Uc_var_symbol *Uc_function::add_symbol ( char *nm ) { if (is_dup(cur_scope, nm)) return 0; // Create & assign slot. Uc_var_symbol *var = new Uc_var_symbol(nm, num_parms + num_locals++); cur_scope->add(var); return var; } /* * Add a new static variable to the current scope. */ void Uc_function::add_static ( char *nm ) { if (is_dup(cur_scope, nm)) return; // Create & assign slot. Uc_var_symbol *var = new Uc_static_var_symbol(nm, num_statics++); cur_scope->add(var); } /* * Add a new string constant to the current scope. */ Uc_symbol *Uc_function::add_string_symbol ( char *nm, char *text ) { if (is_dup(cur_scope, nm)) return 0; // Create & assign slot. Uc_symbol *sym = new Uc_string_symbol(nm, add_string(text)); cur_scope->add(sym); return sym; } /* * Add a new integer constant variable to the current scope. * * Output: New sym, or 0 if already declared. */ Uc_symbol *Uc_function::add_int_const_symbol ( char *nm, int value ) { if (is_dup(cur_scope, nm)) return 0; // Create & assign slot. Uc_const_int_symbol *var = new Uc_const_int_symbol(nm, value); cur_scope->add(var); return var; } /* * Add a new integer constant variable to the global scope. * * Output: New sym, or 0 if already declared. */ Uc_symbol *Uc_function::add_global_int_const_symbol ( char *nm, int value ) { if (is_dup(&globals, nm)) return 0; // Create & assign slot. Uc_const_int_symbol *var = new Uc_const_int_symbol(nm, value); globals.add(var); return var; } /* * Add a global static. */ void Uc_function::add_global_static ( char *nm ) { if (is_dup(&globals, nm)) return; num_global_statics++; // These start with 1. // Create & assign slot. Uc_var_symbol *var = new Uc_static_var_symbol(nm, -num_global_statics); globals.add(var); } /* * Add a string to the data area. * * Output: offset of string. */ int Uc_function::add_string ( char *text ) { // Search for an existing string. std::map::const_iterator exist = text_map.find(text); if (exist != text_map.end()) return (*exist).second; int offset = text_data_size; // This is where it will go. int textlen = strlen(text) + 1; // Got to include ending null. char *new_text_data = new char[text_data_size + textlen]; if (text_data_size) // Copy over old. memcpy(new_text_data, text_data, text_data_size); // Append new. memcpy(new_text_data + text_data_size, text, textlen); delete text_data; text_data = new_text_data; text_data_size += textlen; text_map[text] = offset; // Store map entry. return offset; } /* * Find the (unique) string for a given prefix. * * Output: Offset of string. Error printed if more than one. * 0 if not found, with error printed. */ int Uc_function::find_string_prefix ( Uc_location& loc, // For printing errors. const char *text ) { int len = strlen(text); // Find 1st entry >= text. std::map::const_iterator exist = text_map.lower_bound(text); if (exist == text_map.end() || strncmp(text, (*exist).first.c_str(), len) != 0) { char *buf = new char[len + 100]; sprintf(buf, "Prefix '%s' matches no string in this function", text); loc.error(buf); delete buf; return 0; } std::map::const_iterator next = exist; ++next; if (next != text_map.end() && strncmp(text, (*next).first.c_str(), len) == 0) { char *buf = new char[len + 100]; sprintf(buf, "Prefix '%s' matches more than one string", text); loc.error(buf); delete buf; } return (*exist).second; // Return offset. } /* * Start a loop. */ void Uc_function::start_breakable ( Uc_statement *s // Loop. ) { breakables.push_back(s); breaks.push_back(-1); // Set marker in 'break' list. } /* * Fix up stuff when a loop's body has been generated. */ void Uc_function::end_breakable ( Uc_statement *s, // Loop. For verification. vector& stmt_code ) { // Just make sure things are right. assert(!breakables.empty() && s == breakables.back()); breakables.pop_back(); int stmtlen = stmt_code.size(); // Fix all the 'break' statements, // going backwards. while (!breaks.empty() && breaks.back() >= 0) { // Get offset within loop. int break_offset = breaks.back(); breaks.pop_back(); // Remove from end of list. assert(break_offset < stmtlen - 2); // Store offset. Write2(stmt_code, break_offset + 1, stmtlen - (break_offset + 3)); } assert(!breaks.empty() && breaks.back() == -1); breaks.pop_back(); // Remove marker (-1). } /* * Store a 'break' statement's offset so it can be filled in at the end * of the current loop. */ void Uc_function::add_break ( int op_offset // Offset in loop's code of JMP. ) { assert(op_offset >= 0); if (breakables.empty()) // Not in a loop? Uc_location::yyerror("'break' is not valid here"); else breaks.push_back(op_offset); } /* * Lookup/add a link to an external function. * * Output: Link offset. */ int Uc_function::link ( Uc_function_symbol *fun ) { for (std::vector::const_iterator it = links.begin(); it != links.end(); it++) if (*it == fun) // Found it? Return offset. return (it - links.begin()); int offset = links.size(); // Going to add it. links.push_back(fun); return offset; } void Uc_function::link_labels(vector& code) { std::map::iterator iter; for (iter = labels.begin(); iter != labels.end(); ++iter) { Uc_label *label = iter->second; if (label->is_valid()) { int target = label->get_offset(); std::vector& references = label->get_references(); std::vector::iterator i; for (i = references.begin(); i != references.end(); ++i) { int offset = (*i) + 1; Write2(code, offset, target - (offset + 2)); } } } } /* * Generate Usecode. */ void Uc_function::gen ( std::ostream& out ) { // Start with function #. Write2(out, proto->get_usecode_num()); vector code; // Generate code here first. code.reserve(30000); if (statement) statement->gen(code, this); code.push_back((char) UC_RET); // Always end with a RET. link_labels(code); int codelen = code.size(); // Get its length. int num_links = links.size(); // Total: text_data_size + data + // #args + #locals + #links + links + // codelen. int totallen = 2 + text_data_size + 2 + 2 + 2 + 2*num_links + codelen; Write2(out, totallen); Write2(out, text_data_size); // Now data. out.write(text_data, text_data_size); Write2(out, num_parms); // Counts. Write2(out, num_locals); Write2(out, num_links); // Write external links. for (std::vector::const_iterator it = links.begin(); it != links.end(); it++) Write2(out, (*it)->get_usecode_num()); char *ucstr = &code[0]; // Finally, the code itself. out.write(ucstr, codelen); out.flush(); } #ifndef __STRING #if defined __STDC__ && __STDC__ #define __STRING(x) #x #else #define __STRING(x) "x" #endif #endif /* * Tables of usecode intrinsics: */ #define USECODE_INTRINSIC_PTR(NAME) __STRING(UI_##NAME) const char *bg_intrinsic_table[] = { #include "../bgintrinsics.h" }; const char *si_intrinsic_table[] = { #include "../siintrinsics.h" }; /* * Add one of the intrinsic tables to the 'intrinsics' scope. */ void Uc_function::set_intrinsics ( Intrinsic_type ty ) { int cnt; const char **table; if (ty == bg) { table = bg_intrinsic_table; cnt = sizeof(bg_intrinsic_table)/sizeof(bg_intrinsic_table[0]); add_answer = 5; remove_answer = 6; push_answers = 7; pop_answers = 8; } else { table = si_intrinsic_table; cnt = sizeof(si_intrinsic_table)/sizeof(si_intrinsic_table[0]); add_answer = 0xc; remove_answer = 0xd; push_answers = 0xe; pop_answers = 0xf; } show_face = 3; remove_face = 4; intrinsics.resize(cnt); for (int i = 0; i < cnt; i++) { char *nm = (char *)table[i]; Uc_intrinsic_symbol *sym = new Uc_intrinsic_symbol(nm, i); intrinsics[i] = sym; // Store in indexed list. if (!globals.search(nm)) // ++++Later, get num parms. globals.add(sym); } } exult-1.2/usecode/compiler/ucfun.h0000644000175000001440000001152207633037511012732 /** ** Ucfun.h - Usecode compiler function. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCFUN #define INCL_UCFUN #include "ucsym.h" #include "uclabel.h" class Uc_location; class Uc_statement; #ifndef ALPHA_LINUX_CXX # include #endif /* * This represents a usecode function: */ class Uc_function { static Uc_scope globals; // For finding intrinsics, funs. // Intrinsics, indexed by number: static vector intrinsics; // Some intrinsic numbers: static int add_answer, remove_answer, push_answers, pop_answers, show_face, remove_face; static int num_global_statics; Uc_scope top; // Top-level scope. Uc_function_symbol *proto; // Function declaration. Uc_scope *cur_scope; // Current scope. int num_parms; // # parameters. int num_locals; // Counts locals. int num_statics; // Counts local statics. // Stack of loops (where 'break' can // be used. vector breakables; vector breaks; // Offsets of generated breaks in // current loop, with loops separated // by -1's. // Links to called functions: std::vector links; std::map labels; char *text_data; // All strings. int text_data_size; // Map string to its offset. std::map text_map; Uc_statement *statement; // Statement(s) in function. int reloffset; // relative offset of the code being generated public: Uc_function(Uc_function_symbol *p); ~Uc_function(); enum Intrinsic_type { bg, // Black gate. si // Serpent isle. }; static void set_intrinsics(Intrinsic_type ty); void set_statement(Uc_statement *s) { statement = s; } void adjust_reloffset(int diff) { reloffset += diff; } int get_reloffset() const { return reloffset; } void push_scope() // Start a new scope. { cur_scope = cur_scope->add_scope(); } void pop_scope() // End scope. { cur_scope = cur_scope->get_parent(); } Uc_symbol *search(char *nm) // Search current scope. { return cur_scope->search(nm); } Uc_symbol *search_up(char *nm) { Uc_symbol *sym = cur_scope->search_up(nm); return (sym ? sym : globals.search(nm)); } static Uc_intrinsic_symbol *get_intrinsic(int i) { return (i >= 0 && i < intrinsics.size())? intrinsics[i] : 0;} static Uc_intrinsic_symbol *get_add_answer() { return get_intrinsic(add_answer); } static Uc_intrinsic_symbol *get_remove_answer() { return get_intrinsic(remove_answer); } static Uc_intrinsic_symbol *get_push_answers() { return get_intrinsic(push_answers); } static Uc_intrinsic_symbol *get_pop_answers() { return get_intrinsic(pop_answers); } static Uc_intrinsic_symbol *get_show_face() { return get_intrinsic(show_face); } static Uc_intrinsic_symbol *get_remove_face() { return get_intrinsic(remove_face); } // Already declared? static bool is_dup(Uc_scope *scope, char *nm); Uc_var_symbol *add_symbol(char *nm);// Add var. to current scope. void add_static(char *nm); // Add static var. to current scope. int add_function_symbol(Uc_function_symbol *fun) { return cur_scope->add_function_symbol(fun); } static int add_global_function_symbol(Uc_function_symbol *fun) { return globals.add_function_symbol(fun); } // Add string constant. Uc_symbol *add_string_symbol(char *nm, char *text); // Add int constant. Uc_symbol *add_int_const_symbol(char *nm, int value); static Uc_symbol *add_global_int_const_symbol(char *nm, int val); static void add_global_static(char *nm); int add_string(char *text); int find_string_prefix(Uc_location& loc, const char *text); // Start/end loop. void add_label(Uc_label* l) { labels[l->get_name()] = l; } Uc_label *search_label(char *nm); void start_breakable(Uc_statement *s); void end_breakable(Uc_statement *s, vector& stmt_code); // Store 'break' location. void add_break(int op_offset); // DANGER: Offset is filled in when // end_breakable() is called, so the // string this is in better not have // been deleted!!! // Link external function. int link(Uc_function_symbol *fun); void link_labels(std::vector& code); void gen(std::ostream& out); // Generate Usecode. }; #endif exult-1.2/usecode/compiler/ucloc.h0000644000175000001440000000302607266541313012721 /** ** Ucloc.h - Source location. ** ** Written: 1/0/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCLOC #define INCL_UCLOC 1 #include /* * Location in source code. */ class Uc_location { static std::vector source_names;// All filenames. static char *cur_source; // Source filename. static int cur_line; // Line #. static int num_errors; // Total #. char *source; int line; public: Uc_location() // Use current location. : source(cur_source), line(cur_line) { } static void set_cur(const char *s, int l); static void increment_cur_line() { cur_line++; } const int get_line() { return line; } const char *get_source() { return source; } void error(char *s); // Print error. static void yyerror(char *s); // Print error at cur. location. static int get_num_errors() { return num_errors; } }; #endif exult-1.2/usecode/compiler/Makefile.am0000644000175000001440000000100107647741322013473 INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/.. -I$(srcdir)/../../files -I$(srcdir)/../.. \ $(INCDIRS) $(DEBUG_FLAGS) $(CPPFLAGS) AM_YFLAGS = -d # Want ucparse.h. ucc_SOURCES = ucparse.yy uclex.ll ucmain.cc \ opcodes.h \ ucexpr.cc \ ucexpr.h \ ucfun.cc \ ucfun.h \ uclabel.h \ ucloc.cc \ ucloc.h \ ucparse.h \ ucstmt.cc \ ucstmt.h \ ucsym.cc \ ucsym.h if BUILD_COMPILER bin_PROGRAMS = ucc endif ucc_LDADD = \ $(SYSLIBS) CLEANFILES = *~ MAINTAINERCLEANFILES = uclex.cc ucparse.cc exult-1.2/usecode/compiler/Makefile.in0000644000175000001440000003033210061527061013477 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../../headers -I$(srcdir)/.. -I$(srcdir)/../../files -I$(srcdir)/../.. \ $(INCDIRS) $(DEBUG_FLAGS) $(CPPFLAGS) AM_YFLAGS = -d # Want ucparse.h. ucc_SOURCES = ucparse.yy uclex.ll ucmain.cc \ opcodes.h \ ucexpr.cc \ ucexpr.h \ ucfun.cc \ ucfun.h \ uclabel.h \ ucloc.cc \ ucloc.h \ ucparse.h \ ucstmt.cc \ ucstmt.h \ ucsym.cc \ ucsym.h @BUILD_COMPILER_TRUE@bin_PROGRAMS = ucc ucc_LDADD = \ $(SYSLIBS) CLEANFILES = *~ MAINTAINERCLEANFILES = uclex.cc ucparse.cc subdir = usecode/compiler mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @BUILD_COMPILER_TRUE@bin_PROGRAMS = ucc$(EXEEXT) @BUILD_COMPILER_FALSE@bin_PROGRAMS = PROGRAMS = $(bin_PROGRAMS) am_ucc_OBJECTS = ucparse.$(OBJEXT) uclex.$(OBJEXT) ucmain.$(OBJEXT) \ ucexpr.$(OBJEXT) ucfun.$(OBJEXT) ucloc.$(OBJEXT) \ ucstmt.$(OBJEXT) ucsym.$(OBJEXT) ucc_OBJECTS = $(am_ucc_OBJECTS) ucc_DEPENDENCIES = ucc_LDFLAGS = DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/ucexpr.Po $(DEPDIR)/ucfun.Po \ @AMDEP_TRUE@ $(DEPDIR)/uclex.Po $(DEPDIR)/ucloc.Po \ @AMDEP_TRUE@ $(DEPDIR)/ucmain.Po $(DEPDIR)/ucparse.Po \ @AMDEP_TRUE@ $(DEPDIR)/ucstmt.Po $(DEPDIR)/ucsym.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) LTLEXCOMPILE = $(LIBTOOL) --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS) YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) LTYACCCOMPILE = $(LIBTOOL) --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS) CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(ucc_SOURCES) DIST_COMMON = Makefile.am Makefile.in uclex.cc ucparse.cc ucparse.h SOURCES = $(ucc_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .ll .lo .o .obj .yy mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/compiler/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) ucparse.h: ucparse.cc ucc$(EXEEXT): $(ucc_OBJECTS) $(ucc_DEPENDENCIES) @rm -f ucc$(EXEEXT) $(CXXLINK) $(ucc_LDFLAGS) $(ucc_OBJECTS) $(ucc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucexpr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucfun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/uclex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucmain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucstmt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucsym.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LEXLIB = @LEXLIB@ .ll.cc: $(LEXCOMPILE) $< && mv $(LEX_OUTPUT_ROOT).c $@ .yy.cc: $(YACCCOMPILE) $< && mv y.tab.c $@ if test -f y.tab.h; then \ if cmp -s y.tab.h $*.h; then \ rm -f y.tab.h; \ else \ mv y.tab.h $*.h; \ fi; \ fi uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: $(mkinstalldirs) $(DESTDIR)$(bindir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "ucparse.h$(MAINTAINERCLEANFILES)" || rm -f ucparse.h $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-binPROGRAMS uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool distclean distclean-compile \ distclean-depend distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am info info-am install \ install-am install-binPROGRAMS install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/compiler/ucsym.h0000644000175000001440000001420207732251221012744 /** ** Ucsym.h - Usecode compiler symbol table. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCSYM #define INCL_UCSYM #ifdef HAVE_CONFIG_H # include #endif #include #include #include using std::vector; class Uc_array_expression; class Uc_expression; class Uc_function; /* * For comparing names: */ class String_compare { public: bool operator()(char * const &x, char * const &y) const; }; /* * A formal parameter or local symbol within a function. */ class Uc_symbol { protected: std::string name; // This will be the key. public: friend class Uc_scope; Uc_symbol(char *nm) : name(nm) { } const char *get_name() { return name.c_str(); } // Gen. code to put result on stack. virtual int gen_value(vector& out); // Gen. to assign from stack. virtual int gen_assign(vector& out); // Generate function/procedure call. virtual int gen_call(vector& out, Uc_function *fun, bool orig, Uc_expression *item, Uc_array_expression *parms, bool retvalue); virtual int get_string_offset() // Get offset in text_data. { return -1; } // Return var/int expression. virtual Uc_expression *create_expression(); }; /* * A variable (untyped) that can be assigned to. */ class Uc_var_symbol : public Uc_symbol { protected: int offset; // Within function. Locals follow // formal parameters. public: friend class Uc_scope; Uc_var_symbol(char *nm, int off) : Uc_symbol(nm), offset(off) { } int get_offset() { return offset; } // Gen. code to put result on stack. virtual int gen_value(vector& out); // Gen. to assign from stack. virtual int gen_assign(vector& out); // Return var/int expression. virtual Uc_expression *create_expression(); }; /* * A static (persistent) variable. */ class Uc_static_var_symbol : public Uc_var_symbol { public: Uc_static_var_symbol(char *nm, int off) : Uc_var_symbol(nm, offset) { } // Gen. code to put result on stack. virtual int gen_value(vector& out); // Gen. to assign from stack. virtual int gen_assign(vector& out); }; /* * A constant integer variable. */ class Uc_const_int_symbol : public Uc_symbol { int value; public: Uc_const_int_symbol(char *nm, int v) : Uc_symbol(nm), value(v) { } // Gen. code to put result on stack. virtual int gen_value(vector& out); // Return var/int expression. virtual Uc_expression *create_expression(); int get_value() const { return value; } }; /* * A (constant) string. The offset is within the usecode function's * text_data field. */ class Uc_string_symbol : public Uc_symbol { int offset; // In function's text_data. public: Uc_string_symbol(char *nm, int off) : Uc_symbol(nm), offset(off) { } // Gen. code to put result on stack. virtual int gen_value(vector& out); virtual int get_string_offset() // Get offset in text_data. { return offset; } // Return var/int expression. virtual Uc_expression *create_expression(); }; /* * An intrinsic symbol: */ class Uc_intrinsic_symbol : public Uc_symbol { int intrinsic_num; // Intrinsic #. int num_parms; // # parms. +++++Not used/set yet. public: Uc_intrinsic_symbol(char *nm, int n) : Uc_symbol(nm), intrinsic_num(n), num_parms(0) { } int get_intrinsic_num() { return intrinsic_num; } int get_num_parms() // ++++Not valid yet. { return num_parms; } // Generate function/procedure call. virtual int gen_call(vector& out, Uc_function *fun, bool orig, Uc_expression *item, Uc_array_expression *parms, bool retvalue); }; /* * A function-prototype symbol: */ class Uc_function_symbol : public Uc_symbol { static int last_num; // Last 'usecode_num', so we can // assign automatically. public: // Keep track of #'s used. typedef std::map Sym_nums; private: static Sym_nums nums_used; // Note: offset = Usecode fun. #. std::vector parms; // Parameters. int usecode_num; // Usecode function #. public: Uc_function_symbol(char *nm, int num, std::vector& p); const std::vector& get_parms() { return parms; } int get_usecode_num() { return usecode_num; } int get_num_parms() { return parms.size(); } // Generate function/procedure call. virtual int gen_call(vector& out, Uc_function *fun, bool orig, Uc_expression *item, Uc_array_expression *parms, bool retvalue); }; /* * A 'scope' in the symbol table: */ class Uc_scope { Uc_scope *parent; // ->parent. // For finding syms. by name. typedef std::map Sym_map; Sym_map symbols; std::vector scopes; // Scopes within. public: Uc_scope(Uc_scope *p) : parent(p) { } ~Uc_scope(); Uc_scope *get_parent() { return parent; } Uc_symbol *search(const char *nm) // Look in this scope. { char *nm1 = (char *) nm; Sym_map::const_iterator it = symbols.find(nm1); if (it == symbols.end()) return 0; else return (*it).second; } // Search upwards through scopes. Uc_symbol *search_up(char *nm); void add(Uc_symbol *sym) // Add (does NOT check for dups.) { const char *nm = sym->name.c_str(); char *nm1 = (char *)nm; // ???Can't figure this out! symbols[nm1] = sym; } Uc_scope *add_scope() // Create new scope. { Uc_scope *newscope = new Uc_scope(this); scopes.push_back(newscope); return newscope; } // Add a function decl. int add_function_symbol(Uc_function_symbol *fun); }; #endif exult-1.2/usecode/compiler/uclex.cc0000644000175000001440000016321310032174266013071 /* A lexical scanner generated by flex */ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 90 #define YY_END_OF_BUFFER 91 static yyconst short int yy_accept[322] = { 0, 0, 0, 84, 84, 91, 89, 81, 88, 66, 89, 80, 89, 89, 89, 89, 70, 70, 89, 89, 89, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 89, 84, 86, 85, 81, 73, 0, 68, 0, 80, 80, 80, 80, 64, 76, 0, 83, 82, 70, 0, 74, 72, 75, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 1, 6, 67, 67, 67, 61, 67, 60, 67, 67, 67, 67, 67, 63, 67, 67, 67, 67, 62, 67, 8, 67, 67, 67, 67, 67, 67, 65, 84, 85, 85, 87, 69, 0, 68, 0, 80, 80, 80, 0, 82, 71, 67, 22, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 5, 67, 67, 67, 67, 67, 54, 67, 10, 67, 67, 67, 67, 67, 37, 67, 67, 67, 67, 67, 67, 67, 21, 67, 52, 67, 67, 67, 67, 67, 67, 67, 9, 67, 67, 67, 67, 69, 80, 80, 80, 0, 67, 67, 67, 50, 18, 67, 67, 67, 67, 67, 58, 2, 13, 67, 67, 53, 67, 67, 67, 33, 67, 23, 67, 32, 67, 67, 45, 67, 67, 67, 67, 67, 67, 67, 41, 67, 67, 67, 67, 48, 67, 67, 15, 39, 59, 67, 7, 80, 80, 80, 0, 55, 27, 17, 11, 67, 67, 47, 67, 30, 67, 16, 43, 67, 44, 29, 67, 49, 67, 56, 67, 67, 67, 67, 67, 67, 57, 67, 67, 67, 28, 4, 80, 0, 80, 80, 80, 0, 67, 67, 67, 14, 31, 67, 38, 67, 40, 36, 67, 3, 26, 51, 19, 12, 0, 80, 77, 80, 80, 0, 67, 67, 42, 24, 67, 67, 0, 80, 80, 0, 35, 20, 46, 25, 80, 80, 34, 80, 80, 79, 80, 0, 80, 0, 80, 78, 0, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 1, 1, 9, 1, 1, 1, 10, 1, 1, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 16, 17, 18, 1, 1, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 21, 1, 1, 22, 1, 23, 24, 25, 26, 27, 28, 29, 30, 31, 20, 32, 33, 34, 35, 36, 37, 20, 38, 39, 40, 41, 42, 43, 44, 45, 20, 1, 46, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[47] = { 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 4, 4, 1, 1, 1, 4, 5, 1, 5, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1 } ; static yyconst short int yy_base[340] = { 0, 0, 0, 44, 45, 440, 441, 47, 441, 422, 43, 48, 429, 419, 400, 46, 43, 46, 418, 417, 416, 0, 37, 394, 44, 404, 49, 47, 38, 63, 60, 49, 65, 392, 42, 86, 66, 406, 89, 382, 0, 441, 58, 73, 441, 89, 417, 100, 0, 91, 391, 394, 441, 441, 386, 441, 0, 103, 0, 441, 441, 441, 0, 383, 396, 381, 393, 91, 384, 393, 378, 377, 376, 373, 386, 372, 100, 373, 387, 376, 368, 367, 101, 365, 0, 365, 377, 364, 363, 357, 98, 0, 373, 100, 360, 353, 359, 0, 352, 354, 367, 115, 0, 368, 0, 351, 353, 359, 350, 357, 347, 441, 0, 133, 134, 441, 441, 124, 141, 147, 144, 361, 350, 353, 0, 0, 347, 0, 355, 358, 347, 352, 121, 345, 352, 336, 348, 340, 338, 345, 344, 331, 0, 335, 345, 331, 341, 338, 0, 326, 0, 329, 323, 330, 320, 336, 0, 318, 315, 320, 328, 317, 312, 325, 0, 320, 0, 310, 322, 308, 310, 315, 313, 317, 0, 303, 302, 308, 310, 145, 332, 305, 310, 307, 297, 296, 301, 0, 0, 292, 300, 303, 302, 301, 0, 0, 0, 287, 288, 0, 298, 297, 294, 0, 292, 0, 282, 0, 297, 294, 0, 285, 287, 285, 273, 291, 277, 274, 0, 274, 280, 284, 277, 0, 272, 267, 0, 0, 0, 278, 0, 162, 263, 298, 271, 0, 0, 0, 0, 266, 262, 0, 264, 0, 263, 0, 0, 258, 0, 0, 267, 0, 255, 0, 258, 266, 252, 256, 255, 249, 0, 258, 262, 257, 0, 0, 164, 278, 281, 257, 141, 247, 240, 241, 239, 0, 0, 251, 0, 236, 0, 0, 237, 0, 0, 0, 0, 0, 272, 271, 441, 246, 159, 249, 244, 195, 0, 0, 173, 181, 204, 170, 193, 154, 0, 0, 0, 0, 174, 175, 441, 183, 178, 441, 181, 178, 167, 154, 129, 441, 112, 441, 188, 193, 198, 200, 205, 210, 215, 220, 94, 225, 230, 235, 240, 245, 250, 255, 260, 265 } ; static yyconst short int yy_def[340] = { 0, 321, 1, 322, 322, 321, 321, 321, 321, 321, 323, 324, 321, 321, 321, 321, 321, 321, 321, 321, 321, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 321, 326, 321, 327, 321, 321, 323, 321, 328, 324, 324, 324, 324, 321, 321, 321, 321, 329, 321, 330, 321, 321, 321, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 321, 326, 327, 327, 321, 321, 323, 323, 328, 324, 324, 324, 321, 329, 330, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 323, 324, 324, 324, 321, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 331, 324, 324, 321, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 331, 332, 333, 324, 324, 321, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 334, 333, 321, 324, 324, 321, 325, 325, 325, 325, 325, 325, 334, 324, 324, 321, 325, 325, 325, 325, 335, 336, 321, 335, 335, 321, 336, 337, 338, 339, 338, 321, 339, 0, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321 } ; static yyconst short int yy_nxt[488] = { 0, 6, 7, 8, 7, 7, 9, 10, 11, 12, 6, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 6, 6, 22, 23, 24, 25, 26, 27, 28, 29, 30, 21, 21, 31, 32, 21, 33, 34, 35, 36, 21, 37, 38, 21, 21, 39, 41, 41, 43, 46, 43, 43, 49, 42, 42, 55, 57, 57, 56, 57, 57, 63, 64, 47, 65, 79, 67, 114, 93, 76, 115, 71, 94, 80, 43, 87, 43, 43, 50, 68, 51, 72, 77, 73, 78, 81, 58, 84, 69, 88, 74, 89, 75, 82, 85, 46, 103, 125, 83, 86, 90, 104, 45, 105, 120, 120, 118, 91, 95, 47, 96, 107, 97, 98, 319, 108, 57, 57, 109, 110, 119, 99, 100, 130, 140, 101, 147, 155, 102, 131, 46, 319, 141, 159, 156, 157, 160, 169, 161, 162, 148, 170, 321, 114, 47, 321, 321, 46, 180, 45, 179, 46, 171, 118, 292, 292, 319, 120, 120, 189, 190, 47, 191, 302, 267, 47, 267, 119, 268, 319, 268, 308, 292, 292, 308, 312, 313, 315, 312, 312, 313, 316, 312, 315, 317, 313, 310, 316, 40, 40, 40, 40, 40, 45, 45, 45, 45, 45, 48, 309, 48, 48, 48, 62, 62, 112, 290, 307, 112, 112, 113, 306, 113, 113, 113, 117, 117, 117, 117, 117, 124, 305, 124, 124, 124, 266, 266, 266, 266, 266, 267, 267, 267, 267, 267, 289, 289, 289, 289, 289, 300, 300, 300, 300, 300, 311, 311, 311, 311, 311, 314, 314, 314, 314, 314, 315, 315, 315, 315, 315, 318, 318, 318, 318, 318, 320, 320, 320, 320, 320, 304, 303, 301, 290, 290, 299, 298, 297, 296, 295, 294, 293, 291, 290, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 188, 187, 186, 185, 184, 183, 182, 181, 178, 177, 176, 175, 174, 173, 172, 168, 167, 166, 165, 164, 163, 158, 154, 153, 152, 151, 150, 149, 146, 145, 144, 143, 142, 139, 138, 137, 136, 135, 134, 133, 132, 129, 128, 127, 126, 123, 122, 121, 116, 111, 106, 92, 70, 66, 61, 60, 59, 54, 53, 52, 44, 321, 5, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321 } ; static yyconst short int yy_chk[488] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 7, 10, 7, 7, 11, 3, 4, 15, 16, 16, 15, 17, 17, 22, 22, 10, 22, 28, 24, 42, 34, 27, 42, 26, 34, 28, 43, 31, 43, 43, 11, 24, 11, 26, 27, 26, 27, 29, 16, 30, 24, 31, 26, 32, 26, 29, 30, 45, 36, 330, 29, 30, 32, 36, 47, 36, 49, 49, 47, 32, 35, 45, 35, 38, 35, 35, 320, 38, 57, 57, 38, 38, 47, 35, 35, 67, 76, 35, 82, 90, 35, 67, 117, 318, 76, 93, 90, 90, 93, 101, 93, 93, 82, 101, 113, 114, 117, 113, 114, 118, 120, 119, 118, 179, 101, 119, 270, 270, 317, 120, 120, 132, 132, 118, 132, 292, 231, 179, 266, 119, 231, 316, 266, 301, 292, 292, 301, 308, 308, 309, 308, 312, 312, 309, 312, 314, 315, 311, 303, 314, 322, 322, 322, 322, 322, 323, 323, 323, 323, 323, 324, 302, 324, 324, 324, 325, 325, 326, 300, 299, 326, 326, 327, 298, 327, 327, 327, 328, 328, 328, 328, 328, 329, 295, 329, 329, 329, 331, 331, 331, 331, 331, 332, 332, 332, 332, 332, 333, 333, 333, 333, 333, 334, 334, 334, 334, 334, 335, 335, 335, 335, 335, 336, 336, 336, 336, 336, 337, 337, 337, 337, 337, 338, 338, 338, 338, 338, 339, 339, 339, 339, 339, 294, 293, 291, 289, 288, 282, 279, 277, 274, 273, 272, 271, 269, 268, 267, 263, 262, 261, 259, 258, 257, 256, 255, 254, 252, 250, 247, 244, 242, 240, 239, 234, 233, 232, 229, 225, 224, 222, 221, 220, 219, 217, 216, 215, 214, 213, 212, 211, 209, 208, 206, 204, 202, 201, 200, 198, 197, 193, 192, 191, 190, 189, 186, 185, 184, 183, 182, 181, 180, 178, 177, 176, 175, 173, 172, 171, 170, 169, 168, 167, 165, 163, 162, 161, 160, 159, 158, 157, 155, 154, 153, 152, 151, 149, 147, 146, 145, 144, 143, 141, 140, 139, 138, 137, 136, 135, 134, 133, 131, 130, 129, 128, 126, 123, 122, 121, 110, 109, 108, 107, 106, 105, 103, 100, 99, 98, 96, 95, 94, 92, 89, 88, 87, 86, 85, 83, 81, 80, 79, 78, 77, 75, 74, 73, 72, 71, 70, 69, 68, 66, 65, 64, 63, 54, 51, 50, 46, 39, 37, 33, 25, 23, 20, 19, 18, 14, 13, 12, 9, 5, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "uclex.ll" #define INITIAL 0 #line 2 "uclex.ll" /** ** Uclex.ll - Usecode lexical scanner. ** ** Written: 12/30/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "ucparse.h" #include "ucloc.h" using std::string; extern std::vector include_dirs; // -I directories. /* * Want a stack of files for implementing '#include'. */ std::vector locstack; std::vector bufstack; /* * Parse out a name in quotes. * * Output: ->name, with a null replacing the ending quote. * 0 if not found. */ static char *Find_name ( char *name, char *& ename // ->null at end of name returned. ) { while (*name && *name != '"') // Find start of filename. name++; if (!*name) return 0; name++; // Point to name. ename = name; // Find end. while (*ename && *ename != '"') ename++; if (!*ename) return 0; *ename = 0; return name; } /* * Set location from a preprocessor string. */ static void Set_location ( char *text // ->first digit of line #. ) { char *name; int line = strtol(text, &name, 10); char *ename; name = Find_name(name, ename); if (!name) return; //cout << "Setting location at line " << line - 1 << endl; // We're 0-based. Uc_location::set_cur(name, line - 1); *name = '"'; // Restore text. } /* * Include another source. */ static void Include ( char *yytext // ->text containing name. ) { char msg[180]; if (bufstack.size() > 20) { Uc_location::yyerror("#includes are nested too deeply"); exit(1); } char *ename; char *name = Find_name(yytext, ename); if (!name) { Uc_location::yyerror("No file in #include"); return; } locstack.push_back(new Uc_location()); bufstack.push_back(YY_CURRENT_BUFFER); yyin = fopen(name, "r"); // Look in -I list if not found here. for (std::vector::const_iterator it = include_dirs.begin(); !yyin && it != include_dirs.end(); ++it) { string path(*it); path += '/'; path += name; yyin = fopen(path.c_str(), "r"); } if (!yyin) { sprintf(msg, "Can't open '%s'", name); Uc_location::yyerror(msg); exit(1); } // Set location to new file. Uc_location::set_cur(name, 0); yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); } /* * Make a copy of a string, interpreting '\' codes. * * Output: ->allocated string. */ char *Handle_string ( const char *from // Ends with a '"'. ) { char *to = new char[1 + strlen(from)]; // (Bigger than needed.) char *str = to; while (*from && *from != '\"') { if (*from != '\\') { *to++ = *from++; continue; } switch (*++from) { case 'n': *to++ = '\n'; break; default: *to++ = *from; break; } ++from; } *to = 0; return str; } extern "C" int yywrap() { return 1; } /* Stop at EOF. */ #define comment 1 #line 749 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; #line 174 "uclex.ll" #line 903 "lex.yy.c" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 322 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 441 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 176 "uclex.ll" return IF; YY_BREAK case 2: YY_RULE_SETUP #line 177 "uclex.ll" return ELSE; YY_BREAK case 3: YY_RULE_SETUP #line 178 "uclex.ll" return RETURN; YY_BREAK case 4: YY_RULE_SETUP #line 179 "uclex.ll" return WHILE; YY_BREAK case 5: YY_RULE_SETUP #line 180 "uclex.ll" return FOR; YY_BREAK case 6: YY_RULE_SETUP #line 181 "uclex.ll" return UCC_IN; YY_BREAK case 7: YY_RULE_SETUP #line 182 "uclex.ll" return WITH; YY_BREAK case 8: YY_RULE_SETUP #line 183 "uclex.ll" return TO; YY_BREAK case 9: YY_RULE_SETUP #line 184 "uclex.ll" return VAR; YY_BREAK case 10: YY_RULE_SETUP #line 185 "uclex.ll" return UCC_INT; YY_BREAK case 11: YY_RULE_SETUP #line 186 "uclex.ll" return UCC_CONST; YY_BREAK case 12: YY_RULE_SETUP #line 187 "uclex.ll" return STRING; YY_BREAK case 13: YY_RULE_SETUP #line 188 "uclex.ll" return ENUM; YY_BREAK case 14: YY_RULE_SETUP #line 189 "uclex.ll" return EXTERN; YY_BREAK case 15: YY_RULE_SETUP #line 190 "uclex.ll" return UCTRUE; YY_BREAK case 16: YY_RULE_SETUP #line 191 "uclex.ll" return UCFALSE; YY_BREAK case 17: YY_RULE_SETUP #line 192 "uclex.ll" return BREAK; YY_BREAK case 18: YY_RULE_SETUP #line 193 "uclex.ll" return CASE; YY_BREAK case 19: YY_RULE_SETUP #line 194 "uclex.ll" return STATIC_; YY_BREAK case 20: YY_RULE_SETUP #line 196 "uclex.ll" return CONVERSE; YY_BREAK case 21: YY_RULE_SETUP #line 197 "uclex.ll" return SAY; YY_BREAK case 22: YY_RULE_SETUP #line 198 "uclex.ll" return ADD; YY_BREAK case 23: YY_RULE_SETUP #line 199 "uclex.ll" return HIDE; YY_BREAK case 24: YY_RULE_SETUP #line 200 "uclex.ll" return MESSAGE; YY_BREAK case 25: YY_RULE_SETUP #line 201 "uclex.ll" return RESPONSE; YY_BREAK case 26: YY_RULE_SETUP #line 202 "uclex.ll" return SCRIPT; YY_BREAK case 27: YY_RULE_SETUP #line 203 "uclex.ll" return AFTER; YY_BREAK case 28: YY_RULE_SETUP #line 204 "uclex.ll" return TICKS; YY_BREAK case 29: YY_RULE_SETUP #line 205 "uclex.ll" return HOURS; YY_BREAK case 30: YY_RULE_SETUP #line 206 "uclex.ll" return EVENT; YY_BREAK case 31: YY_RULE_SETUP #line 207 "uclex.ll" return FLAG; YY_BREAK case 32: YY_RULE_SETUP #line 208 "uclex.ll" return ITEM; YY_BREAK case 33: YY_RULE_SETUP #line 209 "uclex.ll" return GOTO; YY_BREAK case 34: YY_RULE_SETUP #line 210 "uclex.ll" return ORIGINAL; YY_BREAK /* Script commands. */ case 35: YY_RULE_SETUP #line 213 "uclex.ll" return CONTINUE; YY_BREAK case 36: YY_RULE_SETUP #line 214 "uclex.ll" return REPEAT; YY_BREAK case 37: YY_RULE_SETUP #line 215 "uclex.ll" return NOP; YY_BREAK case 38: YY_RULE_SETUP #line 216 "uclex.ll" return NOHALT; YY_BREAK case 39: YY_RULE_SETUP #line 217 "uclex.ll" return WAIT; YY_BREAK case 40: YY_RULE_SETUP #line 218 "uclex.ll" return REMOVE; YY_BREAK case 41: YY_RULE_SETUP #line 219 "uclex.ll" return RISE; YY_BREAK case 42: YY_RULE_SETUP #line 220 "uclex.ll" return DESCEND; YY_BREAK case 43: YY_RULE_SETUP #line 221 "uclex.ll" return FRAME; YY_BREAK case 44: YY_RULE_SETUP #line 222 "uclex.ll" return HATCH; YY_BREAK case 45: YY_RULE_SETUP #line 223 "uclex.ll" return NEXT; YY_BREAK case 46: YY_RULE_SETUP #line 224 "uclex.ll" return PREVIOUS; YY_BREAK case 47: YY_RULE_SETUP #line 225 "uclex.ll" return CYCLE; YY_BREAK case 48: YY_RULE_SETUP #line 226 "uclex.ll" return STEP; YY_BREAK case 49: YY_RULE_SETUP #line 227 "uclex.ll" return MUSIC; YY_BREAK case 50: YY_RULE_SETUP #line 228 "uclex.ll" return CALL; YY_BREAK case 51: YY_RULE_SETUP #line 229 "uclex.ll" return SPEECH; YY_BREAK case 52: YY_RULE_SETUP #line 230 "uclex.ll" return SFX; YY_BREAK case 53: YY_RULE_SETUP #line 231 "uclex.ll" return FACE; YY_BREAK case 54: YY_RULE_SETUP #line 232 "uclex.ll" return HIT; YY_BREAK case 55: YY_RULE_SETUP #line 233 "uclex.ll" return ACTOR; YY_BREAK case 56: YY_RULE_SETUP #line 235 "uclex.ll" return NORTH; YY_BREAK case 57: YY_RULE_SETUP #line 236 "uclex.ll" return SOUTH; YY_BREAK case 58: YY_RULE_SETUP #line 237 "uclex.ll" return EAST; YY_BREAK case 59: YY_RULE_SETUP #line 238 "uclex.ll" return WEST; YY_BREAK case 60: YY_RULE_SETUP #line 239 "uclex.ll" return NW; YY_BREAK case 61: YY_RULE_SETUP #line 240 "uclex.ll" return NE; YY_BREAK case 62: YY_RULE_SETUP #line 241 "uclex.ll" return SW; YY_BREAK case 63: YY_RULE_SETUP #line 242 "uclex.ll" return SE; YY_BREAK case 64: YY_RULE_SETUP #line 244 "uclex.ll" return AND; YY_BREAK case 65: YY_RULE_SETUP #line 245 "uclex.ll" return OR; YY_BREAK case 66: YY_RULE_SETUP #line 246 "uclex.ll" return NOT; YY_BREAK case 67: YY_RULE_SETUP #line 248 "uclex.ll" { yylval.strval = strdup(yytext); return IDENTIFIER; } YY_BREAK case 68: YY_RULE_SETUP #line 252 "uclex.ll" { // Remove ending quote. yylval.strval = Handle_string(yytext + 1); return STRING_LITERAL; } YY_BREAK case 69: YY_RULE_SETUP #line 257 "uclex.ll" { // Remove ending quote and asterisk. yylval.strval = strdup(yytext + 1); yylval.strval[strlen(yylval.strval) - 2] = 0; return STRING_PREFIX; } YY_BREAK case 70: YY_RULE_SETUP #line 263 "uclex.ll" { yylval.intval = atoi(yytext); return INT_LITERAL; } YY_BREAK case 71: YY_RULE_SETUP #line 267 "uclex.ll" { yylval.intval = strtol(yytext + 2, 0, 16); return INT_LITERAL; } YY_BREAK case 72: YY_RULE_SETUP #line 272 "uclex.ll" { return EQUALS; } YY_BREAK case 73: YY_RULE_SETUP #line 273 "uclex.ll" { return NEQUALS; } YY_BREAK case 74: YY_RULE_SETUP #line 274 "uclex.ll" { return LTEQUALS; } YY_BREAK case 75: YY_RULE_SETUP #line 275 "uclex.ll" { return GTEQUALS; } YY_BREAK case 76: YY_RULE_SETUP #line 276 "uclex.ll" { return UCC_POINTS; } YY_BREAK case 77: YY_RULE_SETUP #line 278 "uclex.ll" { Set_location(yytext + 2); } YY_BREAK case 78: YY_RULE_SETUP #line 279 "uclex.ll" { Set_location(yytext + 6); } YY_BREAK case 79: YY_RULE_SETUP #line 280 "uclex.ll" { Include(yytext + 8); } YY_BREAK case 80: YY_RULE_SETUP #line 282 "uclex.ll" /* Ignore other cpp directives. */ YY_BREAK case 81: YY_RULE_SETUP #line 284 "uclex.ll" /* Ignore spaces. */ YY_BREAK case 82: YY_RULE_SETUP #line 285 "uclex.ll" /* Comments. */ YY_BREAK case 83: YY_RULE_SETUP #line 286 "uclex.ll" BEGIN(comment); YY_BREAK case 84: YY_RULE_SETUP #line 287 "uclex.ll" /* All but '*'. */ YY_BREAK case 85: YY_RULE_SETUP #line 288 "uclex.ll" /* *'s not followed by '/'. */ YY_BREAK case 86: YY_RULE_SETUP #line 289 "uclex.ll" { Uc_location::increment_cur_line(); } YY_BREAK case 87: YY_RULE_SETUP #line 290 "uclex.ll" BEGIN(INITIAL); YY_BREAK case YY_STATE_EOF(comment): #line 291 "uclex.ll" { Uc_location::yyerror("Comment not terminated"); yyterminate(); } YY_BREAK case 88: YY_RULE_SETUP #line 293 "uclex.ll" { Uc_location::increment_cur_line(); } YY_BREAK case 89: YY_RULE_SETUP #line 294 "uclex.ll" return *yytext; /* Being lazy. */ YY_BREAK case YY_STATE_EOF(INITIAL): #line 295 "uclex.ll" { if (locstack.empty()) yyterminate(); else // Restore buffer and location. { Uc_location *loc = locstack.back(); locstack.pop_back(); const char *nm = loc->get_source(); loc->set_cur(nm, loc->get_line()); delete loc; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(bufstack.back()); bufstack.pop_back(); } } YY_BREAK case 90: YY_RULE_SETUP #line 312 "uclex.ll" ECHO; YY_BREAK #line 1478 "lex.yy.c" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 322 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 322 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 321); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; return c; } #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif #line 312 "uclex.ll" exult-1.2/usecode/compiler/uclex.ll0000644000175000001440000001467610026506353013122 %{ /** ** Uclex.ll - Usecode lexical scanner. ** ** Written: 12/30/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "ucparse.h" #include "ucloc.h" using std::string; extern std::vector include_dirs; // -I directories. /* * Want a stack of files for implementing '#include'. */ std::vector locstack; std::vector bufstack; /* * Parse out a name in quotes. * * Output: ->name, with a null replacing the ending quote. * 0 if not found. */ static char *Find_name ( char *name, char *& ename // ->null at end of name returned. ) { while (*name && *name != '"') // Find start of filename. name++; if (!*name) return 0; name++; // Point to name. ename = name; // Find end. while (*ename && *ename != '"') ename++; if (!*ename) return 0; *ename = 0; return name; } /* * Set location from a preprocessor string. */ static void Set_location ( char *text // ->first digit of line #. ) { char *name; int line = strtol(text, &name, 10); char *ename; name = Find_name(name, ename); if (!name) return; //cout << "Setting location at line " << line - 1 << endl; // We're 0-based. Uc_location::set_cur(name, line - 1); *name = '"'; // Restore text. } /* * Include another source. */ static void Include ( char *yytext // ->text containing name. ) { char msg[180]; if (bufstack.size() > 20) { Uc_location::yyerror("#includes are nested too deeply"); exit(1); } char *ename; char *name = Find_name(yytext, ename); if (!name) { Uc_location::yyerror("No file in #include"); return; } locstack.push_back(new Uc_location()); bufstack.push_back(YY_CURRENT_BUFFER); yyin = fopen(name, "r"); // Look in -I list if not found here. for (std::vector::const_iterator it = include_dirs.begin(); !yyin && it != include_dirs.end(); ++it) { string path(*it); path += '/'; path += name; yyin = fopen(path.c_str(), "r"); } if (!yyin) { sprintf(msg, "Can't open '%s'", name); Uc_location::yyerror(msg); exit(1); } // Set location to new file. Uc_location::set_cur(name, 0); yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); } /* * Make a copy of a string, interpreting '\' codes. * * Output: ->allocated string. */ char *Handle_string ( const char *from // Ends with a '"'. ) { char *to = new char[1 + strlen(from)]; // (Bigger than needed.) char *str = to; while (*from && *from != '\"') { if (*from != '\\') { *to++ = *from++; continue; } switch (*++from) { case 'n': *to++ = '\n'; break; default: *to++ = *from; break; } ++from; } *to = 0; return str; } extern "C" int yywrap() { return 1; } /* Stop at EOF. */ %} %x comment %% if return IF; else return ELSE; return return RETURN; while return WHILE; for return FOR; in return UCC_IN; with return WITH; to return TO; var return VAR; int return UCC_INT; const return UCC_CONST; string return STRING; enum return ENUM; extern return EXTERN; true return UCTRUE; false return UCFALSE; break return BREAK; case return CASE; static return STATIC_; converse return CONVERSE; say return SAY; add return ADD; hide return HIDE; message return MESSAGE; response return RESPONSE; script return SCRIPT; after return AFTER; ticks return TICKS; hours return HOURS; event return EVENT; gflags return FLAG; item return ITEM; goto return GOTO; ".original" return ORIGINAL; /* Script commands. */ continue return CONTINUE; repeat return REPEAT; nop return NOP; nohalt return NOHALT; wait return WAIT; remove return REMOVE; rise return RISE; descent return DESCEND; frame return FRAME; hatch return HATCH; next return NEXT; previous return PREVIOUS; cycle return CYCLE; step return STEP; music return MUSIC; call return CALL; speech return SPEECH; sfx return SFX; face return FACE; hit return HIT; actor return ACTOR; north return NORTH; south return SOUTH; east return EAST; west return WEST; nw return NW; ne return NE; sw return SW; se return SE; "&&" return AND; "||" return OR; "!" return NOT; [a-zA-Z][a-zA-Z0-9_]* { yylval.strval = strdup(yytext); return IDENTIFIER; } \"([^"]|\\.)*\" { // Remove ending quote. yylval.strval = Handle_string(yytext + 1); return STRING_LITERAL; } \"([^"]|\\.)*\"\* { // Remove ending quote and asterisk. yylval.strval = strdup(yytext + 1); yylval.strval[strlen(yylval.strval) - 2] = 0; return STRING_PREFIX; } [0-9]+ { yylval.intval = atoi(yytext); return INT_LITERAL; } 0x[0-9a-fA-F]+ { yylval.intval = strtol(yytext + 2, 0, 16); return INT_LITERAL; } "==" { return EQUALS; } "!=" { return NEQUALS; } "<=" { return LTEQUALS; } ">=" { return GTEQUALS; } "->" { return UCC_POINTS; } "# "[0-9]+\ \"[^"]*\".*\n { Set_location(yytext + 2); } "#line "[0-9]+\ \"[^"]*\".*\n { Set_location(yytext + 6); } "#include"[ \t]+.*\n { Include(yytext + 8); } \#.* /* Ignore other cpp directives. */ [ \t\r]+ /* Ignore spaces. */ "//".* /* Comments. */ "/*" BEGIN(comment); [^*\n]* /* All but '*'. */ "*"+[^*/\n]* /* *'s not followed by '/'. */ \n { Uc_location::increment_cur_line(); } "*/" BEGIN(INITIAL); <> { Uc_location::yyerror("Comment not terminated"); yyterminate(); } \n { Uc_location::increment_cur_line(); } . return *yytext; /* Being lazy. */ <> { if (locstack.empty()) yyterminate(); else // Restore buffer and location. { Uc_location *loc = locstack.back(); locstack.pop_back(); const char *nm = loc->get_source(); loc->set_cur(nm, loc->get_line()); delete loc; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(bufstack.back()); bufstack.pop_back(); } } %% exult-1.2/usecode/compiler/ucloc.cc0000644000175000001440000000364607477225120013066 /** ** Ucloc.cc - Source location. ** ** Written: 1/0/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "ucloc.h" using std::strcmp; using std::strcpy; using std::strlen; using std::cout; using std::endl; std::vector Uc_location::source_names; char *Uc_location::cur_source = 0; int Uc_location::cur_line = 0; int Uc_location::num_errors = 0; /* * Set current source and line #. */ void Uc_location::set_cur ( const char *s, int l ) { cur_line = l; cur_source = 0; // See if already here. for (std::vector::const_iterator it = source_names.begin(); it != source_names.end(); it++) if (strcmp(s, *it) == 0) { cur_source = *it; break; } if (!cur_source) // 1st time. { int len = strlen(s); cur_source = new char[len + 1]; strcpy(cur_source, s); source_names.push_back(cur_source); } } /* * Print error for stored position. */ void Uc_location::error ( char *s ) { cout << source << ':' << line + 1 << ": " << s << endl; num_errors++; } /* * Print error for current parse location. */ void Uc_location::yyerror ( char *s ) { cout << cur_source << ':' << cur_line + 1 << ": " << s << endl; num_errors++; } exult-1.2/usecode/compiler/ucparse.h0000644000175000001440000000373710013577452013264 #ifndef BISON_Y_TAB_H # define BISON_Y_TAB_H #ifndef YYSTYPE typedef union { class Uc_symbol *sym; class Uc_var_symbol *var; class Uc_expression *expr; class Uc_call_expression *funcall; class Uc_function_symbol *funsym; class Uc_statement *stmt; class std::vector *strvec; class Uc_block_statement *block; class Uc_arrayloop_statement *arrayloop; class Uc_array_expression *exprlist; int intval; char *strval; } yystype; # define YYSTYPE yystype # define YYSTYPE_IS_TRIVIAL 1 #endif # define IF 257 # define ELSE 258 # define RETURN 259 # define WHILE 260 # define FOR 261 # define UCC_IN 262 # define WITH 263 # define TO 264 # define EXTERN 265 # define BREAK 266 # define GOTO 267 # define CASE 268 # define VAR 269 # define UCC_INT 270 # define UCC_CONST 271 # define STRING 272 # define ENUM 273 # define CONVERSE 274 # define SAY 275 # define MESSAGE 276 # define RESPONSE 277 # define EVENT 278 # define FLAG 279 # define ITEM 280 # define UCTRUE 281 # define UCFALSE 282 # define REMOVE 283 # define ADD 284 # define HIDE 285 # define SCRIPT 286 # define AFTER 287 # define TICKS 288 # define STATIC_ 289 # define ORIGINAL 290 # define CONTINUE 291 # define REPEAT 292 # define NOP 293 # define NOHALT 294 # define WAIT 295 # define RISE 296 # define DESCEND 297 # define FRAME 298 # define HATCH 299 # define NEXT 300 # define PREVIOUS 301 # define CYCLE 302 # define STEP 303 # define MUSIC 304 # define CALL 305 # define SPEECH 306 # define SFX 307 # define FACE 308 # define HIT 309 # define HOURS 310 # define ACTOR 311 # define NORTH 312 # define SOUTH 313 # define EAST 314 # define WEST 315 # define NE 316 # define NW 317 # define SE 318 # define SW 319 # define STRING_LITERAL 320 # define STRING_PREFIX 321 # define IDENTIFIER 322 # define INT_LITERAL 323 # define AND 324 # define OR 325 # define EQUALS 326 # define NEQUALS 327 # define LTEQUALS 328 # define GTEQUALS 329 # define NOT 330 # define UCC_POINTS 331 extern YYSTYPE yylval; #endif /* not BISON_Y_TAB_H */ exult-1.2/usecode/compiler/ucstmt.h0000644000175000001440000001541207471600176013136 /** ** Ucstmt.h - Usecode compiler statements. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_UCSTMT #define INCL_UCSTMT #include #include "ucloc.h" #include "uclabel.h" class Uc_expression; class Uc_call_expression; class Uc_array_expression; class Uc_function; class Uc_var_symbol; #ifndef ALPHA_LINUX_CXX # include #endif /* * A statement: */ class Uc_statement : public Uc_location { public: Uc_statement() : Uc_location() { } virtual ~Uc_statement() { } // Generate code. virtual void gen(std::vector& out, Uc_function *fun) = 0; }; /* * A group of statements. */ class Uc_block_statement : public Uc_statement { std::vector statements; public: Uc_block_statement() { } ~Uc_block_statement(); void add(Uc_statement *stmt) { statements.push_back(stmt); } // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * An assignment statement: */ class Uc_assignment_statement : public Uc_statement { Uc_expression *target, *value; public: Uc_assignment_statement(Uc_expression *t, Uc_expression *v) : target(t), value(v) { } ~Uc_assignment_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * An IF statement: */ class Uc_if_statement : public Uc_statement { Uc_expression *expr; // What to test. // What to execute: Uc_statement *if_stmt, *else_stmt; public: Uc_if_statement(Uc_expression *e, Uc_statement *t, Uc_statement *f) : expr(e), if_stmt(t), else_stmt(f) { } ~Uc_if_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * An WHILE statement: */ class Uc_while_statement : public Uc_statement { Uc_expression *expr; // What to test. Uc_statement *stmt; // What to execute. public: Uc_while_statement(Uc_expression *e, Uc_statement *s) : expr(e), stmt(s) { } ~Uc_while_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * An array loop statement: */ class Uc_arrayloop_statement : public Uc_statement { Uc_var_symbol *var; // Loop variable. Uc_var_symbol *array; // Array to loop over. Uc_var_symbol *index; // Counter. Uc_var_symbol *array_size; // Symbol holding array size. Uc_statement *stmt; // What to execute. public: Uc_arrayloop_statement(Uc_var_symbol *v, Uc_var_symbol *a) : var(v), array(a), index(0), array_size(0), stmt(0) { } ~Uc_arrayloop_statement(); void set_statement(Uc_statement *s) { stmt = s; } void set_index(Uc_var_symbol *i) { index = i; } void set_array_size(Uc_var_symbol *as) { array_size = as; } void finish(Uc_function *fun); // Create tmps. if necessary. // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * An RETURN statement: */ class Uc_return_statement : public Uc_statement { Uc_expression *expr; // What to return. May be 0. public: Uc_return_statement(Uc_expression *e = 0) : expr(e) { } ~Uc_return_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * BREAK statement: */ class Uc_break_statement : public Uc_statement { public: Uc_break_statement() { } // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * a LABEL statement: */ class Uc_label_statement : public Uc_statement { Uc_label *label; public: Uc_label_statement(Uc_label *l) : label(l) { } virtual void gen(std::vector& out, Uc_function *fun); }; /* * a GOTO statement: */ class Uc_goto_statement : public Uc_statement { char *label; public: Uc_goto_statement(char *l) : label(l) { } virtual void gen(std::vector& out, Uc_function *fun); }; /* * A CONVERSE statement is a loop that prompts for a user response at * the top, or exits the loop if there are no possible answers. */ class Uc_converse_statement : public Uc_statement { Uc_statement *stmt; // What to execute. public: Uc_converse_statement(Uc_statement *s) : stmt(s) { } ~Uc_converse_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * Conversation CASE statement: */ class Uc_converse_case_statement : public Uc_statement { int string_offset; // Offset of string to compare. bool remove; // True to remove answer. Uc_statement *statements; // Execute these. public: Uc_converse_case_statement(int soff, bool rem, Uc_statement *stmts) : string_offset(soff), remove(rem), statements(stmts) { } ~Uc_converse_case_statement() { delete statements; } // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * A CONVERSE2 statement provides a less wordy way to implement a * conversation. It provides for CASE entries for the comparisons, and * also generates push/pop-answers so these can be nested. */ class Uc_converse2_statement : public Uc_statement { static int nest; // Keeps track of nesting. Uc_expression *answers; // Answers to add. Uc_statement *cases; // What to execute. public: Uc_converse2_statement(Uc_expression *a, Uc_statement *cs) : answers(a), cases(cs) { } ~Uc_converse2_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * Add string to current message (for conversations). */ class Uc_message_statement : public Uc_statement { Uc_array_expression *msgs; public: Uc_message_statement(Uc_array_expression *m) : msgs(m) { } // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * Print message on screen (in conversation). */ class Uc_say_statement : public Uc_message_statement { public: Uc_say_statement(Uc_array_expression *m) : Uc_message_statement(m) { } // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; /* * Call a function/intrinsic. */ class Uc_call_statement : public Uc_statement { Uc_call_expression *function_call; public: Uc_call_statement(Uc_call_expression *f); ~Uc_call_statement(); // Generate code. virtual void gen(std::vector& out, Uc_function *fun); }; #endif exult-1.2/usecode/compiler/ucsym.cc0000644000175000001440000002000407732251221013077 /** ** Ucsym.cc - Usecode compiler symbol table. ** ** Written: 1/2/01 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "ucsym.h" #include "opcodes.h" #include "utils.h" #include "ucexpr.h" #include "ucfun.h" using std::strcmp; int Uc_function_symbol::last_num = -1; Uc_function_symbol::Sym_nums Uc_function_symbol::nums_used; /* * Assign value on stack. * * Output: 0 if can't do this. */ int Uc_symbol::gen_assign ( vector& out ) { return 0; } /* * Generate code to push variable's value on stack. * * Output: 0 if can't do this. */ int Uc_symbol::gen_value ( vector& out ) { return 0; } /* * Generate function call. * * Output: 0 if can't do this. */ int Uc_symbol::gen_call ( vector& out, Uc_function *fun, bool orig, // Call original (not one from patch). Uc_expression *itemref, // Non-NULL for CALLE. Uc_array_expression *parms, // Parameter list. bool retvalue // True if a function. ) { return 0; } /* * Create an expression with this value. */ Uc_expression *Uc_symbol::create_expression ( ) { return 0; } /* * Assign value on stack. * * Output: 0 if can't do this. */ int Uc_var_symbol::gen_assign ( vector& out ) { out.push_back((char) UC_POP); Write2(out, offset); return 1; } /* * Generate code to push variable's value on stack. * * Output: 0 if can't do this. */ int Uc_var_symbol::gen_value ( vector& out ) { out.push_back((char) UC_PUSH); Write2(out, offset); return 1; } /* * Create an expression with this value. */ Uc_expression *Uc_var_symbol::create_expression ( ) { return new Uc_var_expression(this); } /* * Assign value on stack. * * Output: 0 if can't do this. */ int Uc_static_var_symbol::gen_assign ( vector& out ) { out.push_back((char) UC_POPSTATIC); Write2(out, offset); return 1; } /* * Generate code to push variable's value on stack. * * Output: 0 if can't do this. */ int Uc_static_var_symbol::gen_value ( vector& out ) { out.push_back((char) UC_PUSHSTATIC); Write2(out, offset); return 1; } /* * Generate code to push variable's value on stack. * * Output: 0 if can't do this. */ int Uc_const_int_symbol::gen_value ( vector& out ) { out.push_back((char) UC_PUSHI); Write2(out, value); return 1; } /* * Create an expression with this value. */ Uc_expression *Uc_const_int_symbol::create_expression ( ) { return new Uc_int_expression(value); } /* * Generate code to push variable's value on stack. * * Output: 0 if can't do this. */ int Uc_string_symbol::gen_value ( vector& out ) { out.push_back((char) UC_PUSHS); Write2(out, offset); return 1; } /* * Create an expression with this value. */ Uc_expression *Uc_string_symbol::create_expression ( ) { return new Uc_string_expression(offset); } /* * Generate function call. * * Output: 0 if can't do this. */ int Uc_intrinsic_symbol::gen_call ( vector& out, Uc_function *fun, bool orig, // Call original (not one from patch). Uc_expression *itemref, // Non-NULL for CALLE. Uc_array_expression *parms, // Parameter list. bool retvalue // True if a function. ) { int parmcnt = 0; if (itemref) // Makes no sense for intrinsice. Uc_location::yyerror("Can't use ITEM for intrinsic"); // Want to push parm. values. const std::vector& exprs = parms->get_exprs(); // Push backwards, so #0 pops first. for (std::vector::const_reverse_iterator it = exprs.rbegin(); it != exprs.rend(); it++) { Uc_expression *expr = *it; expr->gen_value(out); parmcnt++; } // ++++ parmcnt == num_parms. // Opcode depends on val. returned. out.push_back((char) (retvalue ? UC_CALLIS : UC_CALLI)); Write2(out, intrinsic_num); // Intrinsic # is 2 bytes. out.push_back((char) parmcnt); // Parm. count is 1. return 1; } /* * Create new function. */ Uc_function_symbol::Uc_function_symbol ( char *nm, int num, // Function #, or -1 to assign // 1 + last_num. std::vector& p ) : Uc_symbol(nm), parms(p), usecode_num(num) { last_num = usecode_num = num >= 0 ? num : (last_num + 1); // Keep track of #'s used. Sym_nums::const_iterator it = nums_used.find(usecode_num); if (it == nums_used.end()) // Unused? That's good. nums_used[usecode_num] = this; else { char buf[256]; sprintf(buf, "Function 0x%x already used for '%s'.", usecode_num, ((*it).second)->get_name()); Uc_location::yyerror(buf); } } /* * Generate function call. * * Output: 0 if can't do this. */ int Uc_function_symbol::gen_call ( vector& out, Uc_function *fun, bool orig, // Call original (not one from patch). Uc_expression *itemref, // Non-NULL for CALLE. Uc_array_expression *aparms, // Actual parameter list. bool /* retvalue */ // True if a function. ) { int parmcnt = 0; // Want to push parm. values. const std::vector& exprs = aparms->get_exprs(); // Push forwards, so #0 pops last. for (std::vector::const_iterator it = exprs.begin(); it != exprs.end(); it++) { Uc_expression *expr = *it; expr->gen_value(out); parmcnt++; } if (parmcnt != parms.size()) { char buf[100]; sprintf(buf, "# parms. passed (%d) doesn't match '%s' count (%d)", parmcnt, get_name(), parms.size()); } if (orig) { if (!itemref) { Uc_item_expression item; item.gen_value(out); } else itemref->gen_value(out); out.push_back((char) UC_CALLO); Write2(out, usecode_num); // Use fun# directly. } else if (itemref) // Doing CALLE? Push item onto stack. { itemref->gen_value(out); out.push_back((char) UC_CALLE); Write2(out, usecode_num); // Use fun# directly. } else // Normal CALL. { // Called function sets return. out.push_back((char) UC_CALL); // Get offset in function's list. int link = fun->link(this); Write2(out, link); } return 1; } bool String_compare::operator()(char * const &x, char * const &y) const { return strcmp(x, y) < 0; } /* * Delete. */ Uc_scope::~Uc_scope ( ) { for (std::map::iterator it = symbols.begin(); it != symbols.end(); it++) delete (*it).second; for (std::vector::iterator it = scopes.begin(); it != scopes.end(); it++) delete *it; } /* * Search upwards through scope. * * Output: ->symbol if found, else 0. */ Uc_symbol *Uc_scope::search_up ( char *nm ) { Uc_symbol *found = search(nm); // First look here. if (found) return found; if (parent) // Look upwards. return parent->search_up(nm); else return 0; } /* * Add a function symbol. * * Output: 0 if already there. Errors reported. */ int Uc_scope::add_function_symbol ( Uc_function_symbol *fun ) { char buf[150]; const char *nm = fun->get_name(); Uc_symbol *found = search(nm); // Already here? if (!found) // If not, that's good. { add(fun); return 1; } Uc_function_symbol *fun2 = dynamic_cast (found); if (!fun2) // Non-function name. { sprintf(buf, "'%s' already declared", nm); Uc_location::yyerror(buf); } else if (fun->get_usecode_num() != fun2->get_usecode_num() || fun->get_num_parms() != fun2->get_num_parms()) { sprintf(buf, "Decl. of '%s' doesn't match previous decl", nm); Uc_location::yyerror(buf); } return 0; } exult-1.2/usecode/compiler/ucparse.cc0000644000175000001440000024621710013577452013424 /* A Bison parser, made from ucparse.yy by GNU bison 1.35. */ #define YYBISON 1 /* Identify Bison output. */ # define IF 257 # define ELSE 258 # define RETURN 259 # define WHILE 260 # define FOR 261 # define UCC_IN 262 # define WITH 263 # define TO 264 # define EXTERN 265 # define BREAK 266 # define GOTO 267 # define CASE 268 # define VAR 269 # define UCC_INT 270 # define UCC_CONST 271 # define STRING 272 # define ENUM 273 # define CONVERSE 274 # define SAY 275 # define MESSAGE 276 # define RESPONSE 277 # define EVENT 278 # define FLAG 279 # define ITEM 280 # define UCTRUE 281 # define UCFALSE 282 # define REMOVE 283 # define ADD 284 # define HIDE 285 # define SCRIPT 286 # define AFTER 287 # define TICKS 288 # define STATIC_ 289 # define ORIGINAL 290 # define CONTINUE 291 # define REPEAT 292 # define NOP 293 # define NOHALT 294 # define WAIT 295 # define RISE 296 # define DESCEND 297 # define FRAME 298 # define HATCH 299 # define NEXT 300 # define PREVIOUS 301 # define CYCLE 302 # define STEP 303 # define MUSIC 304 # define CALL 305 # define SPEECH 306 # define SFX 307 # define FACE 308 # define HIT 309 # define HOURS 310 # define ACTOR 311 # define NORTH 312 # define SOUTH 313 # define EAST 314 # define WEST 315 # define NE 316 # define NW 317 # define SE 318 # define SW 319 # define STRING_LITERAL 320 # define STRING_PREFIX 321 # define IDENTIFIER 322 # define INT_LITERAL 323 # define AND 324 # define OR 325 # define EQUALS 326 # define NEQUALS 327 # define LTEQUALS 328 # define GTEQUALS 329 # define NOT 330 # define UCC_POINTS 331 #line 1 "ucparse.yy" /** ** Ucparse.y - Usecode parser. ** ** Written: 12/30/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "ucfun.h" #include "ucexpr.h" #include "ucstmt.h" #include "opcodes.h" #include "ucscriptop.h" using std::strcpy; using std::strcat; using std::strlen; void yyerror(char *); extern int yylex(); static Uc_array_expression *Create_array(int, Uc_expression *); static Uc_array_expression *Create_array(int, Uc_expression *, Uc_expression *); #define YYERROR_VERBOSE 1 std::vector functions; // THIS is what we produce. static Uc_function *function = 0; // Current function being parsed. static int enum_val = -1; // Keeps track of enum elements. #line 61 "ucparse.yy" #ifndef YYSTYPE typedef union { class Uc_symbol *sym; class Uc_var_symbol *var; class Uc_expression *expr; class Uc_call_expression *funcall; class Uc_function_symbol *funsym; class Uc_statement *stmt; class std::vector *strvec; class Uc_block_statement *block; class Uc_arrayloop_statement *arrayloop; class Uc_array_expression *exprlist; int intval; char *strval; } yystype; # define YYSTYPE yystype # define YYSTYPE_IS_TRIVIAL 1 #endif #ifndef YYDEBUG # define YYDEBUG 0 #endif #define YYFINAL 374 #define YYFLAG -32768 #define YYNTBASE 97 /* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ #define YYTRANSLATE(x) ((unsigned)(x) <= 331 ? yytranslate[x] : 167) /* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 83, 80, 2, 86, 87, 81, 79, 91, 78, 96, 82, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 93, 90, 76, 92, 77, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 84, 85 }; #if YYDEBUG static const short yyprhs[] = { 0, 0, 3, 5, 7, 9, 11, 13, 15, 16, 20, 27, 29, 30, 31, 36, 39, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 76, 82, 84, 86, 90, 94, 96, 98, 100, 102, 106, 108, 109, 117, 121, 123, 125, 127, 132, 136, 138, 142, 144, 148, 153, 155, 159, 161, 165, 167, 171, 175, 180, 186, 194, 200, 204, 205, 212, 213, 214, 224, 229, 232, 235, 243, 250, 254, 257, 260, 268, 271, 272, 278, 282, 283, 288, 290, 293, 295, 298, 303, 306, 309, 313, 318, 321, 324, 327, 331, 336, 339, 343, 348, 352, 357, 361, 365, 369, 373, 377, 383, 387, 391, 395, 399, 403, 405, 407, 409, 411, 413, 415, 417, 419, 421, 425, 426, 429, 432, 435, 441, 447, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 509, 513, 516, 519, 523, 525, 527, 529, 530, 534, 536, 538, 540, 545, 550, 552, 554, 556, 558, 560, 564, 566, 568, 572, 574, 576, 582, 584, 585, 587, 588, 593, 596, 598, 600, 602, 603, 605, 607 }; static const short yyrhs[] = { 97, 98, 0, 98, 0, 99, 0, 122, 0, 113, 0, 109, 0, 117, 0, 0, 101, 100, 103, 0, 163, 68, 102, 86, 160, 87, 0, 162, 0, 0, 0, 88, 104, 105, 89, 0, 105, 106, 0, 0, 107, 0, 123, 0, 124, 0, 125, 0, 126, 0, 132, 0, 133, 0, 134, 0, 103, 0, 135, 0, 136, 0, 140, 0, 147, 0, 148, 0, 149, 0, 21, 86, 152, 87, 90, 0, 22, 86, 152, 87, 90, 0, 150, 0, 90, 0, 15, 108, 90, 0, 18, 120, 90, 0, 113, 0, 109, 0, 122, 0, 117, 0, 108, 91, 116, 0, 116, 0, 0, 19, 68, 110, 88, 111, 89, 90, 0, 111, 91, 112, 0, 112, 0, 115, 0, 68, 0, 17, 16, 114, 90, 0, 114, 91, 115, 0, 115, 0, 68, 92, 151, 0, 68, 0, 68, 92, 151, 0, 35, 15, 118, 90, 0, 119, 0, 118, 91, 119, 0, 68, 0, 120, 91, 121, 0, 121, 0, 68, 92, 66, 0, 11, 101, 90, 0, 151, 92, 151, 90, 0, 3, 86, 151, 87, 106, 0, 3, 86, 151, 87, 106, 4, 106, 0, 6, 86, 151, 87, 106, 0, 130, 87, 106, 0, 0, 130, 9, 68, 127, 87, 106, 0, 0, 0, 130, 9, 68, 128, 10, 68, 129, 87, 106, 0, 131, 68, 8, 165, 0, 7, 86, 0, 155, 90, 0, 154, 157, 21, 86, 152, 87, 90, 0, 154, 157, 31, 86, 87, 90, 0, 5, 151, 90, 0, 5, 90, 0, 20, 106, 0, 20, 86, 151, 87, 88, 137, 89, 0, 137, 138, 0, 0, 14, 66, 139, 93, 105, 0, 86, 29, 87, 0, 0, 32, 141, 146, 143, 0, 151, 0, 142, 143, 0, 143, 0, 37, 90, 0, 38, 151, 143, 90, 0, 39, 90, 0, 40, 90, 0, 41, 151, 90, 0, 41, 151, 56, 90, 0, 29, 90, 0, 42, 90, 0, 43, 90, 0, 44, 151, 90, 0, 57, 44, 162, 90, 0, 45, 90, 0, 46, 44, 90, 0, 46, 44, 48, 90, 0, 47, 44, 90, 0, 47, 44, 48, 90, 0, 21, 151, 90, 0, 49, 151, 90, 0, 49, 144, 90, 0, 50, 151, 90, 0, 51, 151, 90, 0, 51, 151, 91, 145, 90, 0, 52, 151, 90, 0, 53, 151, 90, 0, 54, 151, 90, 0, 55, 151, 90, 0, 88, 142, 89, 0, 58, 0, 62, 0, 60, 0, 64, 0, 59, 0, 65, 0, 61, 0, 63, 0, 162, 0, 33, 151, 34, 0, 0, 12, 90, 0, 68, 93, 0, 13, 68, 0, 30, 86, 153, 87, 90, 0, 29, 86, 153, 87, 90, 0, 154, 0, 151, 79, 151, 0, 151, 78, 151, 0, 151, 81, 151, 0, 151, 82, 151, 0, 151, 83, 151, 0, 151, 72, 151, 0, 23, 72, 151, 0, 151, 73, 151, 0, 151, 76, 151, 0, 151, 74, 151, 0, 151, 77, 151, 0, 151, 75, 151, 0, 151, 70, 151, 0, 151, 71, 151, 0, 151, 8, 151, 0, 151, 80, 151, 0, 78, 154, 0, 84, 154, 0, 94, 153, 95, 0, 66, 0, 67, 0, 153, 0, 0, 153, 91, 151, 0, 151, 0, 69, 0, 164, 0, 165, 94, 151, 95, 0, 25, 94, 162, 95, 0, 155, 0, 27, 0, 28, 0, 24, 0, 26, 0, 86, 151, 87, 0, 158, 0, 156, 0, 154, 157, 158, 0, 85, 0, 96, 0, 68, 159, 86, 152, 87, 0, 36, 0, 0, 161, 0, 0, 161, 91, 163, 68, 0, 163, 68, 0, 69, 0, 166, 0, 15, 0, 0, 166, 0, 166, 0, 68, 0 }; #endif #if YYDEBUG /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const short yyrline[] = { 0, 140, 142, 145, 147, 152, 153, 154, 157, 157, 169, 177, 179, 183, 183, 193, 199, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 221, 223, 224, 228, 231, 233, 235, 237, 243, 247, 267, 271, 271, 275, 277, 280, 282, 292, 296, 298, 301, 317, 323, 331, 335, 337, 340, 350, 352, 355, 362, 367, 372, 375, 379, 384, 391, 391, 399, 399, 399, 410, 418, 423, 428, 441, 449, 452, 456, 461, 466, 472, 476, 484, 487, 491, 507, 511, 514, 521, 524, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 577, 579, 581, 583, 585, 589, 592, 594, 596, 598, 600, 602, 604, 608, 612, 615, 619, 624, 642, 647, 654, 662, 665, 667, 669, 671, 673, 675, 677, 679, 681, 683, 685, 687, 689, 691, 693, 695, 697, 700, 702, 704, 706, 710, 712, 716, 719, 726, 729, 731, 733, 735, 737, 739, 741, 743, 745, 749, 751, 754, 762, 764, 767, 784, 787, 791, 793, 797, 800, 807, 809, 825, 827, 830, 844, 860 }; #endif #if (YYDEBUG) || defined YYERROR_VERBOSE /* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ static const char *const yytname[] = { "$", "error", "$undefined.", "IF", "ELSE", "RETURN", "WHILE", "FOR", "UCC_IN", "WITH", "TO", "EXTERN", "BREAK", "GOTO", "CASE", "VAR", "UCC_INT", "UCC_CONST", "STRING", "ENUM", "CONVERSE", "SAY", "MESSAGE", "RESPONSE", "EVENT", "FLAG", "ITEM", "UCTRUE", "UCFALSE", "REMOVE", "ADD", "HIDE", "SCRIPT", "AFTER", "TICKS", "STATIC_", "ORIGINAL", "CONTINUE", "REPEAT", "NOP", "NOHALT", "WAIT", "RISE", "DESCEND", "FRAME", "HATCH", "NEXT", "PREVIOUS", "CYCLE", "STEP", "MUSIC", "CALL", "SPEECH", "SFX", "FACE", "HIT", "HOURS", "ACTOR", "NORTH", "SOUTH", "EAST", "WEST", "NE", "NW", "SE", "SW", "STRING_LITERAL", "STRING_PREFIX", "IDENTIFIER", "INT_LITERAL", "AND", "OR", "EQUALS", "NEQUALS", "LTEQUALS", "GTEQUALS", "'<'", "'>'", "'-'", "'+'", "'&'", "'*'", "'/'", "'%'", "NOT", "UCC_POINTS", "'('", "')'", "'{'", "'}'", "';'", "','", "'='", "':'", "'['", "']'", "'.'", "design", "global_decl", "function", "@1", "function_proto", "opt_int", "statement_block", "@2", "statement_list", "statement", "declaration", "var_decl_list", "enum_decl", "@3", "enum_item_list", "enum_item", "const_int_decl", "const_int_decl_list", "const_int", "var_decl", "static_decl", "static_var_decl_list", "static_var", "string_decl_list", "string_decl", "function_decl", "assignment_statement", "if_statement", "while_statement", "array_loop_statement", "@4", "@5", "@6", "start_array_loop", "start_for", "function_call_statement", "special_method_call_statement", "return_statement", "converse_statement", "converse2_statement", "converse_case_list", "converse_case", "converse_options", "script_statement", "item", "script_command_list", "script_command", "direction", "eventid", "opt_script_delay", "break_statement", "label_statement", "goto_statement", "answer_statement", "expression", "opt_expression_list", "expression_list", "primary", "function_call", "method_call", "hierarchy_tok", "routine_call", "opt_original", "opt_identifier_list", "identifier_list", "int_literal", "opt_var", "declared_var_value", "declared_var", "declared_sym", 0 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const short yyr1[] = { 0, 97, 97, 98, 98, 98, 98, 98, 100, 99, 101, 102, 102, 104, 103, 105, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 108, 108, 110, 109, 111, 111, 112, 112, 113, 114, 114, 115, 116, 116, 117, 118, 118, 119, 120, 120, 121, 122, 123, 124, 124, 125, 126, 127, 126, 128, 129, 126, 130, 131, 132, 133, 133, 134, 134, 135, 136, 137, 137, 138, 139, 139, 140, 141, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 145, 146, 146, 147, 148, 149, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 153, 153, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 155, 155, 156, 157, 157, 158, 159, 159, 160, 160, 161, 161, 162, 162, 163, 163, 164, 165, 166 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const short yyr2[] = { 0, 2, 1, 1, 1, 1, 1, 1, 0, 3, 6, 1, 0, 0, 4, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 1, 1, 3, 3, 1, 1, 1, 1, 3, 1, 0, 7, 3, 1, 1, 1, 4, 3, 1, 3, 1, 3, 4, 1, 3, 1, 3, 1, 3, 3, 4, 5, 7, 5, 3, 0, 6, 0, 0, 9, 4, 2, 2, 7, 6, 3, 2, 2, 7, 2, 0, 5, 3, 0, 4, 1, 2, 1, 2, 4, 2, 2, 3, 4, 2, 2, 2, 3, 4, 2, 3, 4, 3, 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 2, 2, 2, 5, 5, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 1, 1, 1, 0, 3, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 5, 1, 0, 1, 0, 4, 2, 1, 1, 1, 0, 1, 1, 1 }; /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const short yydefact[] = { 186, 186, 185, 0, 0, 0, 186, 2, 3, 8, 6, 5, 7, 4, 0, 0, 0, 44, 0, 1, 0, 12, 63, 0, 0, 52, 0, 59, 0, 57, 13, 9, 189, 183, 0, 11, 184, 0, 50, 0, 0, 56, 0, 16, 180, 0, 168, 0, 169, 166, 167, 155, 156, 189, 161, 0, 0, 0, 0, 53, 135, 165, 172, 171, 162, 0, 187, 51, 49, 0, 47, 48, 58, 0, 0, 179, 0, 0, 0, 177, 0, 152, 153, 0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 14, 35, 25, 15, 17, 39, 38, 41, 40, 18, 19, 20, 21, 0, 0, 22, 23, 24, 26, 27, 28, 29, 30, 31, 34, 0, 135, 165, 10, 186, 182, 142, 0, 158, 170, 0, 154, 150, 148, 149, 141, 143, 145, 147, 144, 146, 137, 136, 151, 138, 139, 140, 178, 173, 0, 45, 46, 0, 80, 0, 0, 75, 130, 132, 54, 0, 43, 0, 0, 61, 0, 81, 158, 158, 0, 0, 129, 89, 131, 0, 0, 0, 0, 0, 76, 0, 164, 0, 157, 159, 163, 0, 79, 0, 0, 36, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, 181, 176, 0, 0, 55, 42, 62, 60, 170, 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, 88, 0, 0, 74, 188, 64, 158, 0, 65, 67, 84, 32, 33, 134, 133, 128, 0, 98, 92, 0, 94, 95, 0, 99, 100, 0, 103, 0, 0, 119, 123, 121, 125, 120, 126, 122, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 108, 0, 0, 96, 101, 0, 104, 0, 106, 110, 109, 111, 112, 0, 114, 115, 116, 117, 0, 118, 90, 70, 72, 0, 78, 66, 0, 82, 83, 93, 97, 105, 107, 0, 127, 102, 0, 77, 87, 113, 0, 0, 0, 73, 0, 16, 86, 85, 0, 0 }; static const short yydefgoto[] = { 6, 7, 8, 20, 9, 34, 124, 43, 73, 125, 126, 187, 127, 26, 69, 70, 128, 24, 71, 188, 129, 28, 29, 190, 191, 130, 131, 132, 133, 134, 272, 273, 361, 135, 136, 137, 138, 139, 140, 141, 324, 353, 367, 142, 198, 317, 271, 308, 358, 228, 143, 144, 145, 146, 147, 209, 210, 60, 61, 62, 103, 63, 80, 74, 75, 35, 14, 64, 65, 66 }; static const short yypact[] = { 98, 53,-32768, 91, 14, 99, 101,-32768,-32768,-32768, -32768,-32768,-32768,-32768, 51, 32, 76,-32768, 103,-32768, 81, -3,-32768, 35, 40,-32768, 84,-32768, 44,-32768, -32768,-32768,-32768,-32768, 87,-32768,-32768, 936,-32768, 76, 107,-32768, 103,-32768, 27, 104,-32768, 85,-32768,-32768, -32768,-32768,-32768, -14,-32768, 22, 22, 936, 936, 868, -33,-32768,-32768,-32768,-32768, 86, 90,-32768, 35, -35, -32768,-32768,-32768, 8, 94, 96, 109, 936, -3,-32768, 92, -33, -33, 788, 868, -38, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936,-32768,-32768, 117, 936, 112, 107, 119, 206, 120, 121, 113, 136, 140, 141, 333, 125, 129, 130, 131, 936, -24,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768, 0, 150,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768, 299, -33, 132, -32768, 53,-32768, 59, 124, 936,-32768, 936,-32768, 59, 581, 581, 59, 59, 59, 59, 59, 59, 23, 23, 23,-32768,-32768,-32768, 184,-32768, 118,-32768,-32768, 936, -32768, 465, 936,-32768,-32768,-32768, 133, 58,-32768, 134, 60,-32768, 936,-32768, 936, 936, 936, 936, 191, 868, -32768, 159, 419, 220, 936, 20,-32768, 167,-32768, 149, 146, 868,-32768, 809,-32768, 827, 936,-32768, 140, 172, -32768, 141, 845, 152, 153, -7, 34, 936, 1022, 231, -32768, 174, 486, 158, 160,-32768,-32768, 419, 419, 868, -32768,-32768,-32768, 162, 157, 161, 164, 165, 903, 936, 169, 176, 936, 177, 179, 936, 181, 186, 936, 187, 208, 213, 929, 936, 936, 936, 936, 936, 936, 234, 1022,-32768, 192, 270,-32768,-32768,-32768, 936, 194, 279, -32768,-32768,-32768,-32768,-32768,-32768,-32768, 520,-32768,-32768, 769,-32768,-32768, 444,-32768,-32768, 541,-32768, -9, 10, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 195, 562, 596, 385, 617, 638, 672, 693, -3, 995,-32768, 419, 218, 200, 198, 419, -4,-32768, 199, 201,-32768,-32768, 204,-32768, 209,-32768,-32768,-32768,-32768,-32768, -3,-32768, -32768,-32768,-32768, 211,-32768,-32768,-32768,-32768, 214,-32768, -32768, 232,-32768,-32768,-32768,-32768,-32768,-32768, 215,-32768, -32768, 216,-32768, 222,-32768, 419, 277, 219,-32768, 224, -32768,-32768, 419, 309,-32768 }; static const short yypgoto[] = { -32768, 307,-32768,-32768, 313,-32768, 296,-32768, -50, -109, -32768,-32768, 61,-32768,-32768, 217, 64,-32768, 39, 108, 73,-32768, 280,-32768, 106, 83,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768, -246,-32768,-32768,-32768, -32768,-32768,-32768,-32768, 66, -178, -51, -55, -70,-32768, 189, -95,-32768,-32768,-32768, -73, -40,-32768, 110, -19 }; #define YYLAST 1110 static const short yytable[] = { 81, 82, 36, 149, 76, 154, 193, 85, 175, 201, 351, 107, 79, 108, 109, 110, 223, 224, 148, 1, 111, 112, 79, 113, 318, 3, 114, 4, 115, 116, 117, 45, 46, 47, 48, 49, 50, 118, 119, 330, 120, 233, 2, 5, 326, 149, 46, 47, 48, 49, 50, 234, 101, 157, 105, 25, 106, 158, 332, 36, 148, 10, -178, 102, 11, 32, 33, 10, 2, 200, 11, 345, -178, 12, 51, 52, 121, 54, 67, 12, 246, 331, 17, 13, 157, 352, 55, 202, 174, 13, 53, 54, 56, 230, 57, -186, 30, 122, 123, 321, 333, 373, 58, 59, 98, 99, 100, 16, 57, 1, 175, 207, 1, 2, 18, 3, 2, 4, 3, 21, 4, 247, 22, 83, 84, 157, 86, 37, 279, 280, 38, 39, 149, 5, 41, 42, 5, 95, 96, 97, 98, 99, 100, 153, 23, 225, 226, 148, 217, 218, 220, 221, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 149, 149, 30, 176, 27, 40, 44, 181, 68, 77, 152, 155, 78, 104, 150, 148, 148, -188, 174, 199, 151, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 177, 184, 185, 179, 182, 183, 186, 189, 346, 194, 275, 212, 350, 195, 196, 197, 203, 208, 79, 84, 206, 211, 227, 216, 219, 229, 231, 45, 46, 47, 48, 49, 50, 235, 236, 157, 241, 244, 245, -71, 32, 343, 277, 213, 278, 282, 215, 149, 281, 283, 298, 149, 284, 285, 368, 299, 222, 288, 84, 84, 84, 84, 148, 359, 289, 291, 148, 292, 232, 294, 51, 52, 53, 54, 295, 297, 316, 319, 320, 322, 239, 323, 55, 334, 347, 348, 349, 354, 56, 355, 57, 248, 356, 149, 180, 36, 363, 357, 58, 360, 149, 365, 362, 364, 369, 86, 366, 374, 148, 371, 370, 19, 15, 287, 31, 148, 290, 36, 372, 293, 72, 178, 296, 0, 240, 242, 309, 310, 311, 312, 313, 314, 315, 0, 107, 205, 108, 109, 110, 274, 0, 84, 1, 111, 112, 0, 113, 0, 3, 114, 4, 115, 116, 117, 45, 46, 47, 48, 49, 50, 118, 119, 0, 120, 0, 0, 5, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 86, 0, 0, 0, 0, 0, 51, 52, 121, 54, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 56, 0, 192, 0, 30, 107, 123, 108, 109, 110, 58, 0, 0, 1, 111, 112, 0, 113, 0, 3, 114, 4, 115, 116, 117, 45, 46, 47, 48, 49, 50, 118, 119, 0, 120, 86, 0, 5, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 0, 86, 0, 337, 338, 0, 0, 0, 0, 0, 0, 0, 0, 51, 52, 121, 54, 0, 0, 0, 0, 0, 86, 0, 0, 55, 0, 0, 327, 0, 0, 56, 0, 57, 0, 30, 0, 123, 0, 0, 0, 58, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 328, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 214, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 325, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 329, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 335, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 336, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 339, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 0, 0, 0, 341, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 0, 0, 342, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 86, 0, 250, 0, 0, 0, 0, 0, 0, 0, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 86, 262, 263, 264, 265, 266, 267, 268, 0, 269, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 0, 270, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 156, 86, 0, 0, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 237, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 86, 0, 0, 238, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 0, 0, 243, 0, 0, 0, 0, 286, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 45, 46, 47, 48, 49, 50, 0, 45, 46, 47, 48, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 300, 301, 302, 303, 304, 305, 306, 307, 51, 52, 53, 54, 0, 0, 0, 51, 52, 53, 54, 0, 55, 0, 0, 0, 0, 0, 56, 55, 57, 249, 0, 0, 0, 56, 0, 57, 58, 250, 0, 0, 0, 0, 0, 58, 0, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 249, 262, 263, 264, 265, 266, 267, 268, 250, 269, 0, 0, 0, 0, 0, 0, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 0, 262, 263, 264, 265, 266, 267, 268, 0, 269, 0, 0, 0, 270, 344, 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, 270 }; static const short yycheck[] = { 55, 56, 21, 73, 44, 78, 115, 58, 103, 9, 14, 3, 36, 5, 6, 7, 194, 195, 73, 11, 12, 13, 36, 15, 270, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 48, 32, 21, 15, 35, 290, 115, 24, 25, 26, 27, 28, 31, 85, 91, 89, 16, 91, 95, 48, 78, 115, 0, 86, 96, 0, 68, 69, 6, 15, 93, 6, 317, 86, 0, 66, 67, 68, 69, 39, 6, 87, 90, 68, 0, 91, 89, 78, 87, 68, 6, 68, 69, 84, 202, 86, 68, 88, 89, 90, 277, 90, 0, 94, 37, 81, 82, 83, 16, 86, 11, 205, 151, 11, 15, 15, 17, 15, 19, 17, 68, 19, 87, 90, 57, 58, 91, 8, 92, 237, 238, 90, 91, 202, 35, 90, 91, 35, 78, 79, 80, 81, 82, 83, 77, 68, 196, 197, 202, 90, 91, 90, 91, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 237, 238, 88, 104, 68, 88, 86, 108, 68, 72, 68, 86, 94, 94, 87, 237, 238, 94, 68, 120, 91, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 90, 90, 68, 86, 86, 86, 68, 68, 319, 86, 231, 95, 323, 86, 86, 86, 68, 95, 36, 155, 90, 157, 33, 92, 92, 68, 8, 23, 24, 25, 26, 27, 28, 68, 87, 91, 66, 87, 87, 10, 68, 316, 86, 179, 86, 90, 182, 319, 88, 90, 44, 323, 90, 90, 365, 44, 192, 90, 194, 195, 196, 197, 319, 338, 90, 90, 323, 90, 204, 90, 66, 67, 68, 69, 90, 90, 44, 87, 10, 87, 216, 4, 78, 90, 68, 87, 90, 90, 84, 90, 86, 227, 90, 365, 90, 316, 66, 90, 94, 90, 372, 87, 90, 90, 29, 8, 86, 0, 365, 87, 93, 6, 1, 249, 20, 372, 252, 338, 370, 255, 42, 106, 258, -1, 218, 221, 262, 263, 264, 265, 266, 267, 268, -1, 3, 148, 5, 6, 7, 231, -1, 277, 11, 12, 13, -1, 15, -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1, 32, -1, -1, 35, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, -1, -1, -1, -1, -1, 92, -1, 8, -1, -1, -1, -1, -1, 66, 67, 68, 69, -1, -1, -1, -1, -1, -1, -1, -1, 78, -1, -1, -1, -1, -1, 84, -1, 86, -1, 88, 3, 90, 5, 6, 7, 94, -1, -1, 11, 12, 13, -1, 15, -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1, 32, 8, -1, 35, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, -1, 8, -1, 90, 91, -1, -1, -1, -1, -1, -1, -1, -1, 66, 67, 68, 69, -1, -1, -1, -1, -1, 8, -1, -1, 78, -1, -1, 56, -1, -1, 84, -1, 86, -1, 88, -1, 90, -1, -1, -1, 94, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, -1, -1, -1, 90, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, 8, -1, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 8, 49, 50, 51, 52, 53, 54, 55, -1, 57, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, -1, 88, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, 87, 8, -1, -1, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, 87, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 8, -1, -1, 87, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 34, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 23, 24, 25, 26, 27, 28, -1, 23, 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -1, -1, -1, 66, 67, 68, 69, -1, 78, -1, -1, -1, -1, -1, 84, 78, 86, 21, -1, -1, -1, 84, -1, 86, 94, 29, -1, -1, -1, -1, -1, 94, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 21, 49, 50, 51, 52, 53, 54, 55, 29, 57, -1, -1, -1, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -1, 49, 50, 51, 52, 53, 54, 55, -1, 57, -1, -1, -1, 88, 89, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 88 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/share/bison/bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ #if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) /* The parser invokes alloca or malloc; define the necessary symbols. */ # if YYSTACK_USE_ALLOCA # define YYSTACK_ALLOC alloca # else # ifndef YYSTACK_USE_ALLOCA # if defined (alloca) || defined (_ALLOCA_H) # define YYSTACK_ALLOC alloca # else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif # define YYSTACK_ALLOC malloc # define YYSTACK_FREE free # endif #endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short yyss; YYSTYPE yyvs; # if YYLSP_NEEDED YYLTYPE yyls; # endif }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # if YYLSP_NEEDED # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAX) # else # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAX) # endif /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror ("syntax error: cannot back up"); \ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Compute the default location (before the actions are run). When YYLLOC_DEFAULT is run, CURRENT is set the location of the first token. By default, to implement support for ranges, extend its range to the last symbol. */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ Current.last_line = Rhs[N].last_line; \ Current.last_column = Rhs[N].last_column; #endif /* YYLEX -- calling `yylex' with the right arguments. */ #if YYPURE # if YYLSP_NEEDED # ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) # else # define YYLEX yylex (&yylval, &yylloc) # endif # else /* !YYLSP_NEEDED */ # ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) # else # define YYLEX yylex (&yylval) # endif # endif /* !YYLSP_NEEDED */ #else /* !YYPURE */ # define YYLEX yylex () #endif /* !YYPURE */ /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #if YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #ifdef YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { register const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { register char *yyd = yydest; register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif #endif #line 315 "/usr/share/bison/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) # define YYPARSE_PARAM_ARG void *YYPARSE_PARAM # define YYPARSE_PARAM_DECL # else # define YYPARSE_PARAM_ARG YYPARSE_PARAM # define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; # endif #else /* !YYPARSE_PARAM */ # define YYPARSE_PARAM_ARG # define YYPARSE_PARAM_DECL #endif /* !YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ # ifdef YYPARSE_PARAM int yyparse (void *); # else int yyparse (void); # endif #endif /* YY_DECL_VARIABLES -- depending whether we use a pure parser, variables are global, or local to YYPARSE. */ #define YY_DECL_NON_LSP_VARIABLES \ /* The lookahead symbol. */ \ int yychar; \ \ /* The semantic value of the lookahead symbol. */ \ YYSTYPE yylval; \ \ /* Number of parse errors so far. */ \ int yynerrs; #if YYLSP_NEEDED # define YY_DECL_VARIABLES \ YY_DECL_NON_LSP_VARIABLES \ \ /* Location data for the lookahead symbol. */ \ YYLTYPE yylloc; #else # define YY_DECL_VARIABLES \ YY_DECL_NON_LSP_VARIABLES #endif /* If nonreentrant, generate the variables here. */ #if !YYPURE YY_DECL_VARIABLES #endif /* !YYPURE */ int yyparse (YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { /* If reentrant, generate the variables here. */ #if YYPURE YY_DECL_VARIABLES #endif /* !YYPURE */ register int yystate; register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ int yychar1 = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short yyssa[YYINITDEPTH]; short *yyss = yyssa; register short *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; #if YYLSP_NEEDED /* The location stack. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #endif #if YYLSP_NEEDED # define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else # define YYPOPSTACK (yyvsp--, yyssp--) #endif YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYLSP_NEEDED YYLTYPE yyloc; #endif /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; #if YYLSP_NEEDED yylsp = yyls; #endif goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ # if YYLSP_NEEDED YYLTYPE *yyls1 = yyls; /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); yyls = yyls1; # else yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); # endif yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyoverflowlab; # else /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) goto yyoverflowlab; yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; { short *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # if YYLSP_NEEDED YYSTACK_RELOCATE (yyls); # endif # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; #if YYLSP_NEEDED yylsp = yyls + yysize - 1; #endif YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyssp >= yyss + yystacksize - 1) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yychar1 = YYTRANSLATE (yychar); #if YYDEBUG /* We have to keep this `#if YYDEBUG', since we use variables which are defined only if `YYDEBUG' is set. */ if (yydebug) { YYFPRINTF (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ # ifdef YYPRINT YYPRINT (stderr, yychar, yylval); # endif YYFPRINTF (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ YYDPRINTF ((stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #if YYLSP_NEEDED *++yylsp = yylloc; #endif /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to the semantic value of the lookahead token. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; #if YYLSP_NEEDED /* Similarly for the default location. Let the user run additional commands if for instance locations are ranges. */ yyloc = yylsp[1-yylen]; YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); #endif #if YYDEBUG /* We have to keep this `#if YYDEBUG', since we use variables which are defined only if `YYDEBUG' is set. */ if (yydebug) { int yyi; YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 4: #line 148 "ucparse.yy" { if (!Uc_function::add_global_function_symbol(yyvsp[0].funsym)) delete yyvsp[0].funsym; } break; case 8: #line 159 "ucparse.yy" { function = new Uc_function(yyvsp[0].funsym); } break; case 9: #line 161 "ucparse.yy" { function->set_statement(yyvsp[0].stmt); functions.push_back(function); function = 0; } break; case 10: #line 171 "ucparse.yy" { yyval.funsym = new Uc_function_symbol(yyvsp[-4].strval, yyvsp[-3].intval, *yyvsp[-1].strvec); delete yyvsp[-1].strvec; // A copy was made. } break; case 12: #line 180 "ucparse.yy" { yyval.intval = -1; } break; case 13: #line 185 "ucparse.yy" { function->push_scope(); } break; case 14: #line 187 "ucparse.yy" { yyval.stmt = yyvsp[-1].block; function->pop_scope(); } break; case 15: #line 195 "ucparse.yy" { if (yyvsp[0].stmt) yyval.block->add(yyvsp[0].stmt); } break; case 16: #line 200 "ucparse.yy" { yyval.block = new Uc_block_statement(); } break; case 32: #line 220 "ucparse.yy" { yyval.stmt = new Uc_say_statement(yyvsp[-2].exprlist); } break; case 33: #line 222 "ucparse.yy" { yyval.stmt = new Uc_message_statement(yyvsp[-2].exprlist); } break; case 35: #line 225 "ucparse.yy" { yyval.stmt = 0; } break; case 36: #line 230 "ucparse.yy" { yyval.stmt = yyvsp[-1].stmt; } break; case 37: #line 232 "ucparse.yy" { yyval.stmt = 0; } break; case 38: #line 234 "ucparse.yy" { yyval.stmt = 0; } break; case 39: #line 236 "ucparse.yy" { yyval.stmt = 0; } break; case 40: #line 238 "ucparse.yy" { if (!function->add_function_symbol(yyvsp[0].funsym)) delete yyvsp[0].funsym; yyval.stmt = 0; } break; case 41: #line 244 "ucparse.yy" { yyval.stmt = 0; } break; case 42: #line 249 "ucparse.yy" { if (!yyvsp[0].stmt) yyval.stmt = yyvsp[-2].stmt; else if (!yyvsp[-2].stmt) yyval.stmt = yyvsp[0].stmt; else /* Both nonzero. Need a list. */ { Uc_block_statement *b = dynamic_cast(yyvsp[-2].stmt); if (!b) { b = new Uc_block_statement(); b->add(yyvsp[-2].stmt); } b->add(yyvsp[0].stmt); yyval.stmt = b; } } break; case 43: #line 268 "ucparse.yy" { yyval.stmt = yyvsp[0].stmt; } break; case 44: #line 272 "ucparse.yy" { enum_val = -1; } break; case 49: #line 283 "ucparse.yy" { /* Increment last value. */ ++enum_val; if (function) function->add_int_const_symbol(yyvsp[0].strval, enum_val); else // Global. Uc_function::add_global_int_const_symbol(yyvsp[0].strval, enum_val); } break; case 53: #line 303 "ucparse.yy" { int val; // Get constant. if (yyvsp[0].expr->eval_const(val)) { if (function) function->add_int_const_symbol(yyvsp[-2].strval, val); else // Global. Uc_function::add_global_int_const_symbol( yyvsp[-2].strval, val); enum_val = val; // In case we're in an enum. } } break; case 54: #line 319 "ucparse.yy" { function->add_symbol(yyvsp[0].strval); yyval.stmt = 0; } break; case 55: #line 324 "ucparse.yy" { Uc_var_symbol *var = function->add_symbol(yyvsp[-2].strval); yyval.stmt = new Uc_assignment_statement( new Uc_var_expression(var), yyvsp[0].expr); } break; case 59: #line 342 "ucparse.yy" { if (function) function->add_static(yyvsp[0].strval); else Uc_function::add_global_static(yyvsp[0].strval); } break; case 62: #line 357 "ucparse.yy" { function->add_string_symbol(yyvsp[-2].strval, yyvsp[0].strval); } break; case 63: #line 364 "ucparse.yy" { yyval.funsym = yyvsp[-1].funsym; } break; case 64: #line 369 "ucparse.yy" { yyval.stmt = new Uc_assignment_statement(yyvsp[-3].expr, yyvsp[-1].expr); } break; case 65: #line 374 "ucparse.yy" { yyval.stmt = new Uc_if_statement(yyvsp[-2].expr, yyvsp[0].stmt, 0); } break; case 66: #line 376 "ucparse.yy" { yyval.stmt = new Uc_if_statement(yyvsp[-4].expr, yyvsp[-2].stmt, yyvsp[0].stmt); } break; case 67: #line 381 "ucparse.yy" { yyval.stmt = new Uc_while_statement(yyvsp[-2].expr, yyvsp[0].stmt); } break; case 68: #line 386 "ucparse.yy" { yyvsp[-2].arrayloop->set_statement(yyvsp[0].stmt); yyvsp[-2].arrayloop->finish(function); function->pop_scope(); } break; case 69: #line 392 "ucparse.yy" { yyvsp[-2].arrayloop->set_index(function->add_symbol(yyvsp[0].strval)); } break; case 70: #line 394 "ucparse.yy" { yyvsp[-5].arrayloop->set_statement(yyvsp[0].stmt); yyvsp[-5].arrayloop->finish(function); function->pop_scope(); } break; case 71: #line 400 "ucparse.yy" { yyvsp[-2].arrayloop->set_index(function->add_symbol(yyvsp[0].strval)); } break; case 72: #line 402 "ucparse.yy" { yyvsp[-5].arrayloop->set_array_size(function->add_symbol(yyvsp[0].strval)); } break; case 73: #line 404 "ucparse.yy" { yyvsp[-8].arrayloop->set_statement(yyvsp[0].stmt); function->pop_scope(); } break; case 74: #line 412 "ucparse.yy" { Uc_var_symbol *var = function->add_symbol(yyvsp[-2].strval); yyval.arrayloop = new Uc_arrayloop_statement(var, yyvsp[0].var); } break; case 75: #line 420 "ucparse.yy" { function->push_scope(); } break; case 76: #line 425 "ucparse.yy" { yyval.stmt = new Uc_call_statement(yyvsp[-1].funcall); } break; case 77: #line 431 "ucparse.yy" { Uc_block_statement *stmts = new Uc_block_statement(); /* Set up 'show' call. */ stmts->add(new Uc_call_statement( new Uc_call_expression(Uc_function::get_show_face(), new Uc_array_expression(yyvsp[-6].expr, new Uc_int_expression(0)), function))); stmts->add(new Uc_say_statement(yyvsp[-2].exprlist)); yyval.stmt = stmts; } break; case 78: #line 442 "ucparse.yy" { yyval.stmt = new Uc_call_statement( new Uc_call_expression(Uc_function::get_remove_face(), new Uc_array_expression(yyvsp[-5].expr), function)); } break; case 79: #line 451 "ucparse.yy" { yyval.stmt = new Uc_return_statement(yyvsp[-1].expr); } break; case 80: #line 453 "ucparse.yy" { yyval.stmt = new Uc_return_statement(); } break; case 81: #line 458 "ucparse.yy" { yyval.stmt = new Uc_converse_statement(yyvsp[0].stmt); } break; case 82: #line 463 "ucparse.yy" { yyval.stmt = new Uc_converse2_statement(yyvsp[-4].expr, yyvsp[-1].block); } break; case 83: #line 468 "ucparse.yy" { if (yyvsp[0].stmt) yyval.block->add(yyvsp[0].stmt); } break; case 84: #line 473 "ucparse.yy" { yyval.block = new Uc_block_statement(); } break; case 85: #line 478 "ucparse.yy" { yyval.stmt = new Uc_converse_case_statement(function->add_string(yyvsp[-3].strval), (yyvsp[-2].intval ? true : false), yyvsp[0].block); } break; case 86: #line 486 "ucparse.yy" { yyval.intval = 1; } break; case 87: #line 488 "ucparse.yy" { yyval.intval = 0; } break; case 88: #line 493 "ucparse.yy" { Uc_array_expression *parms = new Uc_array_expression(); parms->add(yyvsp[-2].expr); // Itemref. parms->add(yyvsp[0].expr); // Script. if (yyvsp[-1].expr) // Delay? parms->add(yyvsp[-1].expr); // Get the script intrinsic. Uc_symbol *sym = Uc_function::get_intrinsic(yyvsp[-1].expr ? 2 : 1); Uc_call_expression *fcall = new Uc_call_expression(sym, parms, function); yyval.stmt = new Uc_call_statement(fcall); } break; case 90: #line 513 "ucparse.yy" { yyval.exprlist->concat(yyvsp[0].expr); } break; case 91: #line 515 "ucparse.yy" { yyval.exprlist = new Uc_array_expression(); yyval.exprlist->concat(yyvsp[0].expr); } break; case 92: #line 523 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::cont); } break; case 93: #line 525 "ucparse.yy" { Uc_array_expression *result = new Uc_array_expression(); result->concat(yyvsp[-1].expr); // Start with cmnds. to repeat. int sz = result->get_exprs().size(); result->add(new Uc_int_expression(Ucscript::repeat)); // Then -offset to start. result->add(new Uc_int_expression(-sz)); result->add(yyvsp[-2].expr); // Then #times to repeat. yyval.expr = result; } break; case 94: #line 537 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::nop); } break; case 95: #line 539 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::dont_halt); } break; case 96: #line 541 "ucparse.yy" { yyval.expr = Create_array(Ucscript::delay_ticks, yyvsp[-1].expr); } break; case 97: #line 543 "ucparse.yy" { yyval.expr = Create_array(Ucscript::delay_hours, yyvsp[-2].expr); } break; case 98: #line 545 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::remove); } break; case 99: #line 547 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::rise); } break; case 100: #line 549 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::descend); } break; case 101: #line 551 "ucparse.yy" { yyval.expr = Create_array(Ucscript::frame, yyvsp[-1].expr); } break; case 102: #line 553 "ucparse.yy" { yyval.expr = new Uc_int_expression(0x61 + (yyvsp[-1].intval & 15)); } break; case 103: #line 555 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::egg); } break; case 104: #line 557 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::next_frame_max); } break; case 105: #line 559 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::next_frame); } break; case 106: #line 561 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::prev_frame_min); } break; case 107: #line 563 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::prev_frame); } break; case 108: #line 565 "ucparse.yy" { yyval.expr = Create_array(Ucscript::say, yyvsp[-1].expr); } break; case 109: #line 567 "ucparse.yy" { yyval.expr = Create_array(Ucscript::step, yyvsp[-1].expr); } break; case 110: #line 569 "ucparse.yy" { yyval.expr = new Uc_int_expression(Ucscript::step_n + yyvsp[-1].intval); } break; case 111: #line 571 "ucparse.yy" { yyval.expr = Create_array(Ucscript::music, yyvsp[-1].expr); } break; case 112: #line 573 "ucparse.yy" { yyval.expr = Create_array(Ucscript::usecode, yyvsp[-1].expr); } break; case 113: #line 575 "ucparse.yy" { yyval.expr = Create_array(Ucscript::usecode2, yyvsp[-3].expr, new Uc_int_expression(yyvsp[-1].intval)); } break; case 114: #line 578 "ucparse.yy" { yyval.expr = Create_array(Ucscript::speech, yyvsp[-1].expr); } break; case 115: #line 580 "ucparse.yy" { yyval.expr = Create_array(Ucscript::sfx, yyvsp[-1].expr); } break; case 116: #line 582 "ucparse.yy" { yyval.expr = Create_array(Ucscript::face_dir, yyvsp[-1].expr); } break; case 117: #line 584 "ucparse.yy" { yyval.expr = Create_array(Ucscript::hit, yyvsp[-1].expr); } break; case 118: #line 586 "ucparse.yy" { yyval.expr = yyvsp[-1].exprlist; } break; case 119: #line 591 "ucparse.yy" { yyval.intval = 0; } break; case 120: #line 593 "ucparse.yy" { yyval.intval = 1; } break; case 121: #line 595 "ucparse.yy" { yyval.intval = 2; } break; case 122: #line 597 "ucparse.yy" { yyval.intval = 3; } break; case 123: #line 599 "ucparse.yy" { yyval.intval = 4; } break; case 124: #line 601 "ucparse.yy" { yyval.intval = 5; } break; case 125: #line 603 "ucparse.yy" { yyval.intval = 6; } break; case 126: #line 605 "ucparse.yy" { yyval.intval = 7; } break; case 128: #line 614 "ucparse.yy" { yyval.expr = yyvsp[-1].expr; } break; case 129: #line 616 "ucparse.yy" { yyval.expr = 0; } break; case 130: #line 621 "ucparse.yy" { yyval.stmt = new Uc_break_statement(); } break; case 131: #line 626 "ucparse.yy" { Uc_label *label = function->search_label(yyvsp[-1].strval); if (label) { char buf[150]; sprintf(buf, "duplicate label: '%s'", yyvsp[-1].strval); yyerror(buf); yyval.stmt = 0; } else { label = new Uc_label(yyvsp[-1].strval); function->add_label(label); yyval.stmt = new Uc_label_statement(label); } } break; case 132: #line 644 "ucparse.yy" { yyval.stmt = new Uc_goto_statement(yyvsp[0].strval); } break; case 133: #line 649 "ucparse.yy" { yyval.stmt = new Uc_call_statement( new Uc_call_expression(Uc_function::get_add_answer(), yyvsp[-2].exprlist, function)); } break; case 134: #line 655 "ucparse.yy" { yyval.stmt = new Uc_call_statement(new Uc_call_expression( Uc_function::get_remove_answer(), yyvsp[-2].exprlist, function)); } break; case 135: #line 664 "ucparse.yy" { yyval.expr = yyvsp[0].expr; } break; case 136: #line 666 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_ADD, yyvsp[-2].expr, yyvsp[0].expr); } break; case 137: #line 668 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_SUB, yyvsp[-2].expr, yyvsp[0].expr); } break; case 138: #line 670 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_MUL, yyvsp[-2].expr, yyvsp[0].expr); } break; case 139: #line 672 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_DIV, yyvsp[-2].expr, yyvsp[0].expr); } break; case 140: #line 674 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_MOD, yyvsp[-2].expr, yyvsp[0].expr); } break; case 141: #line 676 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPEQ, yyvsp[-2].expr, yyvsp[0].expr); } break; case 142: #line 678 "ucparse.yy" { yyval.expr = new Uc_response_expression(yyvsp[0].expr); } break; case 143: #line 680 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPNE, yyvsp[-2].expr, yyvsp[0].expr); } break; case 144: #line 682 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPL, yyvsp[-2].expr, yyvsp[0].expr); } break; case 145: #line 684 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPLE, yyvsp[-2].expr, yyvsp[0].expr); } break; case 146: #line 686 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPG, yyvsp[-2].expr, yyvsp[0].expr); } break; case 147: #line 688 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_CMPGE, yyvsp[-2].expr, yyvsp[0].expr); } break; case 148: #line 690 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_AND, yyvsp[-2].expr, yyvsp[0].expr); } break; case 149: #line 692 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_OR, yyvsp[-2].expr, yyvsp[0].expr); } break; case 150: #line 694 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_IN, yyvsp[-2].expr, yyvsp[0].expr); } break; case 151: #line 696 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_ARRA, yyvsp[-2].expr, yyvsp[0].expr); } break; case 152: #line 698 "ucparse.yy" { yyval.expr = new Uc_binary_expression(UC_SUB, new Uc_int_expression(0), yyvsp[0].expr); } break; case 153: #line 701 "ucparse.yy" { yyval.expr = new Uc_unary_expression(UC_NOT, yyvsp[0].expr); } break; case 154: #line 703 "ucparse.yy" { yyval.expr = yyvsp[-1].exprlist; } break; case 155: #line 705 "ucparse.yy" { yyval.expr = new Uc_string_expression(function->add_string(yyvsp[0].strval)); } break; case 156: #line 707 "ucparse.yy" { yyval.expr = new Uc_string_prefix_expression(function, yyvsp[0].strval); } break; case 158: #line 713 "ucparse.yy" { yyval.exprlist = new Uc_array_expression(); } break; case 159: #line 718 "ucparse.yy" { yyval.exprlist->add(yyvsp[0].expr); } break; case 160: #line 720 "ucparse.yy" { yyval.exprlist = new Uc_array_expression(); yyval.exprlist->add(yyvsp[0].expr); } break; case 161: #line 728 "ucparse.yy" { yyval.expr = new Uc_int_expression(yyvsp[0].intval); } break; case 162: #line 730 "ucparse.yy" { yyval.expr = yyvsp[0].expr; } break; case 163: #line 732 "ucparse.yy" { yyval.expr = new Uc_arrayelem_expression(yyvsp[-3].var, yyvsp[-1].expr); } break; case 164: #line 734 "ucparse.yy" { yyval.expr = new Uc_flag_expression(yyvsp[-1].intval); } break; case 165: #line 736 "ucparse.yy" { yyval.expr = yyvsp[0].funcall; } break; case 166: #line 738 "ucparse.yy" { yyval.expr = new Uc_bool_expression(true); } break; case 167: #line 740 "ucparse.yy" { yyval.expr = new Uc_bool_expression(false); } break; case 168: #line 742 "ucparse.yy" { yyval.expr = new Uc_event_expression(); } break; case 169: #line 744 "ucparse.yy" { yyval.expr = new Uc_item_expression(); } break; case 170: #line 746 "ucparse.yy" { yyval.expr = yyvsp[-1].expr; } break; case 173: #line 756 "ucparse.yy" { yyvsp[0].funcall->set_itemref(yyvsp[-2].expr); yyval.funcall = yyvsp[0].funcall; } break; case 176: #line 769 "ucparse.yy" { Uc_symbol *sym = function->search_up(yyvsp[-4].strval); if (!sym) { char buf[150]; sprintf(buf, "'%s' not declared", yyvsp[-4].strval); yyerror(buf); yyval.funcall = 0; } else yyval.funcall = new Uc_call_expression(sym, yyvsp[-1].exprlist, function, yyvsp[-3].intval ? true : false); } break; case 177: #line 786 "ucparse.yy" { yyval.intval = 1; } break; case 178: #line 788 "ucparse.yy" { yyval.intval = 0; } break; case 180: #line 794 "ucparse.yy" { yyval.strvec = new std::vector; } break; case 181: #line 799 "ucparse.yy" { yyvsp[-3].strvec->push_back(yyvsp[0].strval); } break; case 182: #line 801 "ucparse.yy" { yyval.strvec = new std::vector; yyval.strvec->push_back(yyvsp[0].strval); } break; case 184: #line 810 "ucparse.yy" { Uc_const_int_symbol *sym = dynamic_cast(yyvsp[0].sym); if (!sym) { char buf[150]; sprintf(buf, "'%s' is not a const int"); yyerror(buf); yyval.intval = 0; } else yyval.intval = sym->get_value(); } break; case 187: #line 832 "ucparse.yy" { yyval.expr = yyvsp[0].sym->create_expression(); if (!yyval.expr) { char buf[150]; sprintf(buf, "Can't use '%s' here", yyvsp[0].sym->get_name()); yyerror(buf); yyval.expr = new Uc_int_expression(0); } } break; case 188: #line 846 "ucparse.yy" { Uc_var_symbol *var = dynamic_cast(yyvsp[0].sym); if (!var) { char buf[150]; sprintf(buf, "'%s' not a 'var'", yyvsp[0].sym); yyerror(buf); sprintf(buf, "%s_needvar", yyvsp[0].sym->get_name()); var = function->add_symbol(buf); } yyval.var = var; } break; case 189: #line 862 "ucparse.yy" { Uc_symbol *sym = function->search_up(yyvsp[0].strval); if (!sym) { char buf[150]; sprintf(buf, "'%s' not declared", yyvsp[0].strval); yyerror(buf); sym = function->add_symbol(yyvsp[0].strval); } yyval.sym = sym; } break; } #line 705 "/usr/share/bison/bison.simple" yyvsp -= yylen; yyssp -= yylen; #if YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG if (yydebug) { short *yyssp1 = yyss - 1; YYFPRINTF (stderr, "state stack now"); while (yyssp1 != yyssp) YYFPRINTF (stderr, " %d", *++yyssp1); YYFPRINTF (stderr, "\n"); } #endif *++yyvsp = yyval; #if YYLSP_NEEDED *++yylsp = yyloc; #endif /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { YYSIZE_T yysize = 0; char *yymsg; int yyx, yycount; yycount = 0; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ for (yyx = yyn < 0 ? -yyn : 0; yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx) yysize += yystrlen (yytname[yyx]) + 15, yycount++; yysize += yystrlen ("parse error, unexpected ") + 1; yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { char *yyp = yystpcpy (yymsg, "parse error, unexpected "); yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); if (yycount < 5) { yycount = 0; for (yyx = yyn < 0 ? -yyn : 0; yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx) { const char *yyq = ! yycount ? ", expecting " : " or "; yyp = yystpcpy (yyp, yyq); yyp = yystpcpy (yyp, yytname[yyx]); yycount++; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else yyerror ("parse error; also virtual memory exhausted"); } else #endif /* defined (YYERROR_VERBOSE) */ yyerror ("parse error"); } goto yyerrlab1; /*--------------------------------------------------. | yyerrlab1 -- error raised explicitly by an action | `--------------------------------------------------*/ yyerrlab1: if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; YYDPRINTF ((stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1])); yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; /*-------------------------------------------------------------------. | yyerrdefault -- current state does not do anything special for the | | error token. | `-------------------------------------------------------------------*/ yyerrdefault: #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ /* If its default is to accept any token, ok. Otherwise pop it. */ yyn = yydefact[yystate]; if (yyn) goto yydefault; #endif /*---------------------------------------------------------------. | yyerrpop -- pop the current state because it cannot handle the | | error token | `---------------------------------------------------------------*/ yyerrpop: if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #if YYLSP_NEEDED yylsp--; #endif #if YYDEBUG if (yydebug) { short *yyssp1 = yyss - 1; YYFPRINTF (stderr, "Error: state stack now"); while (yyssp1 != yyssp) YYFPRINTF (stderr, " %d", *++yyssp1); YYFPRINTF (stderr, "\n"); } #endif /*--------------. | yyerrhandle. | `--------------*/ yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; #if YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; /*---------------------------------------------. | yyoverflowab -- parser overflow comes here. | `---------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 875 "ucparse.yy" /* * Create an array with an integer as the first element. */ static Uc_array_expression *Create_array ( int e1, Uc_expression *e2 ) { Uc_array_expression *arr = new Uc_array_expression(); arr->add(new Uc_int_expression(e1)); arr->add(e2); return arr; } static Uc_array_expression *Create_array ( int e1, Uc_expression *e2, Uc_expression *e3 ) { Uc_array_expression *arr = new Uc_array_expression(); arr->add(new Uc_int_expression(e1)); arr->add(e2); arr->add(e3); return arr; } exult-1.2/usecode/compiler/ucparse.yy0000644000175000001440000004615207732251221013471 %{ /** ** Ucparse.y - Usecode parser. ** ** Written: 12/30/2000 - JSF **/ /* Copyright (C) 2000 The Exult Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "ucfun.h" #include "ucexpr.h" #include "ucstmt.h" #include "opcodes.h" #include "ucscriptop.h" using std::strcpy; using std::strcat; using std::strlen; void yyerror(char *); extern int yylex(); static Uc_array_expression *Create_array(int, Uc_expression *); static Uc_array_expression *Create_array(int, Uc_expression *, Uc_expression *); #define YYERROR_VERBOSE 1 std::vector functions; // THIS is what we produce. static Uc_function *function = 0; // Current function being parsed. static int enum_val = -1; // Keeps track of enum elements. %} %union { class Uc_symbol *sym; class Uc_var_symbol *var; class Uc_expression *expr; class Uc_call_expression *funcall; class Uc_function_symbol *funsym; class Uc_statement *stmt; class std::vector *strvec; class Uc_block_statement *block; class Uc_arrayloop_statement *arrayloop; class Uc_array_expression *exprlist; int intval; char *strval; } /* * Keywords: */ %token IF ELSE RETURN WHILE FOR UCC_IN WITH TO EXTERN BREAK GOTO CASE %token VAR UCC_INT UCC_CONST STRING ENUM %token CONVERSE SAY MESSAGE RESPONSE EVENT FLAG ITEM UCTRUE UCFALSE REMOVE %token ADD HIDE SCRIPT AFTER TICKS STATIC_ ORIGINAL /* * Script keywords: */ /* Script commands. */ %token CONTINUE REPEAT NOP NOHALT WAIT REMOVE RISE DESCEND FRAME HATCH %token NEXT PREVIOUS CYCLE STEP MUSIC CALL SPEECH SFX FACE HIT HOURS ACTOR %token NORTH SOUTH EAST WEST NE NW SE SW /* * Other tokens: */ %token STRING_LITERAL STRING_PREFIX IDENTIFIER %token INT_LITERAL /* * Handle if-then-else conflict. */ %left IF %right ELSE /* * Expression precedence rules (lowest to highest): */ %left AND OR %left EQUALS NEQUALS LTEQUALS GTEQUALS '<' '>' UCC_IN %left '-' '+' '&' %left '*' '/' '%' %left NOT %left UCC_POINTS /* * Production types: */ %type expression primary declared_var_value opt_script_delay item %type script_command %type opt_int eventid direction int_literal converse_options %type opt_original %type declared_sym %type declared_var %type function_proto function_decl %type identifier_list opt_identifier_list %type statement assignment_statement if_statement while_statement %type statement_block return_statement function_call_statement %type special_method_call_statement %type array_loop_statement var_decl var_decl_list declaration %type break_statement converse_statement converse2_statement %type converse_case script_statement %type label_statement goto_statement answer_statement %type statement_list converse_case_list %type start_array_loop %type opt_expression_list expression_list script_command_list %type function_call routine_call method_call %% design: design global_decl | global_decl ; global_decl: function | function_decl { if (!Uc_function::add_global_function_symbol($1)) delete $1; } | const_int_decl | enum_decl | static_decl ; function: function_proto { function = new Uc_function($1); } statement_block { function->set_statement($3); functions.push_back(function); function = 0; } ; /* Opt_int assigns function #. */ function_proto: opt_var IDENTIFIER opt_int '(' opt_identifier_list ')' { $$ = new Uc_function_symbol($2, $3, *$5); delete $5; // A copy was made. } ; opt_int: int_literal | /* Empty. */ { $$ = -1; } ; statement_block: '{' { function->push_scope(); } statement_list '}' { $$ = $3; function->pop_scope(); } ; statement_list: statement_list statement { if ($2) $$->add($2); } | /* Empty. */ { $$ = new Uc_block_statement(); } ; statement: declaration | assignment_statement | if_statement | while_statement | array_loop_statement | function_call_statement | special_method_call_statement | return_statement | statement_block | converse_statement | converse2_statement | script_statement | break_statement | label_statement | goto_statement | SAY '(' opt_expression_list ')' ';' { $$ = new Uc_say_statement($3); } | MESSAGE '(' opt_expression_list ')' ';' { $$ = new Uc_message_statement($3); } | answer_statement | ';' /* Null statement */ { $$ = 0; } ; declaration: VAR var_decl_list ';' { $$ = $2; } | STRING string_decl_list ';' { $$ = 0; } | const_int_decl { $$ = 0; } | enum_decl { $$ = 0; } | function_decl { if (!function->add_function_symbol($1)) delete $1; $$ = 0; } | static_decl { $$ = 0; } ; var_decl_list: var_decl_list ',' var_decl { if (!$3) $$ = $1; else if (!$1) $$ = $3; else /* Both nonzero. Need a list. */ { Uc_block_statement *b = dynamic_cast($1); if (!b) { b = new Uc_block_statement(); b->add($1); } b->add($3); $$ = b; } } | var_decl { $$ = $1; } ; enum_decl: /* Decls. the elems, not the enum. */ ENUM IDENTIFIER { enum_val = -1; } '{' enum_item_list '}' ';' ; enum_item_list: enum_item_list ',' enum_item | enum_item ; enum_item: const_int | IDENTIFIER { /* Increment last value. */ ++enum_val; if (function) function->add_int_const_symbol($1, enum_val); else // Global. Uc_function::add_global_int_const_symbol($1, enum_val); } ; const_int_decl: UCC_CONST UCC_INT const_int_decl_list ';' ; const_int_decl_list: const_int_decl_list ',' const_int | const_int ; const_int: IDENTIFIER '=' expression { int val; // Get constant. if ($3->eval_const(val)) { if (function) function->add_int_const_symbol($1, val); else // Global. Uc_function::add_global_int_const_symbol( $1, val); enum_val = val; // In case we're in an enum. } } ; var_decl: IDENTIFIER { function->add_symbol($1); $$ = 0; } | IDENTIFIER '=' expression { Uc_var_symbol *var = function->add_symbol($1); $$ = new Uc_assignment_statement( new Uc_var_expression(var), $3); } ; static_decl: STATIC_ VAR static_var_decl_list ';' ; static_var_decl_list: static_var | static_var_decl_list ',' static_var ; static_var: IDENTIFIER { if (function) function->add_static($1); else Uc_function::add_global_static($1); } ; string_decl_list: string_decl_list ',' string_decl | string_decl ; string_decl: IDENTIFIER '=' STRING_LITERAL { function->add_string_symbol($1, $3); } ; function_decl: EXTERN function_proto ';' { $$ = $2; } ; assignment_statement: expression '=' expression ';' { $$ = new Uc_assignment_statement($1, $3); } ; if_statement: IF '(' expression ')' statement %prec IF { $$ = new Uc_if_statement($3, $5, 0); } | IF '(' expression ')' statement ELSE statement { $$ = new Uc_if_statement($3, $5, $7); } ; while_statement: WHILE '(' expression ')' statement { $$ = new Uc_while_statement($3, $5); } ; array_loop_statement: start_array_loop ')' statement { $1->set_statement($3); $1->finish(function); function->pop_scope(); } | start_array_loop WITH IDENTIFIER { $1->set_index(function->add_symbol($3)); } ')' statement { $1->set_statement($6); $1->finish(function); function->pop_scope(); } | start_array_loop WITH IDENTIFIER { $1->set_index(function->add_symbol($3)); } TO IDENTIFIER { $1->set_array_size(function->add_symbol($6)); } ')' statement { $1->set_statement($9); function->pop_scope(); } ; start_array_loop: start_for IDENTIFIER UCC_IN declared_var { Uc_var_symbol *var = function->add_symbol($2); $$ = new Uc_arrayloop_statement(var, $4); } ; start_for: FOR '(' { function->push_scope(); } ; function_call_statement: function_call ';' { $$ = new Uc_call_statement($1); } ; special_method_call_statement: /* Have 'primary' say something.*/ primary hierarchy_tok SAY '(' opt_expression_list ')' ';' { Uc_block_statement *stmts = new Uc_block_statement(); /* Set up 'show' call. */ stmts->add(new Uc_call_statement( new Uc_call_expression(Uc_function::get_show_face(), new Uc_array_expression($1, new Uc_int_expression(0)), function))); stmts->add(new Uc_say_statement($5)); $$ = stmts; } | primary hierarchy_tok HIDE '(' ')' ';' { $$ = new Uc_call_statement( new Uc_call_expression(Uc_function::get_remove_face(), new Uc_array_expression($1), function)); } ; return_statement: RETURN expression ';' { $$ = new Uc_return_statement($2); } | RETURN ';' { $$ = new Uc_return_statement(); } ; converse_statement: CONVERSE statement { $$ = new Uc_converse_statement($2); } ; converse2_statement: /* A less wordy form. */ CONVERSE '(' expression ')' '{' converse_case_list '}' { $$ = new Uc_converse2_statement($3, $6); } ; converse_case_list: converse_case_list converse_case { if ($2) $$->add($2); } | { $$ = new Uc_block_statement(); } ; converse_case: CASE STRING_LITERAL converse_options ':' statement_list { $$ = new Uc_converse_case_statement(function->add_string($2), ($3 ? true : false), $5); } ; converse_options: '(' REMOVE ')' /* For now, just one. */ { $$ = 1; } | { $$ = 0; } ; script_statement: /* Yes, this could be an intrinsic. */ SCRIPT item opt_script_delay script_command { Uc_array_expression *parms = new Uc_array_expression(); parms->add($2); // Itemref. parms->add($4); // Script. if ($3) // Delay? parms->add($3); // Get the script intrinsic. Uc_symbol *sym = Uc_function::get_intrinsic($3 ? 2 : 1); Uc_call_expression *fcall = new Uc_call_expression(sym, parms, function); $$ = new Uc_call_statement(fcall); } ; item: /* Any object, NPC. */ expression ; script_command_list: script_command_list script_command { $$->concat($2); } | script_command { $$ = new Uc_array_expression(); $$->concat($1); } ; script_command: CONTINUE ';' /* Continue script without painting. */ { $$ = new Uc_int_expression(Ucscript::cont); } | REPEAT expression script_command ';' { Uc_array_expression *result = new Uc_array_expression(); result->concat($3); // Start with cmnds. to repeat. int sz = result->get_exprs().size(); result->add(new Uc_int_expression(Ucscript::repeat)); // Then -offset to start. result->add(new Uc_int_expression(-sz)); result->add($2); // Then #times to repeat. $$ = result; } /* REPEAT2? */ | NOP ';' { $$ = new Uc_int_expression(Ucscript::nop); } | NOHALT ';' { $$ = new Uc_int_expression(Ucscript::dont_halt); } | WAIT expression ';' /* Ticks. */ { $$ = Create_array(Ucscript::delay_ticks, $2); } | WAIT expression HOURS ';' /* Game hours. */ { $$ = Create_array(Ucscript::delay_hours, $2); } | REMOVE ';' /* Remove item. */ { $$ = new Uc_int_expression(Ucscript::remove); } | RISE ';' /* For flying barges. */ { $$ = new Uc_int_expression(Ucscript::rise); } | DESCEND ';' { $$ = new Uc_int_expression(Ucscript::descend); } | FRAME expression ';' { $$ = Create_array(Ucscript::frame, $2); } | ACTOR FRAME int_literal ';' /* 0-15. ++++Maybe have keywords. */ { $$ = new Uc_int_expression(0x61 + ($3 & 15)); } | HATCH ';' /* Assumes item is an egg. */ { $$ = new Uc_int_expression(Ucscript::egg); } | NEXT FRAME ';' /* Next, but stop at last. */ { $$ = new Uc_int_expression(Ucscript::next_frame_max); } | NEXT FRAME CYCLE ';' /* Next, or back to 0. */ { $$ = new Uc_int_expression(Ucscript::next_frame); } | PREVIOUS FRAME ';' /* Prev. but stop at 0. */ { $$ = new Uc_int_expression(Ucscript::prev_frame_min); } | PREVIOUS FRAME CYCLE ';' { $$ = new Uc_int_expression(Ucscript::prev_frame); } | SAY expression ';' { $$ = Create_array(Ucscript::say, $2); } | STEP expression ';' /* Step in given direction (0-7). */ { $$ = Create_array(Ucscript::step, $2); } | STEP direction ';' { $$ = new Uc_int_expression(Ucscript::step_n + $2); } | MUSIC expression ';' { $$ = Create_array(Ucscript::music, $2); } | CALL expression ';' { $$ = Create_array(Ucscript::usecode, $2); } | CALL expression ',' eventid ';' { $$ = Create_array(Ucscript::usecode2, $2, new Uc_int_expression($4)); } | SPEECH expression ';' { $$ = Create_array(Ucscript::speech, $2); } | SFX expression ';' { $$ = Create_array(Ucscript::sfx, $2); } | FACE expression ';' { $$ = Create_array(Ucscript::face_dir, $2); } | HIT expression ';' /* 2nd parm unknown. */ { $$ = Create_array(Ucscript::hit, $2); } | '{' script_command_list '}' { $$ = $2; } ; direction: NORTH { $$ = 0; } | NE { $$ = 1; } | EAST { $$ = 2; } | SE { $$ = 3; } | SOUTH { $$ = 4; } | SW { $$ = 5; } | WEST { $$ = 6; } | NW { $$ = 7; } ; eventid: int_literal ; opt_script_delay: AFTER expression TICKS { $$ = $2; } | { $$ = 0; } ; break_statement: BREAK ';' { $$ = new Uc_break_statement(); } ; label_statement: IDENTIFIER ':' { Uc_label *label = function->search_label($1); if (label) { char buf[150]; sprintf(buf, "duplicate label: '%s'", $1); yyerror(buf); $$ = 0; } else { label = new Uc_label($1); function->add_label(label); $$ = new Uc_label_statement(label); } } ; goto_statement: GOTO IDENTIFIER { $$ = new Uc_goto_statement($2); } ; answer_statement: ADD '(' expression_list ')' ';' { $$ = new Uc_call_statement( new Uc_call_expression(Uc_function::get_add_answer(), $3, function)); } | REMOVE '(' expression_list ')' ';' { $$ = new Uc_call_statement(new Uc_call_expression( Uc_function::get_remove_answer(), $3, function)); } ; expression: primary { $$ = $1; } | expression '+' expression { $$ = new Uc_binary_expression(UC_ADD, $1, $3); } | expression '-' expression { $$ = new Uc_binary_expression(UC_SUB, $1, $3); } | expression '*' expression { $$ = new Uc_binary_expression(UC_MUL, $1, $3); } | expression '/' expression { $$ = new Uc_binary_expression(UC_DIV, $1, $3); } | expression '%' expression { $$ = new Uc_binary_expression(UC_MOD, $1, $3); } | expression EQUALS expression { $$ = new Uc_binary_expression(UC_CMPEQ, $1, $3); } | RESPONSE EQUALS expression { $$ = new Uc_response_expression($3); } | expression NEQUALS expression { $$ = new Uc_binary_expression(UC_CMPNE, $1, $3); } | expression '<' expression { $$ = new Uc_binary_expression(UC_CMPL, $1, $3); } | expression LTEQUALS expression { $$ = new Uc_binary_expression(UC_CMPLE, $1, $3); } | expression '>' expression { $$ = new Uc_binary_expression(UC_CMPG, $1, $3); } | expression GTEQUALS expression { $$ = new Uc_binary_expression(UC_CMPGE, $1, $3); } | expression AND expression { $$ = new Uc_binary_expression(UC_AND, $1, $3); } | expression OR expression { $$ = new Uc_binary_expression(UC_OR, $1, $3); } | expression UCC_IN expression /* Value in array. */ { $$ = new Uc_binary_expression(UC_IN, $1, $3); } | expression '&' expression /* append arrays */ { $$ = new Uc_binary_expression(UC_ARRA, $1, $3); } | '-' primary { $$ = new Uc_binary_expression(UC_SUB, new Uc_int_expression(0), $2); } | NOT primary { $$ = new Uc_unary_expression(UC_NOT, $2); } | '[' expression_list ']' /* Concat. into an array. */ { $$ = $2; } | STRING_LITERAL { $$ = new Uc_string_expression(function->add_string($1)); } | STRING_PREFIX { $$ = new Uc_string_prefix_expression(function, $1); } ; opt_expression_list: expression_list | { $$ = new Uc_array_expression(); } ; expression_list: expression_list ',' expression { $$->add($3); } | expression { $$ = new Uc_array_expression(); $$->add($1); } ; primary: INT_LITERAL { $$ = new Uc_int_expression($1); } | declared_var_value { $$ = $1; } | declared_var '[' expression ']' { $$ = new Uc_arrayelem_expression($1, $3); } | FLAG '[' int_literal ']' { $$ = new Uc_flag_expression($3); } | function_call { $$ = $1; } | UCTRUE { $$ = new Uc_bool_expression(true); } | UCFALSE { $$ = new Uc_bool_expression(false); } | EVENT { $$ = new Uc_event_expression(); } | ITEM { $$ = new Uc_item_expression(); } | '(' expression ')' { $$ = $2; } ; function_call: routine_call | method_call ; method_call: primary hierarchy_tok routine_call /* Really a way to do CALLE. */ { $3->set_itemref($1); $$ = $3; } ; hierarchy_tok: UCC_POINTS | '.' ; routine_call: IDENTIFIER opt_original '(' opt_expression_list ')' { Uc_symbol *sym = function->search_up($1); if (!sym) { char buf[150]; sprintf(buf, "'%s' not declared", $1); yyerror(buf); $$ = 0; } else $$ = new Uc_call_expression(sym, $4, function, $2 ? true : false); } ; opt_original: ORIGINAL { $$ = 1; } | { $$ = 0; } ; opt_identifier_list: identifier_list | { $$ = new std::vector; } ; identifier_list: identifier_list ',' opt_var IDENTIFIER { $1->push_back($4); } | opt_var IDENTIFIER { $$ = new std::vector; $$->push_back($2); } ; int_literal: /* A const. integer value. */ INT_LITERAL | declared_sym { Uc_const_int_symbol *sym = dynamic_cast($1); if (!sym) { char buf[150]; sprintf(buf, "'%s' is not a const int"); yyerror(buf); $$ = 0; } else $$ = sym->get_value(); } ; opt_var: VAR | ; declared_var_value: declared_sym { $$ = $1->create_expression(); if (!$$) { char buf[150]; sprintf(buf, "Can't use '%s' here", $1->get_name()); yyerror(buf); $$ = new Uc_int_expression(0); } } ; declared_var: declared_sym { Uc_var_symbol *var = dynamic_cast($1); if (!var) { char buf[150]; sprintf(buf, "'%s' not a 'var'", $1); yyerror(buf); sprintf(buf, "%s_needvar", $1->get_name()); var = function->add_symbol(buf); } $$ = var; } ; declared_sym: IDENTIFIER { Uc_symbol *sym = function->search_up($1); if (!sym) { char buf[150]; sprintf(buf, "'%s' not declared", $1); yyerror(buf); sym = function->add_symbol($1); } $$ = sym; } ; %% /* * Create an array with an integer as the first element. */ static Uc_array_expression *Create_array ( int e1, Uc_expression *e2 ) { Uc_array_expression *arr = new Uc_array_expression(); arr->add(new Uc_int_expression(e1)); arr->add(e2); return arr; } static Uc_array_expression *Create_array ( int e1, Uc_expression *e2, Uc_expression *e3 ) { Uc_array_expression *arr = new Uc_array_expression(); arr->add(new Uc_int_expression(e1)); arr->add(e2); arr->add(e3); return arr; } exult-1.2/usecode/Makefile.am0000644000175000001440000000152607500166354011667 INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ -I$(srcdir)/../shapes -I$(srcdir)/../objs -I$(srcdir)/../audio\ -I$(srcdir)/../gumps -I$(srcdir)/../tools \ -I$(srcdir)/../server $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) SUBDIRS = compiler ucxt noinst_LTLIBRARIES = libusecode.la libusecode_la_SOURCES = \ bgintrinsics.h \ siintrinsics.h \ intrinsics.cc \ ucinternal.cc \ ucinternal.h \ ucmachine.cc \ ucmachine.h \ ucsched.h \ ucsched.cc \ ucscriptop.h \ useval.cc \ useval.h \ conversation.cc \ conversation.h \ keyring.cc \ keyring.h \ ucdisasm.cc \ ucdebugging.cc \ ucdebugging.h \ debugserver.cc \ debugserver.h \ debugmsg.h \ stackframe.cc \ stackframe.h \ ucserial.h \ ucserial.cc \ ucfunction.h \ ucfunction.cc CLEANFILES = *~ exult-1.2/usecode/Makefile.in0000644000175000001440000003565010061527060011674 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/../headers -I$(srcdir)/.. -I$(srcdir)/../files -I$(srcdir)/../imagewin \ -I$(srcdir)/../shapes -I$(srcdir)/../objs -I$(srcdir)/../audio\ -I$(srcdir)/../gumps -I$(srcdir)/../tools \ -I$(srcdir)/../server $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) SUBDIRS = compiler ucxt noinst_LTLIBRARIES = libusecode.la libusecode_la_SOURCES = \ bgintrinsics.h \ siintrinsics.h \ intrinsics.cc \ ucinternal.cc \ ucinternal.h \ ucmachine.cc \ ucmachine.h \ ucsched.h \ ucsched.cc \ ucscriptop.h \ useval.cc \ useval.h \ conversation.cc \ conversation.h \ keyring.cc \ keyring.h \ ucdisasm.cc \ ucdebugging.cc \ ucdebugging.h \ debugserver.cc \ debugserver.h \ debugmsg.h \ stackframe.cc \ stackframe.h \ ucserial.h \ ucserial.cc \ ucfunction.h \ ucfunction.cc CLEANFILES = *~ subdir = usecode mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libusecode_la_LDFLAGS = libusecode_la_LIBADD = am_libusecode_la_OBJECTS = intrinsics.lo ucinternal.lo ucmachine.lo \ ucsched.lo useval.lo conversation.lo keyring.lo ucdisasm.lo \ ucdebugging.lo debugserver.lo stackframe.lo ucserial.lo \ ucfunction.lo libusecode_la_OBJECTS = $(am_libusecode_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/conversation.Plo \ @AMDEP_TRUE@ $(DEPDIR)/debugserver.Plo $(DEPDIR)/intrinsics.Plo \ @AMDEP_TRUE@ $(DEPDIR)/keyring.Plo $(DEPDIR)/stackframe.Plo \ @AMDEP_TRUE@ $(DEPDIR)/ucdebugging.Plo $(DEPDIR)/ucdisasm.Plo \ @AMDEP_TRUE@ $(DEPDIR)/ucfunction.Plo $(DEPDIR)/ucinternal.Plo \ @AMDEP_TRUE@ $(DEPDIR)/ucmachine.Plo $(DEPDIR)/ucsched.Plo \ @AMDEP_TRUE@ $(DEPDIR)/ucserial.Plo $(DEPDIR)/useval.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libusecode_la_SOURCES) RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ uninstall-info-recursive all-recursive install-data-recursive \ install-exec-recursive installdirs-recursive install-recursive \ uninstall-recursive check-recursive installcheck-recursive DIST_COMMON = Makefile.am Makefile.in DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(libusecode_la_SOURCES) all: all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu usecode/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libusecode.la: $(libusecode_la_OBJECTS) $(libusecode_la_DEPENDENCIES) $(CXXLINK) $(libusecode_la_LDFLAGS) $(libusecode_la_OBJECTS) $(libusecode_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/conversation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/debugserver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/intrinsics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/keyring.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stackframe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucdebugging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucdisasm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucfunction.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucinternal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucmachine.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucsched.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ucserial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/useval.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-recursive distclean distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-recursive \ distclean-tags distdir dvi dvi-am dvi-recursive info info-am \ info-recursive install install-am install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive tags tags-recursive uninstall \ uninstall-am uninstall-info-am uninstall-info-recursive \ uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/usecode/keyring.h0000644000175000001440000000215707724430454011460 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _KEYRING_H #define _KEYRING_H #include class Keyring { public: Keyring() { } void read(); // read from KEYRING.DAT void write(); // write to KEYRING.DAT void clear(); // remove all keys void addkey(int qual); // add key to keyring bool checkkey(int qual); // is key on keyring? private: std::set keys; }; #endif exult-1.2/usecode/ucinternal.h0000644000175000001440000003742707776726135012177 /* * ucinternal.h - Interpreter for usecode. * * Usecode_internal is the implementation, so this header should only * be included within .cc's in the 'usecode' directory. * * * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UCINTERNAL_H #define _UCINTERNAL_H #ifndef ALPHA_LINUX_CXX # include #endif #include "exult_types.h" class Actor; class Barge_object; class Npc_actor; class Usecode_value; class Text_gump; class Vector; class Stack_frame; class Usecode_function; #include "useval.h" #include "ucmachine.h" #include "ucdebugging.h" #include "tiles.h" #include "vec.h" // Includes STL vector. #include // STL string #include /* * Recursively look for a barge that an object is a part of, or on. * * Output: ->barge if found, else 0. */ Barge_object *Get_barge ( Game_object *obj ); #define USECODE_INTRINSIC_DECL(NAME) Usecode_value UI_## NAME (int event,int intrinsic,int num_parms,Usecode_value parms[12]) /* * Here's our virtual machine for running usecode. */ class Usecode_internal : public Usecode_machine { // I'th entry contains funs for ID's // 256*i + n. Exult_vector funs[16]; Exult_vector statics; // Global persistent vars. std::deque call_stack; // the call stack Stack_frame *frame; // One intrinsic uses this for now... bool modified_map; // We add/deleted/moved an object. unsigned long timers[20]; // Each has time in hours when set. int speech_track; // Set/read by some intrinsics. Text_gump *book; // Book/scroll being displayed. Game_object *caller_item; // Item this is being called on. Game_object_vector last_created;// Stack of last items created with // intrins. x24. Actor *path_npc; // Last NPC in path_run_usecode(). const char *user_choice; // String user clicked on. bool found_answer; // Did we already handle the // conversation option? Tile_coord saved_pos; // For a couple SI intrinsics. char *String; // The single string register. int telekenesis_fun; // For next Usecode call from spell. void append_string(const char *txt); // Append to string. void show_pending_text(); // Make sure user's seen all text. void show_book(); // "Say" book/scroll text. void say_string(); // "Say" the string. Usecode_value *stack; // Stack. Usecode_value *sp; // Stack ptr. Grows upwards. void stack_error(int under); void push(Usecode_value& val); // Push/pop stack. Usecode_value pop(); void pushref(Game_object* obj); // Push itemref void pushi(long val); // Push/pop integers. int popi(); // Push/pop strings. void pushs(char *s); // Get ->obj. from 'itemref'. Game_object *get_item(Usecode_value& itemref); // "Safe" cast to Actor and Npc_actor. Actor *as_actor(Game_object *obj); // Get position. Tile_coord get_position(Usecode_value& itemref); /* * Built-in usecode functions: */ typedef Usecode_value (Usecode_internal::*UsecodeIntrinsicFn)( int event,int intrinsic,int num_parms,Usecode_value parms[12]); void show_npc_face(Usecode_value& arg1, Usecode_value& arg2, int slot = -1); void remove_npc_face(Usecode_value& arg1); void set_item_shape(Usecode_value& item_arg, Usecode_value& shape_arg); void set_item_frame(Game_object *item, int frame, int check_empty = 0, int set_rotated = 0); void add_dirty(Game_object *obj); void remove_item(Game_object *obj); Usecode_value get_party(); void item_say(Usecode_value& objval, Usecode_value& strval); void activate_cached(Tile_coord pos); Usecode_value find_nearby(Usecode_value& objval, Usecode_value& shapeval, Usecode_value& qval, Usecode_value& mval); Usecode_value find_nearest(Usecode_value& objval, Usecode_value& shapeval, Usecode_value& unknown); Usecode_value find_direction(Usecode_value& from, Usecode_value& to); Usecode_value count_objects(Usecode_value& objval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval); Usecode_value get_objects(Usecode_value& objval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval); Usecode_value remove_party_items(Usecode_value& quantval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval, Usecode_value& flagval); Usecode_value add_party_items(Usecode_value& quantval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval, Usecode_value& flagval); Usecode_value add_cont_items(Usecode_value& container, Usecode_value& quantval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval, Usecode_value& flagval); Usecode_value remove_cont_items(Usecode_value& container, Usecode_value& quantval, Usecode_value& shapeval, Usecode_value& qualval, Usecode_value& frameval, Usecode_value& flagval); int path_run_usecode(Usecode_value& npcval, Usecode_value& locval, Usecode_value& useval, Usecode_value& itemval, Usecode_value& eventval, int find_free = 0, int always = 0); void create_script(Usecode_value& objval, Usecode_value& codeval, long delay); /* * Embedded intrinsics */ static struct IntrinsicTableEntry { UsecodeIntrinsicFn func; const char *name; } intrinsic_table[], serpent_table[]; Usecode_value Execute_Intrinsic(UsecodeIntrinsicFn func,const char *name,int event,int intrinsic,int num_parms,Usecode_value parms[12]); USECODE_INTRINSIC_DECL(NOP); USECODE_INTRINSIC_DECL(UNKNOWN); USECODE_INTRINSIC_DECL(get_random); USECODE_INTRINSIC_DECL(execute_usecode_array); USECODE_INTRINSIC_DECL(delayed_execute_usecode_array); USECODE_INTRINSIC_DECL(show_npc_face); USECODE_INTRINSIC_DECL(remove_npc_face); USECODE_INTRINSIC_DECL(add_answer); USECODE_INTRINSIC_DECL(remove_answer); USECODE_INTRINSIC_DECL(push_answers); USECODE_INTRINSIC_DECL(pop_answers); USECODE_INTRINSIC_DECL(clear_answers); USECODE_INTRINSIC_DECL(select_from_menu); USECODE_INTRINSIC_DECL(select_from_menu2); USECODE_INTRINSIC_DECL(input_numeric_value); USECODE_INTRINSIC_DECL(set_item_shape); USECODE_INTRINSIC_DECL(find_nearest); USECODE_INTRINSIC_DECL(die_roll); USECODE_INTRINSIC_DECL(get_item_shape); USECODE_INTRINSIC_DECL(get_item_frame); USECODE_INTRINSIC_DECL(set_item_frame); USECODE_INTRINSIC_DECL(get_item_quality); USECODE_INTRINSIC_DECL(set_item_quality); USECODE_INTRINSIC_DECL(get_item_quantity); USECODE_INTRINSIC_DECL(set_item_quantity); USECODE_INTRINSIC_DECL(get_object_position); USECODE_INTRINSIC_DECL(get_distance); USECODE_INTRINSIC_DECL(find_direction); USECODE_INTRINSIC_DECL(get_npc_object); USECODE_INTRINSIC_DECL(get_schedule_type); USECODE_INTRINSIC_DECL(set_schedule_type); USECODE_INTRINSIC_DECL(add_to_party); USECODE_INTRINSIC_DECL(remove_from_party); USECODE_INTRINSIC_DECL(get_npc_prop); USECODE_INTRINSIC_DECL(set_npc_prop); USECODE_INTRINSIC_DECL(get_avatar_ref); USECODE_INTRINSIC_DECL(get_party_list); USECODE_INTRINSIC_DECL(create_new_object); USECODE_INTRINSIC_DECL(create_new_object2); USECODE_INTRINSIC_DECL(set_last_created); USECODE_INTRINSIC_DECL(update_last_created); USECODE_INTRINSIC_DECL(get_npc_name); USECODE_INTRINSIC_DECL(count_objects); USECODE_INTRINSIC_DECL(find_object); USECODE_INTRINSIC_DECL(get_cont_items); USECODE_INTRINSIC_DECL(remove_party_items); USECODE_INTRINSIC_DECL(add_party_items); USECODE_INTRINSIC_DECL(play_music); USECODE_INTRINSIC_DECL(npc_nearby); USECODE_INTRINSIC_DECL(npc_nearby2); USECODE_INTRINSIC_DECL(find_nearby_avatar); USECODE_INTRINSIC_DECL(is_npc); USECODE_INTRINSIC_DECL(display_runes); USECODE_INTRINSIC_DECL(click_on_item); USECODE_INTRINSIC_DECL(set_intercept_item); USECODE_INTRINSIC_DECL(find_nearby); USECODE_INTRINSIC_DECL(give_last_created); USECODE_INTRINSIC_DECL(is_dead); USECODE_INTRINSIC_DECL(game_hour); USECODE_INTRINSIC_DECL(game_minute); USECODE_INTRINSIC_DECL(get_npc_number); USECODE_INTRINSIC_DECL(part_of_day); USECODE_INTRINSIC_DECL(get_alignment); USECODE_INTRINSIC_DECL(set_alignment); USECODE_INTRINSIC_DECL(move_object); USECODE_INTRINSIC_DECL(remove_npc); USECODE_INTRINSIC_DECL(item_say); USECODE_INTRINSIC_DECL(clear_item_say); USECODE_INTRINSIC_DECL(projectile_effect); USECODE_INTRINSIC_DECL(get_lift); USECODE_INTRINSIC_DECL(set_lift); USECODE_INTRINSIC_DECL(get_weather); USECODE_INTRINSIC_DECL(set_weather); USECODE_INTRINSIC_DECL(sit_down); USECODE_INTRINSIC_DECL(summon); USECODE_INTRINSIC_DECL(display_map); USECODE_INTRINSIC_DECL(si_display_map); USECODE_INTRINSIC_DECL(kill_npc); USECODE_INTRINSIC_DECL(roll_to_win); USECODE_INTRINSIC_DECL(set_attack_mode); USECODE_INTRINSIC_DECL(get_attack_mode); USECODE_INTRINSIC_DECL(set_opponent); USECODE_INTRINSIC_DECL(clone); USECODE_INTRINSIC_DECL(get_oppressor); USECODE_INTRINSIC_DECL(set_oppressor); USECODE_INTRINSIC_DECL(get_weapon); USECODE_INTRINSIC_DECL(display_area); USECODE_INTRINSIC_DECL(wizard_eye); USECODE_INTRINSIC_DECL(resurrect); USECODE_INTRINSIC_DECL(get_body_npc); USECODE_INTRINSIC_DECL(add_spell); USECODE_INTRINSIC_DECL(sprite_effect); USECODE_INTRINSIC_DECL(obj_sprite_effect); USECODE_INTRINSIC_DECL(explode); USECODE_INTRINSIC_DECL(book_mode); USECODE_INTRINSIC_DECL(stop_time); USECODE_INTRINSIC_DECL(cause_light); USECODE_INTRINSIC_DECL(get_barge); USECODE_INTRINSIC_DECL(earthquake); USECODE_INTRINSIC_DECL(is_pc_female); USECODE_INTRINSIC_DECL(armageddon); USECODE_INTRINSIC_DECL(halt_scheduled); USECODE_INTRINSIC_DECL(lightning); USECODE_INTRINSIC_DECL(get_array_size); USECODE_INTRINSIC_DECL(mark_virtue_stone); USECODE_INTRINSIC_DECL(recall_virtue_stone); USECODE_INTRINSIC_DECL(apply_damage); USECODE_INTRINSIC_DECL(is_pc_inside); USECODE_INTRINSIC_DECL(get_timer); USECODE_INTRINSIC_DECL(set_timer); USECODE_INTRINSIC_DECL(wearing_fellowship); USECODE_INTRINSIC_DECL(mouse_exists); USECODE_INTRINSIC_DECL(get_speech_track); USECODE_INTRINSIC_DECL(flash_mouse); USECODE_INTRINSIC_DECL(get_item_frame_rot); USECODE_INTRINSIC_DECL(set_item_frame_rot); USECODE_INTRINSIC_DECL(on_barge); USECODE_INTRINSIC_DECL(get_container); USECODE_INTRINSIC_DECL(remove_item); USECODE_INTRINSIC_DECL(reduce_health); USECODE_INTRINSIC_DECL(is_readied); USECODE_INTRINSIC_DECL(get_readied); USECODE_INTRINSIC_DECL(restart_game); USECODE_INTRINSIC_DECL(start_speech); USECODE_INTRINSIC_DECL(is_water); USECODE_INTRINSIC_DECL(run_endgame); USECODE_INTRINSIC_DECL(fire_cannon); USECODE_INTRINSIC_DECL(nap_time); USECODE_INTRINSIC_DECL(advance_time); USECODE_INTRINSIC_DECL(in_usecode); USECODE_INTRINSIC_DECL(call_guards); USECODE_INTRINSIC_DECL(attack_avatar); USECODE_INTRINSIC_DECL(path_run_usecode); USECODE_INTRINSIC_DECL(close_gumps); USECODE_INTRINSIC_DECL(in_gump_mode); USECODE_INTRINSIC_DECL(is_not_blocked); USECODE_INTRINSIC_DECL(direction_from); USECODE_INTRINSIC_DECL(get_item_flag); USECODE_INTRINSIC_DECL(set_item_flag); USECODE_INTRINSIC_DECL(clear_item_flag); USECODE_INTRINSIC_DECL(set_path_failure); USECODE_INTRINSIC_DECL(fade_palette); USECODE_INTRINSIC_DECL(get_party_list2); USECODE_INTRINSIC_DECL(set_camera); USECODE_INTRINSIC_DECL(in_combat); USECODE_INTRINSIC_DECL(center_view); USECODE_INTRINSIC_DECL(get_dead_party); USECODE_INTRINSIC_DECL(play_sound_effect); USECODE_INTRINSIC_DECL(play_sound_effect2); USECODE_INTRINSIC_DECL(get_npc_id); USECODE_INTRINSIC_DECL(set_npc_id); USECODE_INTRINSIC_DECL(add_cont_items); USECODE_INTRINSIC_DECL(remove_cont_items); // Serpent Isle: USECODE_INTRINSIC_DECL(si_path_run_usecode); USECODE_INTRINSIC_DECL(remove_from_area); USECODE_INTRINSIC_DECL(infravision); USECODE_INTRINSIC_DECL(error_message); USECODE_INTRINSIC_DECL(set_polymorph); USECODE_INTRINSIC_DECL(show_npc_face0); USECODE_INTRINSIC_DECL(show_npc_face1); USECODE_INTRINSIC_DECL(remove_npc_face0); USECODE_INTRINSIC_DECL(remove_npc_face1); USECODE_INTRINSIC_DECL(set_conversation_slot); USECODE_INTRINSIC_DECL(init_conversation); USECODE_INTRINSIC_DECL(end_conversation); USECODE_INTRINSIC_DECL(set_new_schedules); USECODE_INTRINSIC_DECL(revert_schedule); USECODE_INTRINSIC_DECL(run_schedule); USECODE_INTRINSIC_DECL(modify_schedule); USECODE_INTRINSIC_DECL(get_temperature); USECODE_INTRINSIC_DECL(set_temperature); // USECODE_INTRINSIC_DECL(add_removed_npc); USECODE_INTRINSIC_DECL(approach_avatar); USECODE_INTRINSIC_DECL(set_barge_dir); USECODE_INTRINSIC_DECL(telekenesis); USECODE_INTRINSIC_DECL(a_or_an); USECODE_INTRINSIC_DECL(add_to_keyring); USECODE_INTRINSIC_DECL(is_on_keyring); USECODE_INTRINSIC_DECL(save_pos); USECODE_INTRINSIC_DECL(teleport_to_saved_pos); USECODE_INTRINSIC_DECL(get_item_usability); USECODE_INTRINSIC_DECL(get_skin_colour); USECODE_INTRINSIC_DECL(printf); /* * Other private methods: */ // Call instrinsic function. Usecode_value call_intrinsic(int event, int intrinsic, int num_parms); void click_to_continue(); // Wait for user to click. void set_book(Text_gump *b); // Set book/scroll to display. const char *get_user_choice(); // Get user's choice. int get_user_choice_num(); void read_usevars(std::istream& in); // Read static variables. Game_object *intercept_item; Game_object *temp_to_be_deleted; // execution functions bool call_function(int funcid, int event, Game_object *caller = 0, bool entrypoint = false, bool orig = false); void previous_stack_frame(); void return_from_function(Usecode_value& retval); void return_from_procedure(); void abort_function(); int run(); // debugging functions void uc_trace_disasm(Stack_frame* frame); void uc_trace_disasm(Usecode_value* locals, int num_locals, uint8* data, uint8* externals, uint8* code, uint8* ip); static int get_opcode_length(int opcode); void stack_trace(std::ostream& out); #ifdef USECODE_DEBUGGER Breakpoints breakpoints; bool on_breakpoint; // are we on a breakpoint? int breakpoint_action; // stay on breakpoint/continue/abort? public: bool is_on_breakpoint() const { return on_breakpoint; } void set_breakpoint_action(int a) { breakpoint_action = a; } void set_breakpoint(); int set_location_breakpoint(int funcid, int ip); bool clear_breakpoint(int id) { return breakpoints.remove(id); } void transmit_breakpoints(int fd) { breakpoints.transmit(fd); } void dbg_stepover(); void dbg_finish(); int get_callstack_size() const; Stack_frame* get_stackframe(int i); int get_stack_size() const; Usecode_value* peek_stack(int depth) const; void poke_stack(int depth, Usecode_value& val); #endif public: friend class Usecode_script; Usecode_internal(); ~Usecode_internal(); // Read in usecode functions. virtual void read_usecode(std::istream& file, bool patch = false); // Call desired function. virtual int call_usecode(int id, Game_object *obj, Usecode_events event); virtual void do_speech(int num);// Start speech, or show text. virtual int in_usecode() // Currently in a usecode function? { return !call_stack.empty(); } virtual void write(); // Write out 'gamedat/usecode.dat'. virtual void read(); // Read in 'gamedat/usecode.dat'. virtual void intercept_click_on_item(Game_object *obj) { intercept_item = obj; } }; #endif exult-1.2/usecode/ucfunction.cc0000644000175000001440000000252507732251221012312 /* * ucfunction.cc - Usecode function * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include using std::istream; #include "ucfunction.h" #include "utils.h" /* * Read in a function. */ Usecode_function::Usecode_function ( istream& file ) : orig(0) { id = Read2(file); // support for our extended usecode format. (32 bit lengths) if (id == 0xFFFF) { id = Read2(file); len = Read4(file); extended = true; } else { len = Read2(file); extended = false; } code = new unsigned char[len]; // Allocate buffer & read it in. file.read((char*)code, len); } exult-1.2/usecode/conversation.h0000644000175000001440000000511607724430454012520 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CONVERSATION_H #define _CONVERSATION_H #include "rect.h" #include "singles.h" #include "shapeid.h" #include #include #include class Npc_face_info; class Usecode_value; class Game_window; class Conversation : public Game_singletons, public Paintable{ public: Conversation(); ~Conversation(); private: Npc_face_info *face_info[2]; // NPC's on-screen faces in convers. int num_faces; int last_face_shown; // Index of last npc face shown. Rectangle avatar_face; // Area take by Avatar in conversation. Rectangle *conv_choices; // Choices during a conversation. std::vector answers; std::deque< std::vector > answer_stack; public: inline int get_num_answers() const { return answers.size(); } inline int get_num_faces_on_screen() const { return num_faces; } void init_faces(); void show_face(int shape, int frame, int slot = -1); void remove_face(int shape); void remove_slot_face(int slot); // SI. void remove_last_face(); // SI. void show_npc_message(const char *msg); bool is_npc_text_pending(); void clear_text_pending(); void show_avatar_choices(); void clear_avatar_choices(); int conversation_choice(int x, int y); void set_slot(int i) { last_face_shown = i; } // SI. virtual void paint(); // Paint entire conversation. void paint_faces(bool text = false); void add_answer(Usecode_value& val); void remove_answer(Usecode_value& val); void clear_answers(void); int locate_answer(const char* str); const char* get_answer(int num) { return answers[num].c_str(); } void push_answers(); void pop_answers(); bool stack_empty() const { return !answer_stack.size(); } private: void show_avatar_choices(int num_choices, char **choices); void add_answer(const char *str); void remove_answer(const char *str); }; #endif exult-1.2/usecode/ucdebugging.cc0000644000175000001440000001045307724430454012427 /* * ucdebugging.cc - Debugging-related functions for usecode * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ucdebugging.h" #include "ucinternal.h" #include "stackframe.h" #include "ucfunction.h" #include "utils.h" #include "servemsg.h" #include "debugmsg.h" Breakpoint::Breakpoint(bool once) { this->once = once; id = Breakpoints::getNewID(); } AnywhereBreakpoint::AnywhereBreakpoint() : Breakpoint(true) { } LocationBreakpoint::LocationBreakpoint(int functionid, int ip, bool once) : Breakpoint(once) { this->functionid = functionid; this->ip = ip; } bool LocationBreakpoint::check(Stack_frame *frame) const { return (frame->function->id == functionid) && ((int)(frame->ip - frame->code) == ip); } void LocationBreakpoint::serialize(int fd) const { unsigned char d[13]; d[0] = (unsigned char)(Exult_server::dbg_set_location_bp); unsigned char *dptr = &d[1]; Write4(dptr, functionid); Write4(dptr, ip); Write4(dptr, id); Exult_server::Send_data(fd, Exult_server::usecode_debugging, d, 13); } StepoverBreakpoint::StepoverBreakpoint(Stack_frame* frame) : Breakpoint(true) { call_chain = frame->call_chain; call_depth = frame->call_depth; } bool StepoverBreakpoint::check(Stack_frame *frame) const { return ((frame->call_chain == call_chain && frame->call_depth <= call_depth) || (frame->call_chain < call_chain)); } FinishBreakpoint::FinishBreakpoint(Stack_frame* frame) : Breakpoint(true) { call_chain = frame->call_chain; call_depth = frame->call_depth; } bool FinishBreakpoint::check(Stack_frame *frame) const { return ((frame->call_chain == call_chain && frame->call_depth < call_depth) || (frame->call_chain < call_chain)); } int Breakpoints::lastID = 0; Breakpoints::Breakpoints() { } Breakpoints::~Breakpoints() { std::list::iterator iter; // clear queue for (iter = breaks.begin(); iter != breaks.end(); ++iter) { delete (*iter); } } // returns ID of a (any) breakpoint encountered, or -1 if no breakpoints int Breakpoints::check(Stack_frame* frame) { // check all breakpoints (always check all of them, even if match found) // and delete the matching ones with 'once' set // question: do we really want to delete a breakpoint (with once set) // as soon as it is triggered? (or wait a while until it has been // processed properly?) // also, it might be necessary to return a list of all matching and/or // deleted breakpoints // OTOH, which 'once' breakpoint is hit is generally not interesting, // and also, only one of these will be set, usually. int breakID = -1; std::list::iterator iter; for (iter = breaks.begin(); iter != breaks.end(); ++iter) { if ((*iter)->check(frame)) { breakID = (*iter)->id; if ((*iter)->once) { delete (*iter); (*iter) = 0; } } } breaks.remove((Breakpoint*)0); // delete all NULLs from the list return breakID; } void Breakpoints::add(Breakpoint* breakpoint) { breaks.remove(breakpoint); // avoid double occurences breaks.push_back(breakpoint); } void Breakpoints::remove(Breakpoint* breakpoint) { breaks.remove(breakpoint); } bool Breakpoints::remove(int id) { bool found = false; std::list::iterator iter; for (iter = breaks.begin(); iter != breaks.end(); ++iter) { if ((*iter)->id == id) { found = true; delete (*iter); (*iter) = 0; } } breaks.remove((Breakpoint*)0); // delete all NULLs from the list return found; } void Breakpoints::transmit(int fd) { std::list::iterator iter; for (iter = breaks.begin(); iter != breaks.end(); ++iter) (*iter)->serialize(fd); } exult-1.2/usecode/ucsched.cc0000644000175000001440000004073410040670407011554 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "ucinternal.h" #include "useval.h" #include "ucsched.h" #include "Audio.h" #include "barge.h" #include "game.h" #include "frameseq.h" #include "gamewin.h" #include "gameclk.h" #include "egg.h" #include "actors.h" #include "ucscriptop.h" #include #include using std::cout; using std::endl; using std::hex; using std::setfill; using std::setw; using namespace Ucscript; int Usecode_script::count = 0; Usecode_script *Usecode_script::first = 0; /* * Create for a 'restore'. */ Usecode_script::Usecode_script ( Game_object *item, Usecode_value *cd, int findex, int nhalt, int del ) : obj(item), code(cd), i(0), frame_index(findex), no_halt(nhalt != 0), must_finish(false), delay(del) { cnt = code->get_array_size(); } /* * Create. */ Usecode_script::Usecode_script ( Game_object *o, Usecode_value *cd // May be NULL for empty script. ) : obj(o), code(cd), cnt(0), i(0), frame_index(0), no_halt(false), must_finish(false), delay(0) { if (!code) // Empty? code = new Usecode_value(0, 0); else { cnt = code->get_array_size(); if (!cnt) // Not an array?? (This happens.) { // Create with single element. code = new Usecode_value(1, code); cnt = 1; } } } /* * Delete. */ Usecode_script::~Usecode_script() { delete code; count--; if (next) next->prev = prev; if (prev) prev->next = next; else first = next; } /* * Enter into the time-queue and our own chain. Terminate existing * scripts for this object unless 'dont_halt' is set. */ void Usecode_script::start ( long d // Start after this many msecs. ) { Game_window *gwin = Game_window::get_instance(); int cnt = code->get_array_size();// Check initial elems. for (int i = 0; i < cnt; i++) { int opval0 = code->get_elem(i).get_int_value(); if (opval0 == Ucscript::dont_halt) no_halt = true; else if (opval0 == Ucscript::finish) must_finish = true; else break; } if (!is_no_halt()) // If flag not set, // Remove other entries that aren't // 'no_halt'. Usecode_script::terminate(obj); count++; // Keep track of total. next = first; // Put in chain. prev = 0; if (first) first->prev = this; first = this; //++++ Messes up Moonshade Trial. // gwin->get_tqueue()->add(d + Game::get_ticks(), this, gwin->get_tqueue()->add(d + SDL_GetTicks(), this, (long) gwin->get_usecode()); } /* * Set this script to halt. */ void Usecode_script::halt ( ) { if (!no_halt) i = cnt; } /* * Append instructions. */ void Usecode_script::add(int v1) { code->append(&v1, 1); cnt++; } void Usecode_script::add(int v1, int v2) { int vals[2]; vals[0] = v1; vals[1] = v2; code->append(vals, 2); cnt += 2; } void Usecode_script::add(int v1, const char *str) { int sz = code->get_array_size(); code->resize(sz + 2); (*code)[sz] = v1; (*code)[sz + 1] = str; cnt += 2; } void Usecode_script::add(int *vals, int c) { code->append(vals, cnt); cnt += c; } /* * Search list for one for a given item. * * Output: ->Usecode_script if found, else 0. */ Usecode_script *Usecode_script::find ( Game_object *srch, Usecode_script *last_found // Find next after this. ) { Usecode_script *start = last_found ? last_found->next : first; for (Usecode_script *each = start; each; each = each->next) if (each->obj == srch) return each; // Found it. return (0); } /* * Terminate all scripts for a given object. */ void Usecode_script::terminate ( Game_object *obj ) { Usecode_script *next = 0; for (Usecode_script *each = first; each; each = next) { next = each->next; // Get next in case we delete 'each'. if (each->obj == obj) each->halt(); } } /* * Remove all from global list (assuming they've already been cleared * from the time queue). */ void Usecode_script::clear ( ) { while (first) delete first; } /* * Terminate all scripts for objects that are more than a given distance * from a particular spot. */ void Usecode_script::purge ( Tile_coord spot, int dist // In tiles. ) { Usecode_script *next = 0; Game_window *gwin = Game_window::get_instance(); Usecode_internal *usecode = static_cast( gwin->get_usecode()); for (Usecode_script *each = first; each; each = next) { next = each->next; // Get next in case we delete 'each'. // Only purge if not yet started. if (each->obj && !each->i && each->obj->get_outermost()->get_tile().distance( spot) > dist) { // Force it to halt. each->no_halt = false; if (each->must_finish) { cout << "MUST finish this script" << endl; each->exec(usecode, true); } each->halt(); } } } inline void Usecode_script::activate_egg(Usecode_internal *usecode, Game_object *e) { if (!e || !e->is_egg()) return; int type = ((Egg_object *) e)->get_type(); // Guess: Only certain types: if (type == Egg_object::monster || type == Egg_object::button || type == Egg_object::missile) ((Egg_object *) e)->activate( usecode->gwin->get_main_actor(), true); } /* * Execute an array of usecode, generally one instruction per tick. */ void Usecode_script::handle_event ( unsigned long curtime, // Current time of day. long udata // ->usecode machine. ) { Usecode_internal *usecode = (Usecode_internal *) udata; int delay = exec(usecode, false); if (i < cnt) // More to do? { usecode->gwin->get_tqueue()->add(curtime + delay, this, udata); return; } #if 0 /* ++++Might need this for Test of Love!! */ if (count == 1 && // Last one? GUESSING: objpos.tx != -1) // And valid pos. { usecode->activate_cached(objpos); } #endif delete this; // Hope this is safe. } /* * Execute an array of usecode, generally one instruction per tick. * * Output: Delay for next execution. */ int Usecode_script::exec ( Usecode_internal *usecode, bool finish // If set, keep going to end. ) { Game_window *gwin = usecode->gwin; int delay = gwin->get_std_delay(); // Start with default delay. bool do_another = true; // Flag to keep going. int opcode; // If a 1 follows, keep going. for (; i < cnt && ((opcode = code->get_elem(i).get_int_value()) == 0x1 || do_another); i++) { do_another = finish; switch (opcode) { case cont: // Means keep going without painting. do_another = true; gwin->set_painted(); // Want to paint when done. break; case repeat: // ?? 2 parms, 1st one < 0. { // Loop(offset, cnt). Usecode_value& cntval = code->get_elem(i + 2); int cnt = cntval.get_int_value(); if (cnt <= 0) // Done. i += 2; else { // Decr. and loop. cntval = Usecode_value(cnt - 1); Usecode_value& offval = code->get_elem(i + 1); i += offval.get_int_value() - 1; if (i < -1) // Before start? i = -1; do_another = true; } break; } case repeat2: // Loop with 3 parms.??? { // Loop(offset, cnt1, cnt2?). //Guessing: loop cnt1 each round. use cnt2 as loop var. //This is necessary for loop nesting. //(used in mining machine, orb of the moons) // maybe cnt1 and cnt2 should be swapped... not sure do_another = true; Usecode_value& cntval = code->get_elem(i + 3); Usecode_value& origval = code->get_elem(i + 2); int cnt = cntval.get_int_value(); int orig = origval.get_int_value(); if (cnt > orig) { // ++++ First pass? Set to orig or not? cntval = origval; cnt = orig; } if (cnt <= 0) { // Done. i += 3; cntval = origval; // restore counter } else { // Decr. and loop. cntval = Usecode_value(cnt - 1); Usecode_value& offval = code->get_elem(i + 1); i += offval.get_int_value() - 1; } break; } case nop: // Just a nop. break; case Ucscript::finish: // Flag to finish if deleted. must_finish = true; do_another = true; break; case dont_halt: // ?? Always appears first. // Maybe means "don't let // intrinsic 5c stop it". no_halt = true; // PURE GUESS. do_another = true; break; case delay_ticks: // 1 parm. { // delay before next instruction. Usecode_value& delayval = code->get_elem(++i); // It's # of ticks. delay = gwin->get_std_delay()*delayval.get_int_value(); break; } case delay_hours: // 1 parm., game hours. { Usecode_value& delayval = code->get_elem(++i); delay = delayval.get_int_value(); // Convert to real seconds. delay = (delay*3600)/time_factor; delay *= 1000; // Then to msecs. break; } #if 0 case finish: // Quit if there's already scheduled // code for item? // Or supercede the existing one? break; #endif case Ucscript::remove: // Remove obj. usecode->remove_item(obj); break; case rise: // (For flying carpet. { Tile_coord t = obj->get_tile(); if (t.tz < 10) t.tz++; obj->move(t); break; } case descend: { Tile_coord t = obj->get_tile(); if (t.tz > 0) t.tz--; obj->move(t); break; } case frame: // Set frame. usecode->set_item_frame(obj, code->get_elem(++i).get_int_value()); break; case egg: // Guessing: activate egg. activate_egg(usecode, obj); break; case next_frame_max: // Stop at last frame. { int nframes = obj->get_num_frames(); if (obj->get_framenum() < nframes - 1) usecode->set_item_frame(obj, 1+obj->get_framenum()); break; } case next_frame: { int nframes = obj->get_num_frames(); usecode->set_item_frame(obj, (1 + obj->get_framenum())%nframes); break; } case prev_frame_min: if (obj->get_framenum() > 0) usecode->set_item_frame(obj, obj->get_framenum() - 1); break; case prev_frame: { int nframes = obj->get_num_frames(); int pframe = obj->get_framenum() - 1; usecode->set_item_frame(obj, (pframe + nframes)%nframes); break; } case say: // Say string. { Usecode_value& strval = code->get_elem(++i); Usecode_value objval(obj); usecode->item_say(objval, strval); break; } case Ucscript::step: // Parm. is dir. (0-7). 0=north. { // Get dir. Usecode_value& val = code->get_elem(++i); // It may be 0x3x. step(usecode, val.get_int_value()&7); //+++++Might be a 2nd parm, diff in altitude. // ++++++++++Investigate. break; } case music: // Unknown. { Usecode_value& val = code->get_elem(++i); Audio::get_ptr()->start_music(val.get_int_value(), false); break; } case Ucscript::usecode: // Call? { Usecode_value& val = code->get_elem(++i); int fun = val.get_int_value(); // Watch for eggs: Usecode_internal::Usecode_events ev = Usecode_internal::internal_exec; if (obj && obj->is_egg() #if 0 //removed 20011226, breaks serpent gates in SI without SS -wjp && ((Egg_object *)obj)->get_type() == Egg_object::usecode #endif ) ev = Usecode_internal::egg_proximity; // And for telekenesis spell fun: else if (fun == usecode->telekenesis_fun) { ev = Usecode_internal::double_click; usecode->telekenesis_fun = -1; } usecode->call_usecode(fun, obj, ev); break; } case Ucscript::usecode2:// Call(fun, eventid). { Usecode_value& val = code->get_elem(++i); int evid = code->get_elem(++i).get_int_value(); usecode->call_usecode(val.get_int_value(), obj, (Usecode_internal::Usecode_events) evid); break; } case speech: // Play speech track. { Usecode_value& val = code->get_elem(++i); int track = val.get_int_value(); if (track >= 0) Audio::get_ptr()->start_speech(track); } case sfx: // Play sound effect! { Usecode_value& val = code->get_elem(++i); Audio::get_ptr()->play_sound_effect( val.get_int_value()); break; } case face_dir: // Parm. is dir. (0-7). 0=north. { // Look in that dir. Usecode_value& val = code->get_elem(++i); // It may be 0x3x. Face dir? int dir = val.get_int_value()&7; Actor *npc = obj->as_actor(); if (npc) npc->set_usecode_dir(dir); usecode->set_item_frame(obj, obj->get_dir_framenum( dir, obj->get_framenum()), 1, 1); frame_index = 0;// Reset walking frame index. break; } case hit: // Hit(hps, ??). { Usecode_value hps = code->get_elem(++i); Usecode_value unk = code->get_elem(++i); Actor *act = usecode->as_actor(obj); if (act) // ++++Should apply to any object. act->reduce_health(hps.get_int_value()); break; } case resurrect: { Dead_body *body = (Dead_body *) obj; Actor *act = gwin->get_npc(body->get_live_npc_num()); if (act) act->resurrect(body); break; } default: // Frames with dir. U7-verified! if (opcode >= 0x61 && opcode <= 0x70) { // But don't show empty frames. Actor *npc = obj->as_actor(); npc->clear_rest_time(); int v = obj->get_dir_framenum( npc ? npc->get_usecode_dir() : 0, opcode - 0x61); usecode->set_item_frame(obj, v, 1, 1); } else if (opcode >= 0x30 && opcode < 0x38) { // Step in dir. opcode&7. step(usecode, opcode&7); do_another = true; // Guessing. } else { cout << "Und sched. opcode " << hex << "0x" << setfill((char)0x30) << setw(2) << opcode << std::dec << endl; do_another = true; // Don't let it delay us. } break; } } return delay; } /* * Step in given direction. */ void Usecode_script::step ( Usecode_internal *usecode, int dir // 0-7. ) { int frame = obj->get_framenum(); Barge_object *barge; Actor *act = usecode->as_actor(obj); if (act) { Frames_sequence *frames = act->get_frames(dir); // Get frame (updates frame_index). frame = frames->get_next(frame_index); Tile_coord tile = obj->get_tile().get_neighbor(dir); obj->step(tile, frame); } else if ((barge = obj->as_barge()) != 0) { for (int i = 0; i < 4; i++) { Tile_coord t = obj->get_tile().get_neighbor( dir); obj->step(t, 0); } } } /* * Save (serialize). * * Output: Length written, or -1 if error. */ int Usecode_script::save ( unsigned char *buf, int buflen ) { // Get delay to when due. long when = Game_window::get_instance()->get_tqueue()->find_delay( this, SDL_GetTicks()); if (when < 0) return -1; uint8 *ptr = buf; Write2(ptr, cnt); // # of values we'll store. Write2(ptr, i); // Current spot. for (int j = 0; j < cnt; j++) { Usecode_value& val = code->get_elem(j); int len = val.save(ptr, buflen - (ptr - buf)); if (len < 0) return -1; ptr += len; } if (buflen - (ptr - buf) < 8) // Enough room left? return -1; Write2(ptr, frame_index); Write2(ptr, no_halt ? 1 : 0); Write4(ptr, when); return (ptr - buf); } /* * Restore (serialize). * * Output: ->entry, which is also stored in our global chain, but is NOT * added to the time queue yet. */ Usecode_script *Usecode_script::restore ( Game_object *item, // Object this is executed for. unsigned char *buf, int buflen ) { uint8 *ptr = buf; int cnt = Read2(ptr); // Get # instructions. int curindex = Read2(ptr); // Where it is. // Create empty array. Usecode_value *code = new Usecode_value(cnt, 0); for (int i = 0; i < cnt; i++) { Usecode_value& val = code->get_elem(i); if (!val.restore(ptr, buflen - (ptr - buf))) { delete code; return 0; } } if (buflen - (ptr - buf) < 8) // Enough room left? { delete code; return 0; } int frame_index = Read2(ptr); int no_halt = Read2(ptr); int delay = Read4(ptr); Usecode_script *scr = new Usecode_script(item, code, frame_index, no_halt, delay); scr->i = curindex; // Set index. return scr; } /* * Print for debugging. */ void Usecode_script::print ( std::ostream& out ) { out << hex << "Obj = 0x" << setfill((char)0x30) << setw(2) << (void *) obj << ": " "("; for (int i = 0; i < cnt; i++) { if (i > 0) out << ", "; code->get_elem(i).print(out); } out <<") = "; out << std::dec; } exult-1.2/usecode/useval.h0000644000175000001440000001242307724430454011304 /* * useval.h - Values used in Usecode interpreter. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef USEVAL_H #define USEVAL_H 1 #include #include #include // STL container #include // STL container #include // STL string class Game_object; /* * A value that we store can be an integer, string, or array. */ class Usecode_value { public: enum Val_type // The types: { int_type = 0, string_type = 1, // Allocated string. array_type = 2, end_of_array_type = 3, // Marks end of array. pointer_type = 4 }; private: Val_type type; // Type stored here. union { long intval; char *str; Usecode_value *array; Game_object *ptr; } value; bool undefined; // Count array elements. static int count_array(const Usecode_value& val); public: inline Usecode_value() : type(int_type), undefined(true) { value.intval = 0; } inline Usecode_value(int ival) : type(int_type), undefined(false) { value.intval = ival; } Usecode_value(const char *s); // Create array with 1st element. Usecode_value(int size, Usecode_value *elem0) : type(array_type), undefined(false) { value.array = new Usecode_value[size + 1]; value.array[size].type = end_of_array_type; if (elem0) value.array[0] = *elem0; } Usecode_value(Game_object *ptr) : type(pointer_type), undefined(false) { value.ptr = ptr; } ~Usecode_value(); Usecode_value& operator=(const Usecode_value& v2); Usecode_value& operator=(const char *str); // Copy ctor. inline Usecode_value(const Usecode_value& v2) : type(int_type) { *this = v2; } Usecode_value operator+(const Usecode_value& v2); // Comparator. void push_back(int); bool operator==(const Usecode_value& v2) const; bool operator!=(const Usecode_value& v2) const { return !(*this == v2); } inline Val_type get_type() const { return type; } int get_array_size() const // Get size of array. { return (type == array_type) ? count_array(*this) : 0; } bool is_array() const { return (type == array_type); } bool is_int() const { return (type == int_type); } bool is_ptr() const { return (type == pointer_type); } long get_int_value() const // Get integer value. { #ifdef DEBUG if (type == pointer_type || (type == int_type && (value.intval > 0x10000 || value.intval < -0x10000))) std::cerr << "Probable attempt at getting int value of pointer!!" << std::endl; #endif return ((type == int_type) ? value.intval : 0); } Game_object* get_ptr_value() const // Get pointer value. { return ((type == pointer_type) ? value.ptr : 0); } // Get string value. const char *get_str_value() const { return ((type == string_type) ? value.str : 0); } long need_int_value() const { // Convert strings. const char *str = get_str_value(); return str ? std::atoi(str) : ((type == array_type && get_array_size()) ? value.array[0].need_int_value() // Pointer = ref. : (type == pointer_type ? (value.intval&0x7ffffff) : get_int_value())); } // Add array element. (No checking!) void put_elem(int i, Usecode_value& val) { value.array[i] = val; } // Get an array element. inline Usecode_value& get_elem(int i) const { static Usecode_value zval(0); // assert(type == array_type);//+++++Testing. return (type == array_type) ? value.array[i] : zval; } inline Usecode_value& operator[](int i) { assert(type == array_type); return value.array[i]; } // Get array elem. 0, or this. inline Usecode_value& get_elem0() { return (type == array_type) ? value.array[0] : *this; } inline bool is_false() const // Represents a FALSE value? { switch(type) { case int_type: return value.intval == 0; case pointer_type: return value.ptr == NULL; case array_type: return value.array[0].type == end_of_array_type; default: return false; } } inline bool is_true() const { return !is_false(); } inline bool is_undefined() const { return undefined; } int resize(int new_size); // Resize array. // Look in array for given value. int find_elem(const Usecode_value& val); // Concat. to end of this array. Usecode_value& concat(Usecode_value& val2); void append(int *vals, int cnt);// Append integer values. // Add value(s) to an array. int add_values(int index, Usecode_value& val2); void print(std::ostream& out, bool shortformat=false); // Print in ASCII. // Save/restore. int save(unsigned char *buf, int len); bool restore(unsigned char *& ptr, int len); }; std::ostream& operator<<(std::ostream& out, Usecode_value& val); #endif exult-1.2/usecode/stackframe.cc0000644000175000001440000000526407724430454012270 /* * stackframe.cc - a usecode interpreter stack frame * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "stackframe.h" #include "useval.h" #include "ucinternal.h" #include "utils.h" #include "ucfunction.h" int Stack_frame::LastCallChainID = 0; Stack_frame::Stack_frame(Usecode_function *fun, int event, Game_object *caller, int chain, int depth) : function(fun), ip(0), data(0), externs(0), code(0), endp(0), line_number(-1), call_chain(chain), call_depth(depth), num_externs(0), num_args(0), num_vars(0), locals(0), eventid(event), caller_item(caller), save_sp(0) { ip = function->code; endp = ip + function->len; int data_len; if (!fun->extended) data_len = Read2(ip); // Get length of (text) data. else data_len = (sint32)(Read4(ip)); // 32 bit lengths data = ip; ip += data_len; // Point past text. num_args = Read2(ip); // # of args. this function takes. // Local variables follow args. num_vars = Read2(ip); // Allocate locals. int num_locals = num_vars + num_args; locals = new Usecode_value[num_locals]; num_externs = Read2(ip); // external function references externs = ip; ip += 2 * num_externs; // now points to actual code code = ip; } Stack_frame::~Stack_frame() { delete[] locals; } std::ostream& operator<<(std::ostream& out, Stack_frame& frame) { // #depth: 0xIP in 0xfunid ( obj=..., event=..., arguments ) // TODO: include any debugging info // #depth: 0xIP in functionname (obj=...,event=..., arg1name=..., ...) out << "#" << frame.call_depth << ": 0x" << std::hex << std::setw(4) << std::setfill('0') << (int)(frame.ip - frame.code) << " in 0x" << std::setw(4) << frame.function->id << "(obj=" << std::setw(8) << (long)frame.caller_item << ",ev=" << frame.eventid << std::setfill(' ') << std::dec; for (int i=0; i < frame.num_args; i++) out << ", " << frame.locals[i]; out << ")"; return out; } exult-1.2/usecode/debugserver.cc0000644000175000001440000001316607724430454012465 /* * debugserver.cc: handle usecode debugging messages from client * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #if (defined(USE_EXULTSTUDIO) && defined(USECODE_DEBUGGER)) #include #include #include "servemsg.h" #include "server.h" #include "gamewin.h" #include "ucinternal.h" #include "debugserver.h" #include "debugmsg.h" #include "ucdebugging.h" #include "utils.h" #include "stackframe.h" #include "ucserial.h" #include "useval.h" #include "ucfunction.h" // message handler that only handles debugging messages. void Handle_client_debug_message(int& fd) { unsigned char data[Exult_server::maxlength]; Exult_server::Msg_type id; int datalen = Exult_server::Receive_data(fd, id, data, sizeof(data)); if (datalen < 0) return; switch (id) { case Exult_server::usecode_debugging: Handle_debug_message(&data[0], datalen); break; default: // maybe reply something like "unable to handle message" ? break; } } void Handle_debug_message(unsigned char* data, int datalen) { Usecode_machine *ucm = Game_window::get_instance()->get_usecode(); Usecode_internal *uci = dynamic_cast(ucm); if (uci == 0) return; // huh? Exult_server::Debug_msg_type id = (Exult_server::Debug_msg_type)data[0]; unsigned char *ptr = data; if (uci->is_on_breakpoint()) { // accept extra messages now switch(id) { case Exult_server::dbg_continue: uci->set_breakpoint_action(0); break; case Exult_server::dbg_stepinto: uci->set_breakpoint_action(0); uci->set_breakpoint(); break; case Exult_server::dbg_stepover: uci->set_breakpoint_action(0); uci->dbg_stepover(); break; case Exult_server::dbg_finish: uci->set_breakpoint_action(0); uci->dbg_finish(); break; case Exult_server::dbg_get_callstack: { unsigned char d[3]; d[0] = (unsigned char)Exult_server::dbg_callstack; unsigned char* ptr = &d[1]; int callstacksize = uci->get_callstack_size(); Write2(ptr, callstacksize); Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, d, 3); for (int i=0; i < callstacksize; i++) { Stack_frame *frame = uci->get_stackframe(i); Stack_frame_out(client_socket, frame->function->id, (int)(frame->ip - frame->code), frame->call_chain, frame->call_depth, frame->eventid, (long)frame->caller_item, frame->num_args, frame->num_vars, frame->locals); } break; } case Exult_server::dbg_get_stack: { Usecode_value zeroval((int)0); unsigned char data[Exult_server::maxlength]; unsigned char* ptr = &data[0]; *ptr++ = (unsigned char)Exult_server::dbg_stack; int stacksize = uci->get_stack_size(); Write2(ptr, stacksize); int remaining = Exult_server::maxlength - 3; for (int i=0; i < stacksize; i++) { Usecode_value* val = uci->peek_stack(i); int vallen = -1; if (val) { vallen = val->save(ptr, remaining); } if (vallen == -1) { if (remaining >= 5) vallen = zeroval.save(ptr, remaining); std::cerr << "Error: stack larger than max. message!" << std::endl; } if (vallen != -1) { remaining -= vallen; ptr += vallen; } } Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, data, Exult_server::maxlength - remaining); break; } default: break; } } // these messages can always be handled switch(id) { case Exult_server::dbg_break: uci->set_breakpoint(); break; case Exult_server::dbg_get_status: { unsigned char c; if (uci->is_on_breakpoint()) { c = (unsigned char)Exult_server::dbg_on_breakpoint; } else { c = (unsigned char)Exult_server::dbg_continuing; } Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, &c, 1); break; } case Exult_server::dbg_set_location_bp: { ptr++; int funcid = Read4(ptr); int ip = Read4(ptr); std::cout << "Setting breakpoint at " << std::hex << std::setfill('0') << std::setw(4) << funcid << ", " << std::setw(4) << ip << std::setfill(' ') << std::dec << std::endl; // +++++ check for duplicates? int breakpoint_id = uci->set_location_breakpoint(funcid, ip); unsigned char d[13]; d[0] = (unsigned char)(Exult_server::dbg_set_location_bp); unsigned char *dptr = &d[1]; Write4(dptr, funcid); Write4(dptr, ip); Write4(dptr, breakpoint_id); Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, d, 13); break; } case Exult_server::dbg_clear_breakpoint: { ptr++; int breakpoint_id = Read4(ptr); bool ok = uci->clear_breakpoint(breakpoint_id); if (ok) { // reply Exult_server::Send_data(client_socket, Exult_server::usecode_debugging, data, 5); } break; } case Exult_server::dbg_get_breakpoints: { uci->transmit_breakpoints(client_socket); break; } default: break; } } #endif exult-1.2/usecode/useval.cc0000644000175000001440000002620210054030577011432 /* * useval.cc - Values used in Usecode interpreter. * * Copyright (C) 1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX #include #include #include #include #include #include #endif #include "useval.h" #include "utils.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::dec; using std::hex; using std::memcpy; using std::ostream; using std::setfill; using std::setw; using std::strcmp; using std::strlen; #endif /* * Get array size. */ int Usecode_value::count_array ( const Usecode_value& val ) { int i; for (i = 0; val.value.array[i].type != end_of_array_type; i++) ; return (i); } /* * Destructor * */ Usecode_value::~Usecode_value() { if (type == array_type) delete [] value.array; else if (type == string_type) delete [] value.str; } /* * Copy another to this. */ Usecode_value& Usecode_value::operator= ( const Usecode_value& v2 ) { if (&v2 == this) return *this; if (type == array_type) delete [] value.array; else if (type == string_type) delete [] value.str; type = v2.type; // Assign new values. if (type == int_type) value.intval = v2.value.intval; else if (type == pointer_type) value.ptr = v2.value.ptr; else if (type == string_type) value.str = v2.value.str ? newstrdup(v2.value.str) : 0; else if (type == array_type) { int tempsize = 1+count_array(v2); value.array = new Usecode_value[tempsize]; int i = 0; do value.array[i] = v2.value.array[i]; while (value.array[i++].type != end_of_array_type); } undefined = v2.undefined; return *this; } /* * Set this to (a copy of) a string. */ Usecode_value& Usecode_value::operator= ( const char *str ) { if (type == array_type) delete [] value.array; else if (type == string_type) delete [] value.str; type = string_type; value.str = str ? newstrdup(str) : 0; return *this; } /* * Create a string value. */ Usecode_value::Usecode_value ( const char *s ) : type(string_type), undefined(false) { value.str = s ? newstrdup(s) : 0; } /* * Resize array (or turn single element into an array). The new values * are (integer) 0. * * Output: Always true. */ int Usecode_value::resize ( int new_size ) { if (type != array_type) // Turn it into an array. { Usecode_value elem(*this); *this = Usecode_value(new_size, &elem); return (1); } int size = count_array(*this); // Get current size. if (new_size == size) return (1); // Nothing to do. Usecode_value *newvals = new Usecode_value[new_size + 1]; newvals[new_size].type = end_of_array_type; // Move old values over. int cnt = new_size < size ? new_size : size; for (int i = 0; i < cnt; i++) newvals[i] = value.array[i]; delete [] value.array; // Delete old list. value.array = newvals; // Store new. return (1); } void Usecode_value::push_back(int i) { resize(count_array(*this)+1); value.array[count_array(*this)-1]=Usecode_value(i); } /* * Comparator. * * Output: 1 if they match, else 0. */ bool Usecode_value::operator== ( const Usecode_value& v2 ) const { if (&v2 == this) return true; // Same object. if (type == int_type) // Might be ptr==0. return (v2.type == int_type || v2.type == pointer_type) ? (value.intval == v2.value.intval) // Okay if 0==empty array. : v2.type == array_type && !value.intval && !v2.get_array_size(); else if (type == pointer_type) // Might be ptr==0. { // Or ptr == array. Test elem. 0. if (v2.type == pointer_type || v2.type == int_type) return (value.ptr == v2.value.ptr); else if (v2.type == array_type && v2.get_array_size()) { const Usecode_value& val2 = v2.value.array[0]; return (value.ptr == val2.value.ptr); } else return false; } else if (type == array_type) { if (v2.type == int_type) return !get_array_size() && !v2.get_int_value(); else if (v2.type == pointer_type && get_array_size()) { Usecode_value& v = get_elem(0); return v2.value.ptr == v.value.ptr; } if (v2.type != array_type) return false; int cnt = get_array_size(); if (cnt != v2.get_array_size()) return false; for (int i = 0; i < cnt; i++) { Usecode_value& e1 = get_elem(i); const Usecode_value& e2 = v2.get_elem(i); if (!(e1 == e2)) return false; } return true; // Arrays matched. } else if (type == string_type) return (v2.type == string_type && strcmp(value.str, v2.value.str) == 0); else return false; } /* * Search an array for a given value. * * Output: Index if found, else -1. */ int Usecode_value::find_elem ( const Usecode_value& val ) { if (type != array_type) return (-1); // Not an array. int i; for (i = 0; value.array[i].type != end_of_array_type; i++) if (value.array[i] == val) return (i); return (-1); } /* * Concatenate another value onto this. * * Output: This. */ Usecode_value& Usecode_value::concat ( Usecode_value& val2 // Concat. val2 onto end. ) { int size; // Size of result. if (type != array_type) // Not an array? Create one. { // Current value becomes 1st elem. Usecode_value tmp(1, this); *this = tmp; size = 1; } else size = get_array_size(); if (val2.type != array_type) // Appending a single value? { resize(size + 1); put_elem(size, val2); } else // Appending an array. { int size2 = val2.get_array_size(); resize(size + size2); for (int i = 0; i < size2; i++) put_elem(size + i, val2.get_elem(i)); } return (*this); } /* * Append a list of integer values. */ void Usecode_value::append ( int *vals, int cnt ) { assert(type == array_type); int sz = get_array_size(); resize(sz + cnt); for (int i = 0; i < cnt; i++) value.array[sz + i].value.intval = vals[i]; } /* * Given an array and an index, and a 2nd value, add the new value at that * index, or if the new value is an array itself, add its values. * * Output: # elements added. */ int Usecode_value::add_values ( int index, Usecode_value& val2 ) { int size = get_array_size(); if (!val2.is_array()) // Simple case? { if (index >= size) resize(index + 1); put_elem(index, val2); return (1); } // Add each element. int size2 = val2.get_array_size(); if (index + size2 > size) resize(index + size2); for (int i = 0; i < size2; i++) put_elem(index++, val2.get_elem(i)); return (size2); // Return # added. } /* * Print in ASCII. */ void Usecode_value::print ( ostream& out, bool shortformat ) { switch ((Val_type) type) { case int_type: out << hex << setfill((char)0x30) << setw(4); out << (value.intval&0xffff); out << dec; break; case pointer_type: out << hex << setfill((char)0x30) << setw(8); out << (long)value.ptr; out << dec; break; case string_type: out << '"' << value.str << '"'; break; case array_type: { out << "[ "; int i; for (i = 0; value.array[i].type != end_of_array_type; i++) { if (!shortformat || i < 2) { if (i) out << ", "; value.array[i].print(out); } } if (shortformat && i > 2) out << ", ... (size " << i << ")"; out << " ]"; } break; default: break; } } Usecode_value Usecode_value::operator+(const Usecode_value& v2) { char buf[300]; Usecode_value& v1 = *this; Usecode_value sum(0); if (v1.is_undefined()) { sum = v2; } else if (v2.is_undefined()) { sum = v1; } else if (v1.get_type() == Usecode_value::int_type) { if (v2.get_type() == Usecode_value::int_type) { sum = Usecode_value(v1.get_int_value() + v2.get_int_value()); } else if (v2.get_type() == Usecode_value::string_type) { snprintf(buf, 300, "%ld%s", v1.get_int_value(), v2.get_str_value()); sum = Usecode_value(buf); } else { sum = v1; } } else if (v1.get_type() == Usecode_value::string_type) { if (v2.get_type() == Usecode_value::int_type) { snprintf(buf, 300, "%s%ld", v1.get_str_value(), v2.get_int_value()); sum = Usecode_value(buf); } else if (v2.get_type() == Usecode_value::string_type) { snprintf(buf, 300, "%s%s", v1.get_str_value(), v2.get_str_value()); sum = Usecode_value(buf); } else { sum = v1; } } return sum; } /* * Serialize out. * * Output: # bytes stored, or -1 if error. */ int Usecode_value::save ( unsigned char *buf, int buflen ) { uint8 *ptr = buf; switch ((Val_type) type) { case int_type: if (buflen < 5) return -1; *ptr++ = type; Write4(ptr, value.intval); break; case pointer_type: if (buflen < 5) return -1; *ptr++ = type; Write4(ptr, (int)value.ptr); break; case string_type: { int len = std::strlen(value.str); if (buflen < len + 3) return -1; *ptr++ = type; Write2(ptr, len); std::memcpy(ptr, value.str, len); ptr += len; break; } case array_type: { if (buflen < 3) return -1; *ptr++ = type; int len = count_array(*this); Write2(ptr, len); // first length, then length Usecode_values int remaining = buflen - 3; for (int i=0; i < len; i++) { int retval = value.array[i].save(ptr, remaining); if (retval == -1) return -1; ptr += retval; remaining -= retval; } break; } default: return -1; } return (ptr - buf); } /* * Serialize in. Assumes 'this' contains no data yet. * * Output: False if error. */ bool Usecode_value::restore ( unsigned char *& ptr, // Ptr. to data. Updated past it. int buflen ) { undefined = false; type = (Val_type) *ptr++; switch (type) { case int_type: if (buflen < 5) return false; value.intval = Read4(ptr); return true; case pointer_type: if (buflen < 5) return false; value.ptr = (Game_object*)Read4(ptr); //DON'T dereference this pointer! // Maybe add a new type "serialized_pointer" to prevent "accidents"? return true; case string_type: { int len = Read2(ptr); if (buflen < len + 3) return false; value.str = new char[len + 1]; std::memcpy(value.str, ptr, len); value.str[len] = 0; ptr += len; return true; } case array_type: { if (buflen < 3) return false; int len = Read2(ptr); int remaining = buflen - 3; // already read one byte *this = Usecode_value(len, 0); // create array for (int i=0; i < len; i++) { uint8* t = ptr; bool retval = value.array[i].restore(ptr, remaining); remaining -= (ptr - t); if (!retval) return false; } return true; } default: return false; } } ostream& operator<<(ostream& out, Usecode_value& val) { val.print(out, true); return out; } exult-1.2/usecode/ucfunction.h0000644000175000001440000000274507732251221012160 /* * ucfunction.h - Usecode function * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UCFUNCTION_H #define _UCFUNCTION_H #include #include "useval.h" #include "vec.h" class Usecode_function { public: int id; // The function #. (Appears to be the // game item # the function gets // called for.) Usecode_function *orig; // If this was from 'patch', orig will // be the function this replaced (if // it existed). int len; // Length. bool extended; // is this an 'extented' function? (aka 32 bit function) unsigned char *code; // The code. Exult_vector statics; // Local statics. // Create from file. Usecode_function(std::istream& file); inline ~Usecode_function() { delete [] code; } }; #endif exult-1.2/usecode/intrinsics.cc0000644000175000001440000021624310054030577012326 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Audio.h" #include "Book_gump.h" #include "Gump.h" #include "Gump_manager.h" #include "Scroll_gump.h" #include "Sign_gump.h" #include "items.h" #include "barge.h" #include "bodies.h" #include "cheat.h" #include "chunks.h" #include "conversation.h" #include "effects.h" #include "exult.h" #include "game.h" #include "gamewin.h" #include "gamemap.h" #include "gameclk.h" #include "keyring.h" #include "mouse.h" #include "rect.h" #include "schedule.h" #include "spellbook.h" #include "ucinternal.h" #include "ucsched.h" #include "useval.h" #include "virstone.h" #include "monsters.h" #include "egg.h" #include "monstinf.h" #include "actions.h" #include "ucscriptop.h" #include "ucfunction.h" #include "palette.h" #include "stackframe.h" #include "party.h" #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::rand; using std::strchr; #endif Barge_object *Get_barge (Game_object *obj); extern Usecode_value no_ret; static Game_object *sailor = 0; // The current barge captain. Maybe // this needs to be saved/restored. #define PARTY_MAX (sizeof(party)/sizeof(party[0])) #define USECODE_INTRINSIC(NAME) Usecode_value Usecode_internal:: UI_## NAME (int event,int intrinsic,int num_parms,Usecode_value parms[12]) USECODE_INTRINSIC(NOP) { return(no_ret); } USECODE_INTRINSIC(UNKNOWN) { // Unhandled(intrinsic, num_parms, parms); return(no_ret); } USECODE_INTRINSIC(get_random) { int range = parms[0].get_int_value(); if (range == 0) { Usecode_value u(0); return(u); } Usecode_value u=(1 + (rand() % range)); return(u); } USECODE_INTRINSIC(execute_usecode_array) { COUT("Executing intrinsic 1"); // Start on next tick. create_script(parms[0], parms[1], 1); Usecode_value u(1); return(u); } USECODE_INTRINSIC(delayed_execute_usecode_array) { // Delay = .20 sec.? // +++++Special problem with inf. loop: if (Game::get_game_type() == BLACK_GATE && event == internal_exec && parms[1].get_array_size() == 3 && parms[1].get_elem(2).get_int_value() == 0x6f7) return(no_ret); int delay = parms[2].get_int_value(); create_script(parms[0], parms[1], delay*gwin->get_std_delay()); COUT("Executing intrinsic 2"); Usecode_value u(1); return(u); } USECODE_INTRINSIC(show_npc_face) { show_npc_face(parms[0], parms[1]); return(no_ret); } USECODE_INTRINSIC(remove_npc_face) { remove_npc_face(parms[0]); return(no_ret); } USECODE_INTRINSIC(add_answer) { conv->add_answer(parms[0]); // user_choice = 0; return(no_ret); } USECODE_INTRINSIC(remove_answer) { conv->remove_answer(parms[0]); // Commented out 'user_choice = 0' 8/3/00 for Tseramed conversation. // user_choice = 0; return(no_ret); } USECODE_INTRINSIC(push_answers) { conv->push_answers(); return(no_ret); } USECODE_INTRINSIC(pop_answers) { if(!conv->stack_empty()) { conv->pop_answers(); user_choice = 0; // Added 7/24/2000. } return(no_ret); } USECODE_INTRINSIC(clear_answers) { conv->clear_answers(); return(no_ret); } USECODE_INTRINSIC(select_from_menu) { user_choice = 0; const char *choice = get_user_choice(); user_choice = 0; Usecode_value u(choice); return(u); } USECODE_INTRINSIC(select_from_menu2) { // Return index (1-n) of choice. user_choice = 0; Usecode_value val(get_user_choice_num() + 1); user_choice = 0; return(val); } USECODE_INTRINSIC(input_numeric_value) { // Ask for # (min, max, step, default). Be sure to show conversation. Usecode_value ret(gumpman->prompt_for_number( parms[0].get_int_value(), parms[1].get_int_value(), parms[2].get_int_value(), parms[3].get_int_value(), conv)); conv->clear_text_pending(); // Answered a question. return(ret); } USECODE_INTRINSIC(set_item_shape) { // Set item shape. set_item_shape(parms[0], parms[1]); return(no_ret); } USECODE_INTRINSIC(find_nearest) { // Think it rets. nearest obj. near parm0. Usecode_value u(find_nearest(parms[0], parms[1], parms[2])); return(u); } USECODE_INTRINSIC(die_roll) { // Rand. # within range. int low = parms[0].get_int_value(); int high = parms[1].get_int_value(); if (low > high) { int tmp = low; low = high; high = tmp; } int val = (rand() % (high - low + 1)) + low; Usecode_value u(val); return(u); } USECODE_INTRINSIC(get_item_shape) { Game_object *item = get_item(parms[0]); // Want the actual, not polymorph'd. Actor *act = as_actor(item); return Usecode_value(item == 0 ? 0 : (act ? act->get_shape_real() : item->get_shapenum())); } USECODE_INTRINSIC(get_item_frame) { // Returns frame without rotated bit. Game_object *item = get_item(parms[0]); // Don't count rotated frames. return Usecode_value(item == 0 ? 0 : item->get_framenum()&31); } USECODE_INTRINSIC(set_item_frame) { // Set frame, but don't change rotated bit. //++++++++Seems like in BG, this should be the same as set_item_frame_rot()?? set_item_frame(get_item(parms[0]), parms[1].get_int_value()); return(no_ret); } USECODE_INTRINSIC(get_item_quality) { Game_object *obj = get_item(parms[0]); if (!obj) return Usecode_value(0); Shape_info& info = obj->get_info(); return Usecode_value(info.has_quality() ? obj->get_quality() : 0); } USECODE_INTRINSIC(set_item_quality) { // Guessing it's // set_quality(item, value). int qual = parms[1].get_int_value(); if (qual == c_any_qual) // Leave alone (happens in SI)? return Usecode_value(1); Game_object *obj = get_item(parms[0]); if (obj) { Shape_info& info = obj->get_info(); if (info.has_quality()) { obj->set_quality((unsigned int) qual); return Usecode_value(1); } } return Usecode_value(0); } USECODE_INTRINSIC(get_item_quantity) { // Get quantity of an item. // Get_quantity(item, mystery). Usecode_value ret(0); Game_object *obj = get_item(parms[0]); if (obj) ret = Usecode_value(obj->get_quantity()); return(ret); } USECODE_INTRINSIC(set_item_quantity) { // Set_quantity (item, newcount). Rets 1 iff item.has_quantity(). Usecode_value ret(0); Game_object *obj = get_item(parms[0]); int newquant = parms[1].get_int_value(); if (obj && obj->get_info().has_quantity()) { ret = Usecode_value(1); // If not in world, don't delete! if (newquant == 0 && obj->get_cx() == 255) return ret; int oldquant = obj->get_quantity(); int delta = newquant - oldquant; // Note: This can delete the obj. int newdelta = obj->modify_quantity(delta); } return(ret); } USECODE_INTRINSIC(get_object_position) { // Takes itemref. ?Think it rets. // hotspot coords: (x, y, z). Game_object *obj = get_item(parms[0]); Tile_coord c(0, 0, 0); if (obj) // (Watch for animated objs' wiggles.) c = obj->get_outermost()->get_original_tile_coord(); Usecode_value vx(c.tx), vy(c.ty), vz(c.tz); Usecode_value arr(3, &vx); arr.put_elem(1, vy); arr.put_elem(2, vz); return(arr); } USECODE_INTRINSIC(get_distance) { // Distance from parm[0] -> parm[1]. Guessing how it's computed. Game_object *obj0 = get_item(parms[0]); Game_object *obj1 = get_item(parms[1]); Usecode_value u((obj0 && obj1) ? obj0->get_outermost()->get_tile().distance( obj1->get_outermost()->get_tile()) : 0); return(u); } USECODE_INTRINSIC(find_direction) { // Direction from parm[0] -> parm[1]. // Rets. 0-7. Is 0 east? Usecode_value u=find_direction(parms[0], parms[1]); return(u); } USECODE_INTRINSIC(get_npc_object) { // Takes -npc. Returns object, or array of objects. Usecode_value& v = parms[0]; if (v.is_array()) // Do it for each element of array. { int sz = v.get_array_size(); Usecode_value ret(sz, 0); for (int i = 0; i < sz; i++) { Usecode_value elem(get_item(v.get_elem(i))); ret.put_elem(i, elem); } return ret; } Game_object *obj = get_item(parms[0]); Usecode_value u(obj); return(u); } USECODE_INTRINSIC(get_schedule_type) { // GetSchedule(npc). Rets. schedtype. Actor *npc = as_actor(get_item(parms[0])); if (!npc) return Usecode_value(0); Schedule *schedule = npc->get_schedule(); int sched = schedule ? schedule->get_actual_type(npc) : npc->get_schedule_type(); // Path_run_usecode? (This is to fix // a bug in the Fawn Trial.) //+++++Should be a better way to check. if (Game::get_game_type() == SERPENT_ISLE && npc->get_action() && npc->get_action()->as_usecode_path()) // Give a 'fake' schedule. sched = Schedule::walk_to_schedule; Usecode_value u(sched); return(u); } USECODE_INTRINSIC(set_schedule_type) { // SetSchedule?(npc, schedtype). // Looks like 15=wait here, 11=go home, 0=train/fight... This is the // 'bNum' field in schedules. Actor *npc = as_actor(get_item(parms[0])); if (npc) { int newsched = parms[1].get_int_value(); npc->set_schedule_type(newsched); // Taking Avatar out of combat? if (npc == gwin->get_main_actor() && gwin->in_combat() && newsched != Schedule::combat) // End combat mode (for L.Field). { Audio::get_ptr()->stop_music(); gwin->toggle_combat(); } } return(no_ret); } USECODE_INTRINSIC(add_to_party) { // NPC joins party. Actor *npc = as_actor(get_item(parms[0])); if (!partyman->add_to_party(npc)) return no_ret; // Can't add. npc->set_schedule_type(Schedule::follow_avatar); // cout << "NPC " << npc->get_npc_num() << " added to party." << endl; return no_ret; } USECODE_INTRINSIC(remove_from_party) { // NPC leaves party. Game_object *npc = get_item(parms[0]); partyman->remove_from_party(as_actor(npc)); return no_ret; } USECODE_INTRINSIC(get_npc_prop) { // Get NPC prop (item, prop_id). // (9 is food level). Actor *npc = as_actor(get_item(parms[0])); Usecode_value u(npc ? npc->get_property(parms[1].get_int_value()) : 0); return(u); } USECODE_INTRINSIC(set_npc_prop) { // Set NPC prop (item, prop_id, delta_value). Actor *npc = as_actor(get_item(parms[0])); if (npc) { // NOTE: 3rd parm. is a delta! int prop = parms[1].get_int_value(); npc->set_property(prop, npc->get_property(prop) + parms[2].get_int_value()); return Usecode_value(1);// SI needs return. } return Usecode_value(0); } USECODE_INTRINSIC(get_avatar_ref) { // Guessing it's Avatar's itemref. Usecode_value u(gwin->get_main_actor()); return(u); } USECODE_INTRINSIC(get_party_list) { // Return array with party members. Usecode_value u(get_party()); return(u); } USECODE_INTRINSIC(create_new_object) { // create_new_object(shapenum). Stores it in 'last_created' (which // maybe should be a stack. int shapenum = parms[0].get_int_value(); Game_object *obj; // Create to be written to Ireg. Shape_info& info = ShapeID::get_info(shapenum); modified_map = true; // +++Not sure if 1st test is needed. if (info.get_monster_info() || info.is_npc()) { // (Wait sched. added for FOV.) // don't add equipment (Erethian's transform sequence) Monster_actor *monster = Monster_actor::create(shapenum, Tile_coord(-1, -1, -1), Schedule::wait, (int) Actor::neutral, true, false); // FORCE it to be neutral (dec04,01). monster->set_alignment((int) Actor::neutral); gwin->add_dirty(monster); gwin->add_nearby_npc(monster); gwin->show(); last_created.push_back(monster); return Usecode_value(monster); } else { if (Is_body(shapenum)) { obj = new Dead_body(shapenum, 0, 0, 0, 0, -1); } else { obj = gmap->create_ireg_object(shapenum, 0); // Be liberal about taking stuff. obj->set_flag(Obj_flags::okay_to_take); } } obj->set_invalid(); // Not in world yet. obj->set_flag(Obj_flags::okay_to_take); last_created.push_back(obj); Usecode_value u(obj); return(u); } USECODE_INTRINSIC(create_new_object2) { // create_new_object(shapenum, loc). Usecode_value ret = UI_create_new_object(event, intrinsic, 1, parms); if (ret == 0) return ret; // Failed. UI_update_last_created(event, intrinsic, 1, &parms[1]); return ret; } USECODE_INTRINSIC(set_last_created) { // Take itemref off map and set last_created to it. Game_object *obj = get_item(parms[0]); modified_map = true; if (obj) { add_dirty(obj); // Set to repaint area. last_created.push_back(obj); obj->remove_this(1); // Remove, but don't delete. } Usecode_value u(obj); return(u); } USECODE_INTRINSIC(update_last_created) { // Think it takes array from 0x18, // updates last-created object. // ??guessing?? modified_map = true; if (last_created.empty()) { Usecode_value u((Game_object*) NULL); return(u); } Game_object *obj = last_created.back(); last_created.pop_back(); obj->set_invalid(); // It's already been removed. Usecode_value& arr = parms[0]; int sz = arr.get_array_size(); if (sz == 3 || sz == 2) { Tile_coord dest(arr.get_elem(0).get_int_value(), arr.get_elem(1).get_int_value(), sz == 3 ? arr.get_elem(2).get_int_value() : 0); obj->move(dest.tx, dest.ty, dest.tz); if (GAME_BG) { Usecode_value u(1); return u; } else { Usecode_value u(obj); return u; } // Taking a guess here: } else if (sz == 1) { obj->remove_this(); } #ifdef DEBUG else { cout << " { Intrinsic 0x26: "; arr.print(cout); cout << endl << "} "; } #endif // gwin->paint_dirty(); // Problems in conversations. // gwin->show(); // ?? Usecode_value u(1); return(u); } USECODE_INTRINSIC(get_npc_name) { // Get NPC name(s). Works on arrays, too. static const char *unknown = "??name??"; Actor *npc; int cnt = parms[0].get_array_size(); if (cnt) { // Do array. Usecode_value arr(cnt, 0); for (int i = 0; i < cnt; i++) { Game_object *obj = get_item(parms[0].get_elem(i)); npc = as_actor(obj); std::string namestr = npc ? npc->get_npc_name() : obj->get_name(); Usecode_value v(namestr.c_str()); arr.put_elem(i, v); } return(arr); } Game_object *obj = get_item(parms[0]); std::string namestr; if (obj) { npc = as_actor(obj); namestr = npc ? npc->get_npc_name() : obj->get_name(); } else namestr = unknown; Usecode_value u(namestr.c_str()); return(u); } USECODE_INTRINSIC(count_objects) { // How many? // ((npc?-357==party, -356=avatar), // item, quality, frame (c_any_framenum = any)). // Quality/frame -359 means any. Usecode_value u(count_objects(parms[0], parms[1], parms[2], parms[3])); return(u); } USECODE_INTRINSIC(find_object) { // Find_object(container(-357=party) OR loc, shapenum, qual?? (-359=any), // frame??(-359=any)). int shnum = parms[1].get_int_value(), qual = parms[2].get_int_value(), frnum = parms[3].get_int_value(); if (parms[0].get_array_size() == 3) { // Location (x, y). Game_object_vector vec; Game_object::find_nearby(vec, Tile_coord(parms[0].get_elem(0).get_int_value(), parms[0].get_elem(1).get_int_value(), parms[0].get_elem(2).get_int_value()), shnum, 1, 0, qual, frnum); if (vec.empty()) return Usecode_value((Game_object *) 0); else return Usecode_value(vec.front()); } int oval = parms[0].get_int_value(); if (oval != -357) // Not the whole party? { // Find inside owner. Game_object *obj = get_item(parms[0]); if (!obj) return Usecode_value((Game_object*) NULL); Game_object *f = obj->find_item(shnum, qual, frnum); return Usecode_value(f); } // Look through whole party. Usecode_value party = get_party(); int cnt = party.get_array_size(); for (int i = 0; i < cnt; i++) { Game_object *obj = get_item(party.get_elem(i)); if (obj) { Game_object *f = obj->find_item(shnum, qual, frnum); if (f) return Usecode_value(f); } } return Usecode_value((Game_object*) NULL); } USECODE_INTRINSIC(get_cont_items) { // Get cont. items(container, shape, qual, frame). // recursively find items in container Usecode_value u(get_objects(parms[0], parms[1], parms[2], parms[3])); return(u); } USECODE_INTRINSIC(remove_party_items) { // Remove items(quantity, item, ??quality?? (-359), frame(-359), T/F). return remove_party_items(parms[0], parms[1], parms[2], parms[3], parms[4]); } USECODE_INTRINSIC(add_party_items) { // Add items(num, item, ??quality?? (-359), frame (or -359), T/F). // Returns array of NPC's (->'s) who got the items. Usecode_value u(add_party_items(parms[0], parms[1], parms[2], parms[3], parms[4])); return(u); } USECODE_INTRINSIC(play_music) { // Play music(songnum, item). // ??Show notes by item? #ifdef DEBUG cout << "Music request in usecode" << endl; cout << "Parameter data follows" << endl; cout << "0: " << ((parms[0].get_int_value()>>8)&0xff) << " " << ((parms[0].get_int_value())&0xff) << endl; cout << "1: " << ((parms[1].get_int_value()>>8)&0x01) << " " << ((parms[1].get_int_value())&0x01) << endl; #endif int track = parms[0].get_int_value()&0xff; if (track == 0xff) // I think this is right: Audio::get_ptr()->cancel_streams(); // Stop playing. else { Audio::get_ptr()->start_music(track, (parms[0].get_int_value()>>8)&0x01); // Show notes. Game_object *obj = get_item(parms[1]); if (obj) gwin->get_effects()->add_effect( new Sprites_effect(24, obj, 0, 0, -2, -2)); } return(no_ret); } USECODE_INTRINSIC(npc_nearby) { // NPC nearby? (item). Game_object *npc = get_item(parms[0]); int is_near = (npc != 0 && npc->get_tile().distance(gwin->get_main_actor()->get_tile()) < 12 && // FALSE if asleep. !npc->get_flag(Obj_flags::asleep)); Usecode_value u(is_near); return(u); } USECODE_INTRINSIC(npc_nearby2) { // Guessing wildly (SI). Handles start of Moonshade trial where // companions are a fair distance away. Game_object *npc = get_item(parms[0]); int is_near = (npc != 0 && npc->get_tile().distance(gwin->get_main_actor()->get_tile()) < 40 && // FALSE if asleep. !npc->get_flag(Obj_flags::asleep)); Usecode_value u(is_near); return(u); } USECODE_INTRINSIC(find_nearby_avatar) { // Find objs. with given shape near Avatar? Usecode_value av(gwin->get_main_actor()); // Try bigger # for Test of Love tree. Usecode_value dist(/* 64 */ 192), mask(0); Usecode_value u(find_nearby(av, parms[0], dist, mask)); return(u); } USECODE_INTRINSIC(is_npc) { // Is item an NPC? Actor *npc = as_actor(get_item(parms[0])); Usecode_value u(npc != 0); return(u); } USECODE_INTRINSIC(display_runes) { // Render text into runes for signs, tombstones, plaques and the like // Display sign (gump #, array_of_text). int cnt = parms[1].get_array_size(); if (!cnt) cnt = 1; // Try with 1 element. Sign_gump *sign = new Sign_gump(parms[0].get_int_value(), cnt); bool si = Game::get_game_type()== SERPENT_ISLE; for (int i = 0; i < cnt; i++) { // Paint each line. Usecode_value& lval = !i ? parms[1].get_elem0() : parms[1].get_elem(i); const char *str = lval.get_str_value(); #if 0 /* ++++Not sure about this yet. Compare with orig. */ if (si) // SI: Add 0x20 to each chr. { char *newstr = strdup(str); for (char *ptr = newstr; *ptr; ptr++) if (*ptr >= 'A' && *ptr <= 'Z') *ptr += 0x20; sign->add_text(i, newstr); delete newstr; } else #endif sign->add_text(i, str); } int x, y; // Paint it, and wait for click. Get_click(x, y, Mouse::hand, 0, false, sign); delete sign; gwin->paint(); return(no_ret); } USECODE_INTRINSIC(click_on_item) { // Doesn't ret. until user single- // clicks on an item. Rets. item. Game_object *obj; Tile_coord t; // intercept this click? if (intercept_item) { obj = intercept_item; intercept_item = 0; t = obj->get_tile(); // Special case for weapon hit: } else if (event == weapon && caller_item) { // if caller_item is the Avatar, return the Avatar's target // instead. This makes combat spellcasting work // if caller_item is not the Avatar return caller_item itself // this is needed for hitting Draygan with sleep arrows (SI) Actor *npc = as_actor(caller_item); if (npc == gwin->get_main_actor() && npc->get_target()) obj = npc->get_target(); else obj = caller_item; t = obj->get_tile(); } else { int x, y; // Allow dragging while here: if (!Get_click(x, y, Mouse::greenselect, 0, true)) return Usecode_value(0); // Get abs. tile coords. clicked on. t = Tile_coord(gwin->get_scrolltx() + x/c_tilesize, gwin->get_scrollty() + y/c_tilesize, 0); // Look for obj. in open gump. Gump *gump = gumpman->find_gump(x, y); if (gump) { obj = gump->find_object(x, y); if (!obj) obj = gump->find_actor(x, y); } else // Search rest of world. { obj = gwin->find_object(x, y); if (obj) // Found object? Use its coords. t = obj->get_tile(); } } Usecode_value oval(obj); // Ret. array with obj as 1st elem. Usecode_value ret(4, &oval); Usecode_value xval(t.tx), yval(t.ty), zval(t.tz); ret.put_elem(1, xval); ret.put_elem(2, yval); ret.put_elem(3, zval); return (ret); } /* Set item to be returned by next call to click_on_item(). * Added for Exult. */ USECODE_INTRINSIC(set_intercept_item) { intercept_item = get_item(parms[0]); return no_ret; } USECODE_INTRINSIC(find_nearby) { // Think it rets. objs. near parm0. Usecode_value u(find_nearby(parms[0], parms[1], parms[2], parms[3])); return(u); } USECODE_INTRINSIC(give_last_created) { // Think it's give_last_created(container). Game_object *cont = get_item(parms[0]); int ret = 0; if (cont && !last_created.empty()) { // Get object, but don't pop yet. Game_object *obj = last_created.back(); // Don't check vol. Causes failures. ret = cont->add(obj, 1); if (ret) // Pop only if added. Fixes chest/ // tooth bug in SI. last_created.pop_back(); } Usecode_value u(ret); return(u); } USECODE_INTRINSIC(is_dead) { // Return 1 if parm0 is a dead NPC. Actor *npc = as_actor(get_item(parms[0])); Usecode_value u(npc && npc->is_dead()); return(u); } USECODE_INTRINSIC(game_hour) { // Return. game time hour (0-23). Usecode_value u(gclock->get_hour()); return(u); } USECODE_INTRINSIC(game_minute) { // Return minute (0-59). Usecode_value u(gclock->get_minute()); return(u); } USECODE_INTRINSIC(get_npc_number) { // Returns NPC# of item. (-356 = // avatar). Actor *npc = as_actor(get_item(parms[0])); if (npc == gwin->get_main_actor()) { Usecode_value u(-356); return(u); } int num = npc ? npc->get_npc_num() : 0; Usecode_value u(-num); return(u); } USECODE_INTRINSIC(part_of_day) { // Return 3-hour # (0-7, 0=midnight). Usecode_value u(gclock->get_hour()/3); return(u); } USECODE_INTRINSIC(get_alignment) { // Get npc's alignment. Actor *npc = as_actor(get_item(parms[0])); Usecode_value u(npc ? npc->get_alignment() : 0); return(u); } USECODE_INTRINSIC(set_alignment) { // Set npc's alignment. // 2,3==bad towards Ava. 0==good. Actor *npc = as_actor(get_item(parms[0])); int val = parms[1].get_int_value(); if (npc) { int oldalign = npc->get_alignment(); npc->set_alignment(val); if (oldalign != val) // Changed? Force search for new opp. npc->set_target(0); // For fixing List Field fleeing: if (npc->get_attack_mode() == Actor::flee) npc->set_attack_mode(Actor::nearest); } return(no_ret); } USECODE_INTRINSIC(move_object) { // move_object(obj(-357=party), (tx, ty, tz)). Usecode_value& p = parms[1]; Tile_coord tile(p.get_elem(0).get_int_value(), p.get_elem(1).get_int_value(), p.get_elem(2).get_int_value()); Actor *ava = gwin->get_main_actor(); modified_map = true; if (parms[0].get_int_value() == -357) { // Move whole party. // If Freedom exit teleport, don't ac- // tivate eggs when you arrive. gwin->teleport_party(tile, Game::get_game_type() == SERPENT_ISLE && frame->function->id == 0x7df && caller_item->get_quality() == 0xcf); return (no_ret); } Game_object *obj = get_item(parms[0]); if (!obj) return (no_ret); Tile_coord oldpos = obj->get_tile(); obj->move(tile.tx, tile.ty, tile.tz); Actor *act = as_actor(obj); if (act) { act->set_action(0); if (act == ava) { // Teleported Avatar? // Make new loc. visible, test eggs. gwin->center_view(tile); Map_chunk::try_all_eggs(ava, tile.tx, tile.ty, tile.tz, oldpos.tx, oldpos.ty); } // Close? Add to 'nearby' list. else if (ava->distance(act) < gwin->get_width()/c_tilesize) { Npc_actor *npc = act->as_npc(); if (npc) gwin->add_nearby_npc(npc); } } return(no_ret); } USECODE_INTRINSIC(remove_npc) { // Remove_npc(npc) - Remove npc from world. Actor *npc = as_actor(get_item(parms[0])); if (npc) { modified_map = true; // Don't want him/her coming back! npc->set_schedule_type(Schedule::wait); gwin->add_dirty(npc); npc->remove_this(1); // Remove, but don't delete. } return (no_ret); } USECODE_INTRINSIC(item_say) { // Show str. near item (item, str). if (!conv->is_npc_text_pending()) item_say(parms[0], parms[1]); // Do it now. return(no_ret); } USECODE_INTRINSIC(clear_item_say) { // Clear str. near item (item). Game_object *item = get_item(parms[0]); if (item) gwin->get_effects()->remove_text_effect(item); return(no_ret); } USECODE_INTRINSIC(projectile_effect) { // animate(fromitem, toitem, anim_shape_in_shapesdotvga). // ???? When it reaches toitem, toitem is 'attacked' by anim_shape. // Returns??} Game_object *from = get_item(parms[0]), *to = get_item(parms[1]); if (!from || !to) return Usecode_value(0); Actor *attacker = as_actor(from); if (!attacker) return Usecode_value(0); int shnum = parms[2].get_int_value(); gwin->get_effects()->add_effect( new Projectile_effect(attacker, to, shnum)); return Usecode_value(0); // Not sure what this should be. } USECODE_INTRINSIC(get_lift) { // ?? Guessing rets. lift(item). Game_object *obj = get_item(parms[0]); Usecode_value u(obj ? Usecode_value(obj->get_lift()) : Usecode_value(0)); return(u); } USECODE_INTRINSIC(set_lift) { // ?? Guessing setlift(item, lift). Game_object *obj = get_item(parms[0]); if (obj) { Tile_coord t = obj->get_tile(); int lift = parms[1].get_int_value(); if (lift >= 0 && lift < 20) obj->move(t.tx, t.ty, lift); gwin->paint(); gwin->show(); modified_map = true; } return(no_ret); } USECODE_INTRINSIC(get_weather) { // Get_weather() return Usecode_value(gwin->get_effects()->get_weather()); } USECODE_INTRINSIC(set_weather) { // Set_weather(i) Egg_object::set_weather(parms[0].get_int_value()); return no_ret; } USECODE_INTRINSIC(sit_down) { // Sit_down(npc, chair). Game_object *nobj = get_item(parms[0]); Actor *npc = as_actor(nobj); if (!npc) return (no_ret); // Doesn't look like an NPC. Game_object *chair = get_item(parms[1]); if (!chair) return (no_ret); npc->set_schedule_type(Schedule::sit, new Sit_schedule(npc, chair)); return(no_ret); } USECODE_INTRINSIC(summon) { // summon(shape, flag??). Create monster of desired shape. int shapenum = parms[0].get_int_value(); Monster_info *info = ShapeID::get_info(shapenum).get_monster_info(); if (!info) return Usecode_value(0); Tile_coord start = gwin->get_main_actor()->get_tile(); Tile_coord dest = Map_chunk::find_spot(start, 5, shapenum, 0, 1, -1, gwin->is_main_actor_inside() ? Map_chunk::inside : Map_chunk::outside); if (dest.tx == -1) return Usecode_value(0); Monster_actor *monst = Monster_actor::create(shapenum, dest, Schedule::combat, Actor::friendly); return Usecode_value(monst); } /* * Class to paint a shape centered. */ class Paint_centered : public Paintable, public Game_singletons { protected: ShapeID *sid; // ->shape. int x, y; // Where to paint. public: Paint_centered(ShapeID *si) : sid(si) { Shape_frame *s = sid->get_shape(); // Get coords. for centered view. x = (gwin->get_width() - s->get_width())/2 + s->get_xleft(); y = (gwin->get_height() - s->get_height())/2 + s->get_yabove(); } virtual void paint() { sid->paint_shape(x, y); } }; /* * Paint map. */ class Paint_map : public Paint_centered { bool show_loc; public: Paint_map(ShapeID *s, bool loc) : Paint_centered(s), show_loc(loc) { } virtual void paint() { Paint_centered::paint(); if (show_loc) { // mark location int xx, yy; Tile_coord t = gwin->get_main_actor()->get_tile(); if (Game::get_game_type()==BLACK_GATE) { xx = (int)(t.tx/16.05 + 5 + 0.5); yy = (int)(t.ty/15.95 + 4 + 0.5); } else if (Game::get_game_type()==SERPENT_ISLE) { xx = (int)(t.tx/16.0 + 18 + 0.5); yy = (int)(t.ty/16.0 + 9.4 + 0.5); } Shape_frame *s = sid->get_shape(); xx += x - s->get_xleft(); yy += y - s->get_yabove(); gwin->get_win()->fill8(255, 1, 5, xx, yy - 2); gwin->get_win()->fill8(255, 5, 1, xx - 2, yy); } } }; USECODE_INTRINSIC(display_map) { //count all sextants in party Usecode_value v_357(-357), v650(650), v_359(-359); long sextants=count_objects(v_357, v650, v_359, v_359).get_int_value(); bool loc = !gwin->is_main_actor_inside() && (sextants > 0); // Display map. ShapeID msid(game->get_shape("sprites/map"), 0, SF_SPRITES_VGA); Paint_map map(&msid, loc); int xx, yy; Get_click(xx, yy, Mouse::hand, 0, false, &map); gwin->paint(); return(no_ret); } USECODE_INTRINSIC(si_display_map) { int mapnum = parms[0].get_int_value(); int shapenum; switch (mapnum) { case 0: return UI_display_map(event,intrinsic,num_parms,parms); case 1: shapenum = 57; break; case 2: shapenum = 58; break; case 3: shapenum = 59; break; case 4: shapenum = 60; break; case 5: shapenum = 52; break; default: return no_ret; } // Display map. // Display map. ShapeID msid(shapenum, 0, SF_SPRITES_VGA); Paint_centered map(&msid); int xx, yy; Get_click(xx, yy, Mouse::hand, 0, false, &map); gwin->paint(); return no_ret; } USECODE_INTRINSIC(kill_npc) { // kill_npc(npc). Game_object *item = get_item(parms[0]); Actor *npc = as_actor(item); if (npc) npc->die(0); modified_map = true; return (no_ret); } USECODE_INTRINSIC(roll_to_win) { // roll_to_win(attackpts, defendpts) int attack = parms[0].get_int_value(); int defend = parms[1].get_int_value(); return Usecode_value((int) Actor::roll_to_win(attack, defend)); } USECODE_INTRINSIC(set_attack_mode) { // set_attack_mode(npc, mode). Actor *npc = as_actor(get_item(parms[0])); if (npc) npc->set_attack_mode((Actor::Attack_mode) parms[1].need_int_value()); return (no_ret); } USECODE_INTRINSIC(get_attack_mode) { // get_attack_mode(npc). Actor *npc = as_actor(get_item(parms[0])); if (npc) return Usecode_value((int) npc->get_attack_mode()); return Usecode_value(0); } USECODE_INTRINSIC(set_opponent) { // set_opponent(npc, new_opponent). Actor *npc = as_actor(get_item(parms[0])); Game_object *opponent = get_item(parms[1]); if (npc && opponent) npc->set_target(opponent); return (no_ret); } USECODE_INTRINSIC(clone) { // clone(npc) Actor *npc = as_actor(get_item(parms[0])); if (npc) { modified_map = true; npc->set_alignment(Actor::friendly); npc->set_schedule_type(Schedule::combat); return Usecode_value(npc->clone()); } return Usecode_value(0); } USECODE_INTRINSIC(get_oppressor) { // get_oppressor(npc) Returns 0-n, NPC # (0=avatar). Actor *npc = as_actor(get_item(parms[0])); return Usecode_value(npc ? npc->get_oppressor() : 0); } USECODE_INTRINSIC(set_oppressor) { // set_oppressor(npc, opp) Actor *npc = as_actor(get_item(parms[0])); Actor *opp = as_actor(get_item(parms[1])); if (npc && opp) { if (opp == gwin->get_main_actor()) npc->set_oppressor(0); else npc->set_oppressor(opp->get_npc_num()); // Need this for SI ListField training: npc->set_target(opp); } return no_ret; } USECODE_INTRINSIC(get_weapon) { // get_weapon(npc). Returns shape. Actor *npc = as_actor(get_item(parms[0])); if (npc) { int shape, points; if (npc->get_weapon(points, shape)) return Usecode_value(shape); } return Usecode_value(0); } USECODE_INTRINSIC(display_area) { // display_area(tilepos) - used for crystal balls. int size = parms[0].get_array_size(); if (size >= 3) { int tx = parms[0].get_elem(0).get_int_value(); int ty = parms[0].get_elem(1).get_int_value(); int unknown = parms[0].get_elem(2).get_int_value(); // Figure in tiles. int tw = gwin->get_width()/c_tilesize, th = gwin->get_height()/c_tilesize; gwin->clear_screen(); // Fill with black. Shape_frame *sprite = ShapeID(10, 0, SF_SPRITES_VGA).get_shape(); // Center it. int topx = (gwin->get_width() - sprite->get_width())/2, topy = (gwin->get_height() - sprite->get_height())/2; // Get area to fill. int x = topx, y = topy, w = sprite->get_width(), h = sprite->get_height(); if (w > gwin->get_width()) { x = 0; w = gwin->get_width(); } if (h > gwin->get_height()) { y = 0; h = gwin->get_height(); } int save_dungeon = gwin->is_in_dungeon(); gwin->set_in_dungeon(0); // Disable dungeon. // Paint game area. gwin->paint_map_at_tile(x, y, w, h, tx - tw/2, ty - th/2, 4); // Paint sprite #10 (black gate!) // over it, transparently. sman->paint_shape(topx + sprite->get_xleft(), topy + sprite->get_yabove(), sprite, 1); gwin->set_in_dungeon(save_dungeon); gwin->show(); // Wait for click. Get_click(x, y, Mouse::hand); gwin->paint(); // Repaint normal area. } return (no_ret); } USECODE_INTRINSIC(wizard_eye) { // wizard_eye(#ticks, ??); extern void Wizard_eye(long); // Let's give 50% longer. Wizard_eye(parms[0].get_int_value()*(3*gwin->get_std_delay())/2); return no_ret; } USECODE_INTRINSIC(resurrect) { // resurrect(body). Returns actor if successful. Game_object *body = get_item(parms[0]); int npc_num = body ? body->get_live_npc_num() : -1; if (npc_num < 0) return Usecode_value((Game_object*) NULL); Actor *actor = gwin->get_npc(npc_num); if (actor) { // Want to resurrect after returning. Usecode_script *scr = new Usecode_script(body); (*scr) << Ucscript::resurrect; scr->start(); modified_map = true; } return Usecode_value(actor); } USECODE_INTRINSIC(get_body_npc) { // get_body_npc(body). Returns npc # (negative). Game_object *obj = get_item(parms[0]); int num = obj ? obj->get_live_npc_num() : -1; return Usecode_value(num > 0 ? -num : 0); } USECODE_INTRINSIC(add_spell) { // add_spell(spell# (0-71), ??, spoolbook). // Returns 0 if book already has that spell. Game_object *obj = get_item(parms[2]); if (!obj || obj->get_info().get_shape_class() != Shape_info::spellbook) return Usecode_value(0); Spellbook_object *book = (Spellbook_object *) (obj); if (!book) { cout << "Add_spell - Not a spellbook!" << endl; return Usecode_value(0); } return Usecode_value(book->add_spell(parms[0].get_int_value())); } USECODE_INTRINSIC(sprite_effect) { // Display animation from sprites.vga. // show_sprite(sprite#, tx, ty, dx, dy, frame, length??); // ++++++Pass frame, length+++++++ gwin->get_effects()->add_effect( new Sprites_effect(parms[0].get_int_value(), Tile_coord(parms[1].get_int_value(), parms[2].get_int_value(), 0), parms[3].get_int_value(), parms[4].get_int_value())); return(no_ret); } USECODE_INTRINSIC(obj_sprite_effect) { // obj_sprite_effect(obj, sprite#, -xoff, -yoff, dx, dy, // frame, length??) Game_object *obj = get_item(parms[0]); if (obj) // ++++++Pass frame, length+++++++ gwin->get_effects()->add_effect( new Sprites_effect(parms[1].get_int_value(), obj, -parms[2].get_int_value(), -parms[3].get_int_value(), parms[4].get_int_value(), parms[5].get_int_value())); return(no_ret); } USECODE_INTRINSIC(explode) { // Explode(obj??, item-to-explode, powder-keg-shape). Game_object *exp = get_item(parms[1]); if (!exp) return Usecode_value(0); // Use container if it's in one. Tile_coord pos = exp->get_outermost()->get_tile(); // Sprite 1,4,5 look like explosions. gwin->get_effects()->add_effect(new Explosion_effect(pos, exp)); return Usecode_value(1); } USECODE_INTRINSIC(book_mode) { // Display book or scroll. Text_gump *gump; Game_object *obj = get_item(parms[0]); if (!obj) { return(no_ret); } // check for avatar read here bool do_serp = gwin->get_main_actor()->get_flag(Obj_flags::read) == false; if (obj->get_shapenum() == 707) // Serpentine Scroll - Make SI only??? gump = new Scroll_gump(do_serp); else if (obj->get_shapenum() == 705) // Serpentine Book - Make SI only??? gump = new Book_gump(do_serp); else if (obj->get_shapenum() == 797) gump = new Scroll_gump(); else gump = new Book_gump(); set_book(gump); return(no_ret); } USECODE_INTRINSIC(stop_time) { // stop_time(.25 secs). int length = parms[0].get_int_value(); gwin->set_time_stopped(length*250); return no_ret; } USECODE_INTRINSIC(cause_light) { // Cause_light(game_minutes??) gwin->add_special_light(parms[0].get_int_value()); return no_ret; } USECODE_INTRINSIC(get_barge) { // get_barge(obj) - returns barge object is part of or lying on. Game_object *obj = get_item(parms[0]); if (!obj) return Usecode_value((Game_object*) NULL); return Usecode_value(Get_barge(obj)); } USECODE_INTRINSIC(earthquake) { int len = parms[0].get_int_value(); gwin->get_tqueue()->add(Game::get_ticks() + 10, new Earthquake(len), (long) this); return(no_ret); } USECODE_INTRINSIC(is_pc_female) { // Is player female? Usecode_value u(gwin->get_main_actor()->get_type_flag(Actor::tf_sex)); return(u); } USECODE_INTRINSIC(armageddon) { int cnt = gwin->get_num_npcs(); Rectangle screen = gwin->get_win_tile_rect(); for (int i = 1; i < cnt; i++) // Most everyone dies. { // Leave LB, Batlin, Hook. Actor *npc = gwin->get_npc(i); if (npc && i != 26 && i != 23 && npc->get_shapenum() != 506 && !npc->is_dead()) { const char *text[] = {"Aiiiieee!", "Noooo!", "#!?*#%!"}; const int numtext = sizeof(text)/sizeof(text[0]); Tile_coord loc = npc->get_tile(); if (screen.has_point(loc.tx, loc.ty)) npc->say(text[rand()%numtext]); npc->die(0); } } Actor_vector vec; // Get any monsters nearby. gwin->get_main_actor()->find_nearby_actors(vec, c_any_shapenum, 40); for (Actor_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Actor *act = *it; if (act->is_monster()) // Assume only Avatar can cast this. act->die(gwin->get_main_actor()); } gwin->armageddon = true; return no_ret; } USECODE_INTRINSIC(halt_scheduled) { // Halt_scheduled(item) Game_object *obj = get_item(parms[0]); if (obj) Usecode_script::terminate(obj); return(no_ret); } USECODE_INTRINSIC(lightning) { // 1 sec. is long enough for 1 flash. gwin->get_effects()->add_effect(new Lightning_effect(1000)); return no_ret; } USECODE_INTRINSIC(get_array_size) { int cnt; if (parms[0].is_array()) // An array? We might return 0. cnt = parms[0].get_array_size(); else // Not an array? Usecode wants a 1. cnt = 1; Usecode_value u(cnt); return(u); } USECODE_INTRINSIC(mark_virtue_stone) { Game_object *obj = get_item(parms[0]); if (obj->get_info().get_shape_class() == Shape_info::virtue_stone) { Virtue_stone_object *vs = (Virtue_stone_object *) (obj); vs->set_pos(obj->get_outermost()->get_tile()); } return no_ret; } USECODE_INTRINSIC(recall_virtue_stone) { Game_object *obj = get_item(parms[0]); if (obj->get_info().get_shape_class() == Shape_info::virtue_stone) { Virtue_stone_object *vs = (Virtue_stone_object *) (obj); gumpman->close_all_gumps(); // Pick it up if necessary. if (!obj->get_owner()) { // Go through whole party. obj->remove_this(1); Usecode_value party = get_party(); int cnt = party.get_array_size(); int i; for (i = 0; i < cnt; i++) { Game_object *npc = get_item(party.get_elem(i)); if (npc && npc->add(obj)) break; } if (i == cnt) // Failed? Force it on Avatar. gwin->get_main_actor()->add(obj, 1); } Tile_coord t = vs->get_pos(); if (t.tx > 0 || t.ty > 0) gwin->teleport_party(t); } return no_ret; } USECODE_INTRINSIC(apply_damage) { // apply_damage(??str?, hps, ??type?, NPC); int hps = parms[1].get_int_value(); Actor *npc = as_actor(get_item(parms[3])); if (npc) npc->reduce_health(hps); return Usecode_value(1); // ?? Guessing. } USECODE_INTRINSIC(is_pc_inside) { Usecode_value u(gwin->is_main_actor_inside()); return(u); } USECODE_INTRINSIC(get_timer) { int tnum = parms[0].get_int_value(); int ret; if (tnum >= 0 && tnum < (int)(sizeof(timers)/sizeof(timers[0]))) // Return 0 if not set. ret = timers[tnum] > 0 ? (gclock->get_total_hours() - timers[tnum]) : 0; else { cerr << "Attempt to use invalid timer " << tnum << endl; ret = 0; } return Usecode_value(ret); } USECODE_INTRINSIC(set_timer) { int tnum = parms[0].get_int_value(); if (tnum >= 0 && tnum < (int)(sizeof(timers)/sizeof(timers[0]))) timers[tnum] = gclock->get_total_hours(); else cerr << "Attempt to use invalid timer " << tnum << endl; return(no_ret); } USECODE_INTRINSIC(wearing_fellowship) { Game_object *obj = gwin->get_main_actor()->get_readied(Actor::neck); if (obj && obj->get_shapenum() == 955 && obj->get_framenum() == 1) return Usecode_value(1); else return Usecode_value(0); } USECODE_INTRINSIC(mouse_exists) { Usecode_value u(1); return(u); } USECODE_INTRINSIC(get_speech_track) { // Get speech track set by 0x74 or 0x8f. return Usecode_value(speech_track); } USECODE_INTRINSIC(flash_mouse) { // flash_mouse(code) Mouse::Mouse_shapes shape; switch (parms[0].need_int_value()) { case 2: shape = Mouse::outofrange; break; case 3: shape = Mouse::outofammo; break; case 4: shape = Mouse::tooheavy; break; case 5: shape = Mouse::wontfit; break; case 0: case 1: default: shape = Mouse::redx; break; } Mouse::mouse->flash_shape(shape); return (no_ret); } USECODE_INTRINSIC(get_item_frame_rot) { // Same as get_item_frame, but (guessing!) include rotated bit. Game_object *obj = get_item(parms[0]); return Usecode_value(obj ? obj->get_framenum() : 0); } USECODE_INTRINSIC(set_item_frame_rot) { // Set entire frame, including rotated bit. set_item_frame(get_item(parms[0]), parms[1].get_int_value(), 0, 1); return(no_ret); } USECODE_INTRINSIC(on_barge) { // Only used once for BG, in usecode for magic-carpet. // For SI, used for turtle. // on_barge() Barge_object *barge = Get_barge(gwin->get_main_actor()); if (barge) { // See if party is on barge. Rectangle foot = barge->get_tile_footprint(); Actor *party[9]; int cnt = gwin->get_party(party, 1); for (int i = 0; i < cnt; i++) { Actor *act = party[i]; Tile_coord t = act->get_tile(); if (!foot.has_point(t.tx, t.ty)) return Usecode_value(0); } // Force 'gather()' for turtle. if (Game::get_game_type() == SERPENT_ISLE) barge->done(); return Usecode_value(1); } return Usecode_value(0); // return Usecode_value(1); } USECODE_INTRINSIC(get_container) { // Takes itemref, returns container. Game_object *obj = get_item(parms[0]); Usecode_value u((Game_object *) NULL); if (obj) u = Usecode_value(obj->get_owner()); return(u); } USECODE_INTRINSIC(remove_item) { // Think it's 'delete object'. remove_item(get_item(parms[0])); modified_map = true; return no_ret; } USECODE_INTRINSIC(reduce_health) { // Reduce_health(npc, amount, ??property/flags??0?). Actor *npc = as_actor(get_item(parms[0])); if (npc) // Dies if health goes too low. npc->reduce_health(parms[1].get_int_value()); return no_ret; } /* * Convert Usecode spot # to ours (or -1 if not found). */ static int Get_spot(int ucspot) { int spot; switch (ucspot) { case 1: spot = Actor::lhand; break; case 2: spot = Actor::rhand; break; case 3: spot = Actor::neck; break; case 5: spot = Actor::hands2_spot; break; case 6: spot = Actor::lfinger; break; case 7: spot = Actor::rfinger; break; case 9: spot = Actor::head; break; case 11: spot = Actor::belt; break; default: cerr << "Readied: spot #" << ucspot << " not known yet" << endl; spot = -1; } return spot; } USECODE_INTRINSIC(is_readied) { // is_readied(npc, where, itemshape, frame (-359=any)). // Where: // 1=weapon hand, // 2=other hand, // 6=one finger, // 7=other finger, // 9=head // 20=??? Actor *npc = as_actor(get_item(parms[0])); if (!npc) return Usecode_value(0); int where = parms[1].get_int_value(); int shnum = parms[2].get_int_value(); int frnum = parms[3].get_int_value(); // Spot defined in Actor class. int spot = Get_spot(where); if (spot >= 0) { // See if it's the right one. Game_object *obj = npc->get_readied(spot); if (obj && obj->get_shapenum() == shnum && (frnum == c_any_framenum || obj->get_framenum() == frnum)) return Usecode_value(1); } return Usecode_value(0); } USECODE_INTRINSIC(get_readied) { // get_readied(npc, where) // Where: // 1=weapon hand, // 2=other hand, // 6=one finger, // 7=other finger, // 9=head // 11=belt // 20=??? Actor *npc = as_actor(get_item(parms[0])); if (!npc) return Usecode_value(0); int where = parms[1].get_int_value(); // Spot defined in Actor class. int spot = Get_spot(where); if (spot >= 0) return Usecode_value(npc->get_readied(spot)); return Usecode_value(0); } USECODE_INTRINSIC(restart_game) { // Think it's 'restart game'. // Happens if you die before leaving trinsic. Audio::get_ptr()->stop_music(); quitting_time = QUIT_TIME_RESTART; // Quit & restart. return(no_ret); } USECODE_INTRINSIC(start_speech) { // Start_speech(num). Also sets speech_track. bool okay = false; speech_track = parms[0].get_int_value(); if (speech_track >= 0) okay = Audio::get_ptr()->start_speech(speech_track); if (!okay) // Failed? Clear faces. (Fixes SI). init_conversation(); return(Usecode_value(okay ? 1 : 0)); } USECODE_INTRINSIC(is_water) { // Is_water(pos). int size = parms[0].get_array_size(); if (size >= 3) { Tile_coord t(parms[0].get_elem(0).get_int_value(), parms[0].get_elem(1).get_int_value(), parms[0].get_elem(2).get_int_value()); // Didn't click on an object? int x = (t.tx - gwin->get_scrolltx())*c_tilesize, y = (t.ty - gwin->get_scrollty())*c_tilesize; if (t.tz != 0 || gwin->find_object(x, y)) return Usecode_value(0); ShapeID sid = gwin->get_flat(x, y); if (sid.is_invalid()) return Usecode_value(0); Shape_info& info = sid.get_info(); return Usecode_value(info.is_water()); } return Usecode_value(0); } USECODE_INTRINSIC(run_endgame) { Audio::get_ptr()->stop_sound_effects(); game->end_game(parms[0].get_int_value() != 0); // If successful enable menu entry and play credits afterwards if(parms[0].get_int_value() != 0) { std::ofstream endgameflg; U7open(endgameflg, "/endgame.flg"); endgameflg.close(); game->show_credits(); } quitting_time = QUIT_TIME_YES; return(no_ret); } USECODE_INTRINSIC(fire_cannon) { // fire_cannon(cannon, dir, ballshape, dist?, cannonshape, cannonshape) Game_object *cannon = get_item(parms[0]); // Get direction (0,2,4, or 6). int dir = parms[1].get_int_value(); dir = dir/2; // 0, 1, 2, 3. int ball = parms[2].get_int_value(); int dist = parms[3].get_int_value(); int cshape = parms[4].get_int_value(); Tile_coord pos = cannon->get_tile(); short blastoff[8] = {-2, -5, 1, -2, -2, 1, -5, -2}; Tile_coord blastpos = pos + Tile_coord( blastoff[2*dir], blastoff[2*dir + 1], 0); // Sprite 5 is a small explosion. gwin->get_effects()->add_effect(new Sprites_effect(5, blastpos)); Tile_coord dest = pos; switch (dir) // Figure where to aim. { case 0: dest.ty -= dist; break; case 1: dest.tx += dist; break; case 2: dest.ty += dist; break; case 3: dest.tx -= dist; break; } // Shoot cannonball. gwin->get_effects()->add_effect( new Projectile_effect(blastpos, dest, ball, cshape)); return no_ret; } USECODE_INTRINSIC(nap_time) { // nap_time(bed) Game_object *bed = get_item(parms[0]); if (!bed) return no_ret; // !!! Seems 622 handles sleeping. Actor_vector npcs; // See if bed is occupied by an NPC. int cnt = bed->find_nearby_actors(npcs, c_any_shapenum, 0); if (cnt > 0) { Actor_vector::const_iterator it; for (it = npcs.begin(); it != npcs.end(); ++it) { Game_object *npc = *it; int zdiff = npc->get_lift() - bed->get_lift(); if (npc != gwin->get_main_actor() && (npc->get_framenum()&0xf) == Actor::sleep_frame && zdiff <= 2 && zdiff >= -2) break; // Found one. } if (it != npcs.end()) { // Show party member's face. int party_cnt = partyman->get_count(); int npcnum = party_cnt ? partyman->get_member( rand()%party_cnt) : 356; Usecode_value actval(-npcnum), frval(0); show_npc_face(actval, frval); conv->show_npc_message(item_names[first_bed_occupied + rand()%num_bed_occupied]); remove_npc_face(actval); gwin->get_main_actor()->set_schedule_type( Schedule::follow_avatar); return no_ret; } } Schedule *sched = gwin->get_main_actor()->get_schedule(); if (sched) // Tell (sleep) sched. to use bed. sched->set_bed(bed); // Give him a chance to get there (at // most 5 seconds.) Wait_for_arrival(gwin->get_main_actor(), bed->get_tile(), 5000); call_usecode(0x622, bed, double_click); return(no_ret); } USECODE_INTRINSIC(advance_time) { // Incr. clock by (parm[0]*.04min.). gclock->increment(parms[0].get_int_value()/25); return(no_ret); } USECODE_INTRINSIC(in_usecode) { // in_usecode(item): Return 1 if executing usecode on parms[0]. Game_object *obj = get_item(parms[0]); if (!obj) return Usecode_value(0); return Usecode_value(Usecode_script::find(obj) != 0); } USECODE_INTRINSIC(call_guards) { // Attack thieving Avatar. gwin->call_guards(); return no_ret; } USECODE_INTRINSIC(attack_avatar) { // Attack thieving Avatar. gwin->attack_avatar(); return no_ret; } USECODE_INTRINSIC(path_run_usecode) { // exec(loc(x,y,z)?, usecode#, itemref, eventid). // Think it should have Avatar walk path to loc, return 0 // if he can't get there (and return), 1 if he can. Usecode_value ava(gwin->get_main_actor()); return Usecode_value(path_run_usecode(ava, parms[0], parms[1], parms[2], parms[3], // SI: Look for free spot. (Guess). Game::get_game_type() == SERPENT_ISLE)); } USECODE_INTRINSIC(close_gumps) { if (!gwin->is_dragging()) // NOT while dragging stuff. gumpman->close_all_gumps(); return(no_ret); } USECODE_INTRINSIC(in_gump_mode) { // No persistent return Usecode_value(gumpman->showing_gumps(true)); } USECODE_INTRINSIC(is_not_blocked) { // Is_not_blocked(tile, shape, frame (or -359). Usecode_value fail(0); // Parm. 0 should be tile coords. Usecode_value& pval = parms[0]; if (pval.get_array_size() < 3) return fail; Tile_coord tile(pval.get_elem(0).get_int_value(), pval.get_elem(1).get_int_value(), pval.get_elem(2).get_int_value()); int shapenum = parms[1].get_int_value(); int framenum = parms[2].get_int_value(); // Find out about given shape. Shape_info& info = ShapeID::get_info(shapenum); Rectangle footprint( tile.tx - info.get_3d_xtiles(framenum) + 1, tile.ty - info.get_3d_ytiles(framenum) + 1, info.get_3d_xtiles(framenum), info.get_3d_ytiles(framenum)); int new_lift; int blocked = Map_chunk::is_blocked( info.get_3d_height(), tile.tz, footprint.x, footprint.y, footprint.w, footprint.h, new_lift, MOVE_ALL_TERRAIN, 1); // Okay? if (!blocked && new_lift == tile.tz) return Usecode_value(1); else return Usecode_value(0); } USECODE_INTRINSIC(direction_from) { // ?Direction from parm[0] -> parm[1]. // Rets. 0-7, with 0 = North, 1 = Northeast, etc. // Same as 0x1a?? Usecode_value u=find_direction(parms[0], parms[1]); return(u); } /* * Test for a 'moving barge' flag. */ static int Is_moving_barge_flag ( int fnum ) { if (Game::get_game_type() == BLACK_GATE) { return fnum == (int) Obj_flags::on_moving_barge || fnum == (int) Obj_flags::in_motion; } else // SI. { return fnum == (int) Obj_flags::si_on_moving_barge || // Ice raft needs this one: fnum == (int) Obj_flags::on_moving_barge || fnum == (int) Obj_flags::in_motion; } } USECODE_INTRINSIC(get_item_flag) { // Get npc flag(item, flag#). Game_object *obj = get_item(parms[0]); if (!obj) return Usecode_value(0); int fnum = parms[1].get_int_value(); // Special cases: if (Is_moving_barge_flag(fnum)) { // Test for moving barge. Barge_object *barge; if (!gwin->get_moving_barge() || !(barge = Get_barge(obj))) return Usecode_value(0); return Usecode_value(barge == gwin->get_moving_barge()); } else if (fnum == (int) Obj_flags::okay_to_land) { // Okay to land flying carpet? Barge_object *barge = Get_barge(obj); if (!barge) return Usecode_value(0); return Usecode_value(barge->okay_to_land()); } else if (fnum == (int) Obj_flags::cant_die) { Monster_info *inf = obj->get_info().get_monster_info(); return Usecode_value(inf != 0 && inf->cant_die()); } // +++++0x18 is used in testing for // blocked gangplank. What is it????? else if (fnum == 0x18 && Game::get_game_type() == BLACK_GATE) return Usecode_value(1); else if (fnum == (int) Obj_flags::in_dungeon) return Usecode_value(obj == gwin->get_main_actor() && gwin->is_in_dungeon()); else if (fnum == 0x14) // Must be the sailor, as this is used // to check for Ferryman. return Usecode_value(sailor); Usecode_value u(obj->get_flag(fnum) != 0); return(u); } USECODE_INTRINSIC(set_item_flag) { // Set npc flag(item, flag#). Game_object *obj = get_item(parms[0]); int flag = parms[1].get_int_value(); if (!obj) return no_ret; switch (flag) { case Obj_flags::dont_move: obj->set_flag(flag); // Get out of combat mode. if (obj == gwin->get_main_actor() && Game::get_game_type() == SERPENT_ISLE && gwin->in_combat()) gwin->toggle_combat(); // Show change in status. gwin->set_all_dirty(); break; case Obj_flags::invisible: if (as_actor(obj)) // Only NPC's for now. { obj->set_flag(flag); gwin->add_dirty(obj); } break; case 0x14: // The sailor (Ferryman). sailor = obj; default: obj->set_flag(flag); if (Is_moving_barge_flag(flag)) { // Set barge in motion. Barge_object *barge = Get_barge(obj); if (barge) gwin->set_moving_barge(barge); } break; } return(no_ret); } USECODE_INTRINSIC(clear_item_flag) { // Clear npc flag(item, flag#). Game_object *obj = get_item(parms[0]); int flag = parms[1].get_int_value(); if (obj) { obj->clear_flag(flag); if (flag == Obj_flags::dont_move) { // Show change in status. show_pending_text(); // Fixes Lydia-tatoo. gwin->set_all_dirty(); } else if (Is_moving_barge_flag(flag)) { // Stop barge object is on or part of. Barge_object *barge = Get_barge(obj); if (barge && barge == gwin->get_moving_barge()) gwin->set_moving_barge(0); } else if (flag == 0x14) // Handles Ferryman sailor = 0; } return(no_ret); } USECODE_INTRINSIC(set_path_failure) { // set_path_failure(fun, itemref, eventid) for the last NPC in // a path_run_usecode() call. int fun = parms[0].get_int_value(), eventid = parms[2].get_int_value(); Game_object *item = get_item(parms[1]); if (path_npc && item) // Set in path_run_usecode(). { If_else_path_actor_action *action = path_npc->get_action() ? path_npc->get_action()->as_usecode_path() : 0; if (action) // Set in in path action. action->set_failure( new Usecode_actor_action(fun, item, eventid)); } return no_ret; } USECODE_INTRINSIC(fade_palette) { // Fade(cycles?, ??(always 1), in_out (0=fade to black, 1=fade in)). int cycles = parms[0].get_int_value(); int inout = parms[2].get_int_value(); if (inout == 0) show_pending_text(); // Make sure prev. text was seen. gwin->get_pal()->fade(cycles, inout); return(no_ret); } USECODE_INTRINSIC(get_party_list2) { // Return party. Same as 0x23 // Probably returns a list of everyone with (or without) some flag // List of live chars? Dead chars? Usecode_value u(get_party()); return(u); } USECODE_INTRINSIC(set_camera) { // Set_camera(actor) Actor *actor = as_actor(get_item(parms[0])); if (actor) gwin->set_camera_actor(actor); return no_ret; } USECODE_INTRINSIC(in_combat) { // Are we in combat mode? return Usecode_value(gwin->in_combat()); } USECODE_INTRINSIC(center_view) { // Center view around given item. Game_object *obj = get_item(parms[0]); if (obj) { Tile_coord t = obj->get_tile(); gwin->center_view(t); activate_cached(t); // Mar-10-01 - For Test of Love. } return no_ret; } USECODE_INTRINSIC(get_dead_party) { // Return list of dead companions' bodies. int cnt = partyman->get_dead_count(); Usecode_value ret(cnt, 0); for (int i = 0; i < cnt; i++) { Game_object *body = gwin->get_body( partyman->get_dead_member(i)); // Body within 50 tiles (a guess)? if (body && body->distance(gwin->get_main_actor()) < 50) { Usecode_value v(body); ret.put_elem(i, v); } } return ret; } USECODE_INTRINSIC(play_sound_effect) { if (num_parms < 1) return(no_ret); // Play music(isongnum). COUT("Sound effect " << parms[0].get_int_value() << " request in usecode"); Audio::get_ptr()->play_sound_effect (parms[0].get_int_value()); return(no_ret); } USECODE_INTRINSIC(play_sound_effect2) { if (num_parms < 2) return(no_ret); // Play music(songnum, item). Game_object *obj = get_item(parms[1]); int volume = SDL_MIX_MAXVOLUME; // Set volume based on distance. int dir = 0; if (obj) { Tile_coord apos = gwin->get_main_actor()->get_tile(); Tile_coord opos = obj->get_tile(); int dist = apos.distance(opos); if (dist) { // 160/8 = 20 tiles. 20*20=400. volume = (SDL_MIX_MAXVOLUME*64)/(dist*dist); if (volume < 8) volume = 8; else if (volume > SDL_MIX_MAXVOLUME) volume = SDL_MIX_MAXVOLUME; dir = Get_direction16(apos.ty - opos.ty, opos.tx - apos.tx); } } #ifdef DEBUG cout << "Sound effect(2) " << parms[0].get_int_value() << " request in usecode with volume = " << volume << ", dir = " << dir << endl; #endif Audio::get_ptr()->play_sound_effect (parms[0].get_int_value(), volume, dir); return(no_ret); } USECODE_INTRINSIC(get_npc_id) { Actor *actor = as_actor(get_item(parms[0])); if (!actor) return(no_ret); return Usecode_value (actor->get_ident()); } USECODE_INTRINSIC(set_npc_id) { Actor *actor = as_actor(get_item(parms[0])); if (actor) actor->set_ident(parms[1].get_int_value()); return(no_ret); } USECODE_INTRINSIC(add_cont_items) { // Add items(num, item, ??quality?? (-359), frame (or -359), T/F). return add_cont_items(parms[0], parms[1], parms[2], parms[3], parms[4], parms[5]); } // Is this SI Only USECODE_INTRINSIC(remove_cont_items) { // Add items(num, item, ??quality?? (-359), frame (or -359), T/F). return remove_cont_items(parms[0], parms[1], parms[2], parms[3], parms[4], parms[5]); } /* * SI-specific functions. */ USECODE_INTRINSIC(show_npc_face0) { // Show_npc_face0(npc, frame). Show in position 0. show_npc_face(parms[0], parms[1], 0); return no_ret; } USECODE_INTRINSIC(show_npc_face1) { // Show_npc_face1(npc, frame). Show in position 1. show_npc_face(parms[0], parms[1], 1); return no_ret; } USECODE_INTRINSIC(remove_npc_face0) { show_pending_text(); conv->remove_slot_face(0); return no_ret; } USECODE_INTRINSIC(remove_npc_face1) { show_pending_text(); conv->remove_slot_face(1); return no_ret; } USECODE_INTRINSIC(set_conversation_slot) { // set_conversation_slot(0 or 1) - Choose which face is talking. conv->set_slot(parms[0].get_int_value()); return no_ret; } USECODE_INTRINSIC(init_conversation) { init_conversation(); return no_ret; } USECODE_INTRINSIC(end_conversation) { show_pending_text(); // Wait for click if needed. conv->init_faces(); // Removes faces from screen. gwin->set_all_dirty(); return no_ret; } USECODE_INTRINSIC(si_path_run_usecode) { // exec(npc, loc(x,y,z)?, eventid, itemref, usecode#, ??true/false). // Schedule Npc to walk to loc and then execute usecode. // Guessing: int always = parms[5].get_int_value(); path_run_usecode(parms[0], parms[1], parms[4], parms[3], parms[2], 1, always); return no_ret; } USECODE_INTRINSIC(error_message) { // exec(array) // Output everything to stdout for (int i = 0; i < num_parms; i++) { if (parms[i].is_int()) std::cout << parms[i].get_int_value() ; else if (parms[i].is_ptr()) std::cout << parms[i].get_ptr_value(); else if (!parms[i].is_array()) std::cout << parms[i].get_str_value(); else for (int j = 0; j < parms[i].get_array_size(); j++) { if (parms[i].get_elem(j).is_int()) std::cout << parms[i].get_elem(j).get_int_value() ; else if (parms[i].get_elem(j).is_ptr()) std::cout << parms[i].get_elem(j).get_ptr_value(); else if (!parms[i].get_elem(j).is_array()) std::cout << parms[i].get_elem(j).get_str_value(); } } std::cout << std::endl; return no_ret; } USECODE_INTRINSIC(set_polymorph) { // exec(npc, shape). // Npc's shape is change to shape. Actor *actor = as_actor(get_item(parms[0])); if (actor) actor->set_polymorph(parms[1].get_int_value()); return no_ret; } USECODE_INTRINSIC(set_new_schedules) { // set_new_schedules ( npc, time, activity, [x, y] ) // // or // // set_new_schedules ( npc, [ time1, time2, ...], // [activity1, activity2, ...], // [x1,y1, x2, y2, ...] ) // Actor *actor = as_actor(get_item(parms[0])); // If no actor return if (!actor) return no_ret; int count = parms[1].is_array()?parms[1].get_array_size():1; Schedule_change *list = new Schedule_change[count]; if (!parms[1].is_array()) { int time = parms[1].get_int_value(); int sched = parms[2].get_int_value(); int tx = parms[3].get_elem(0).get_int_value(); int ty = parms[3].get_elem(1).get_int_value(); list[0].set(tx, ty, sched, time); } else for (int i = 0; i < count; i++) { int time = parms[1].get_elem(i).get_int_value(); int sched = parms[2].get_elem(i).get_int_value(); int tx = parms[3].get_elem(i*2).get_int_value(); int ty = parms[3].get_elem(i*2+1).get_int_value(); list[i].set(tx, ty, sched, time); } actor->set_schedules(list, count); return no_ret; } USECODE_INTRINSIC(revert_schedule) { // revert_schedule(npc) // Reverts the schedule of the npc to the saved state in // /schedule.dat Actor *actor = as_actor(get_item(parms[0])); if (actor) gwin->revert_schedules(actor); return no_ret; } USECODE_INTRINSIC(run_schedule) { // run_schedule(npc) // I think this is actually reset activity to current // scheduled activity - Colourless Actor *actor = as_actor(get_item(parms[0])); if (actor) { actor->update_schedule(gclock->get_hour()/3, 7); } return no_ret; } USECODE_INTRINSIC(modify_schedule) { // modify_schedule ( npc, time, activity, [x, y] ) Actor *actor = as_actor(get_item(parms[0])); // If no actor return if (!actor) return no_ret; int time = parms[1].get_int_value(); int sched = parms[2].get_int_value(); int tx = parms[3].get_elem(0).get_int_value(); int ty = parms[3].get_elem(1).get_int_value(); actor->set_schedule_time_type(time, sched); actor->set_schedule_time_location(time, tx, ty); return no_ret; } USECODE_INTRINSIC(get_temperature) { Actor *npc = as_actor(get_item(parms[0])); return Usecode_value(npc ? npc->get_temperature() : 0); } USECODE_INTRINSIC(set_temperature) { // set_temperature(npc, value (0-63)). Actor *npc = as_actor(get_item(parms[0])); if (npc) npc->set_temperature(parms[1].get_int_value()); return no_ret; } #if 0 /* +++++Not used at the moment. */ USECODE_INTRINSIC(add_removed_npc) { // move_offscreen(npc, x, y) - I think (seems good) I think // // returns false if not moved // else, moves the object to the closest position off // Actor we want to move Actor *actor = as_actor(get_item(parms[0])); // Need to check superchunk int cx = actor->get_cx(); int cy = actor->get_cx(); int scx = cx / c_chunks_per_schunk; int scy = cy / c_chunks_per_schunk; int scx2 = parms[1].get_int_value() / c_tiles_per_schunk; int scy2 = parms[2].get_int_value() / c_tiles_per_schunk; // Are the coords are good if ( (cx == 0xff && scx2) || (cx != 0xff && scx != scx2) || (cy == 0xff && scy2) || (cy != 0xff && scy != scy2) ) return (Usecode_value(false)); // Ok they were good, now move it // Get the tiles around the edge of the screen Rectangle rect = gwin->get_win_tile_rect(); int sx = rect.x; // Tile coord of x start int ex = rect.x + rect.w; // Tile coord of x end int sy = rect.y; // y start int ey = rect.y + rect.h; // x end // The height of the Actor we are checking int height = actor->get_info().get_3d_height(); int i = 0, nlift = 0; int tx, ty; // Avatars coords Tile_coord av = gwin->get_main_actor()->get_tile();; Tile_coord close; // The tile coords of the closest tile int dist = -1; // The distance cy = sy/c_tiles_per_chunk; ty = sy%c_tiles_per_chunk; cout << "1" << endl; for (i = 0; i < rect.w; i++) { cx = (sx+i)/c_tiles_per_chunk; tx = (sx+i)%c_tiles_per_chunk; Map_chunk *clist = gmap->get_chunk_safely(cx, cy); clist->setup_cache(); if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1)) { Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift); if (cur.distance(av) < dist || dist == -1) { dist = cur.distance(av); cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl; close = cur; } } } cx = ex/c_tiles_per_chunk; tx = ex%c_tiles_per_chunk; cout << "2" << endl; for (i = 0; i < rect.h; i++) { cy = (sy+i)/c_tiles_per_chunk; ty = (sy+i)%c_tiles_per_chunk; Map_chunk *clist = gmap->get_chunk_safely(cx, cy); clist->setup_cache(); if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1)) { Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift); if (cur.distance(av) < dist || dist == -1) { dist = cur.distance(av); cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl; close = cur; } } } cy = ey/c_tiles_per_chunk; ty = ey%c_tiles_per_chunk; cout << "3" << endl; for (i = 0; i < rect.w; i++) { cx = (ex-i)/c_tiles_per_chunk; tx = (ex-i)%c_tiles_per_chunk; Map_chunk *clist = gmap->get_chunk_safely(cx, cy); clist->setup_cache(); if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1)) { Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift); if (cur.distance(av) < dist || dist == -1) { dist = cur.distance(av); cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl; close = cur; } } } cx = sx/c_tiles_per_chunk; tx = sx%c_tiles_per_chunk; cout << "4" << endl; for (i = 0; i < rect.h; i++) { cy = (ey-i)/c_tiles_per_chunk; ty = (ey-i)%c_tiles_per_chunk; Map_chunk *clist = gmap->get_chunk_safely(cx, cy); clist->setup_cache(); if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1)) { Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift); if (cur.distance(av) < dist || dist == -1) { dist = cur.distance(av); cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl; close = cur; } } } if (dist != -1) { actor->move(close); return (Usecode_value(true)); } return (Usecode_value(false)); } #endif USECODE_INTRINSIC(approach_avatar) { // Approach_avatar(npc, ?, ?). // Actor we want to move Actor *actor = as_actor(get_item(parms[0])); if (!actor || actor->is_dead()) return Usecode_value(0); // Guessing!! If already close... if (actor->distance(gwin->get_main_actor()) < 10) return Usecode_value(1); // Approach, and wait. if (!actor->approach_another(gwin->get_main_actor(), true)) return Usecode_value(0); return Usecode_value(1); } USECODE_INTRINSIC(set_barge_dir) { // set_barge_dir(barge, dir (0-7)). Game_object *obj = get_item(parms[0]); int dir = parms[1].get_int_value(); Barge_object *barge = obj ? obj->as_barge() : 0; if (barge) barge->face_direction(dir); return no_ret; } USECODE_INTRINSIC(telekenesis) { // telekenesis(fun#) - Save item for executing Usecode on. telekenesis_fun = parms[0].get_int_value(); return no_ret; } USECODE_INTRINSIC(a_or_an) { // a_or_an (word) // return a/an depending on 'word' if (strchr("aeiouyAEIOUY", (parms[0].get_str_value())[0]) == 0) return (Usecode_value("a")); else return (Usecode_value("an")); } USECODE_INTRINSIC(remove_from_area) { // Remove_from_area(shapenum, framenum, [x,y]from, [x,y]to). int shnum = parms[0].get_int_value(), frnum = parms[1].get_int_value(); int fromx = parms[2].get_elem(0).get_int_value(), fromy = parms[2].get_elem(1).get_int_value(), tox = parms[3].get_elem(0).get_int_value(), toy = parms[3].get_elem(1).get_int_value(); Rectangle area(fromx, fromy, tox - fromx + 1, toy - fromy + 1); if (area.w <= 0 || area.h <= 0) return no_ret; Game_object_vector vec; // Find objects. Map_chunk::find_in_area(vec, area, shnum, frnum); // Remove them. for (Game_object_vector::iterator it = vec.begin(); it != vec.end(); it++) { Game_object *obj = *it; gwin->add_dirty(obj); obj->remove_this(0); } return no_ret; } USECODE_INTRINSIC(infravision) { // infravision(npc, onoff) Actor *npc = as_actor(get_item(parms[0])); if (npc && npc->is_in_party()) { if (parms[1].get_int_value()) { // On? cheat.set_infravision(true); gwin->get_pal()->set(0); } else { cheat.set_infravision(false); gclock->set_palette(); } } return no_ret; } // parms[0] = quality of key to be added USECODE_INTRINSIC(add_to_keyring) { getKeyring()->addkey(parms[0].get_int_value()); return no_ret; } // parms[0] = quality of key to check // returns true if key is on keyring USECODE_INTRINSIC(is_on_keyring) { if (getKeyring()->checkkey(parms[0].get_int_value())) return Usecode_value(true); else return Usecode_value(false); } USECODE_INTRINSIC(save_pos) { // save_pos(item). Game_object *item = get_item(parms[0]); if (item) saved_pos = item->get_tile(); return no_ret; } USECODE_INTRINSIC(teleport_to_saved_pos) { // teleport_to_saved_pos(actor). Only supported for Avatar for now. Actor *npc = as_actor(get_item(parms[0])); if (npc == gwin->get_main_actor()) { // Bad value? if (saved_pos.tx < 0 || saved_pos.tx >= c_num_tiles) // Fix old games. Send to Monitor. saved_pos = Tile_coord(719, 2608, 1); gwin->teleport_party(saved_pos); } return no_ret; } USECODE_INTRINSIC(get_item_usability) { // Complete guess: Returns 1 for grabbable items (for fetch spell). Game_object *obj = get_item(parms[0]); if (!obj || !obj->is_dragable()) return Usecode_value(0); else return Usecode_value(1);// Only 1 I'm pretty sure of. } USECODE_INTRINSIC(get_skin_colour) { // Gets skin colour of avatar. 0 (wh), 1 (br) or 2 (bl) Main_actor *av = gwin->get_main_actor(); return Usecode_value(av->get_skin_color()); } /* * This is like the C version, but only '%s' is supported, and all the * parms should be packed into one array. * Added for Exult. */ USECODE_INTRINSIC(printf) { Usecode_value ret(""); const char *fmt = parms[0].get_elem0().get_str_value(); int count; cout << endl; // For now... if (!fmt || (count = parms[0].get_array_size()) <= 1) { parms[0].print(cout); return ret; } int i = 1; // Parm. #. while (*fmt) { const char *spec = strchr(fmt, '%'); if (!spec) spec = fmt + std::strlen(fmt); cout.write(fmt, spec - fmt); if (*spec == '%') { if (spec[1] == 's') { Usecode_value p = i < count ? parms[0][i] : Usecode_value(0); if (p.get_type() == Usecode_value::int_type) cout << p.get_int_value(); else p.print(cout); spec += 2; } else { cout << '%'; spec++; } } fmt = spec; } return ret; } exult-1.2/usecode/debugmsg.h0000644000175000001440000000360007724430454011577 /* * debugmsg.h: debugging messages * * Copyright (C) 2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DEBUGMSG_H #define _DEBUGMSG_H namespace Exult_server { enum Debug_msg_type { // c->s = client to server, s->c = server to client, * = both ways dbg_continue = 0, // (c->s) continue running dbg_stepinto = 1, // (c->s) step (into calls) dbg_stepover = 2, // (c->s) step (over calls) dbg_finish = 3, // (c->s) finish current function dbg_break = 4, // (c->s) break imediately dbg_on_breakpoint = 5, // (s->c) hit a breakpoint dbg_get_callstack = 6, // (c->s) request callstack dbg_callstack = 7, // (s->c) sending callstack dbg_stackframe = 8, // (s->c) sending stack frame dbg_get_stack = 9, // (c->s) request (data) stack dbg_stack = 10, // (s->c) sending stack dbg_continuing = 11, // (s->c) continuing from breakpoint dbg_get_status = 12, // (c->s) request status (breakpoint/running) dbg_set_location_bp = 13,// ( * ) set a breakpoint at a specific location dbg_clear_breakpoint= 14,// ( * ) clear a breakpoint dbg_get_breakpoints = 15 // (c->s) request all (permanent) breakpoints }; } #endif exult-1.2/AUTHORS0000644000175000001440000000073007472420447007254 The Exult Team -------------- Jeff S. Freedman Dancer Vesperman Willem Jan Palenstijn Tristan Tarrant Max Horn Coder Infidel Ryan Nunn Patrick Burke Dominik Reichardt Ruediger Hanke Simon Quinn exult-1.2/pathfinder/0000777000175000001440000000000010062225331010374 5exult-1.2/pathfinder/Astar.h0000644000175000001440000000325407724430453011555 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ASTAR_H #define ASTAR_H #include "PathFinder.h" #include class Astar: public virtual PathFinder { std::vector path; // Coords. to goal. int pathlen; // Length of path. int dir; // 1 or -1. int stop; // Index to stop at. int next_index; // Index of next tile to return. public: Astar() : PathFinder(),path(), pathlen(0), dir(0),stop(0),next_index(0) { } // Find a path from sx,sy,sz to dx,dy,dz // Return 0 if no path can be traced. // Return !0 if path found virtual int NewPath(Tile_coord s, Tile_coord d, Pathfinder_client *client); // Retrieve the coordinates of the next step on the path virtual int GetNextStep(Tile_coord& n, bool& done); // Set to retrieve in opposite order. virtual int set_backwards(); virtual int following_smart_path() // Astar? { return 1; } virtual int get_num_steps(); // # of steps left to take. virtual ~Astar(); }; #endif exult-1.2/pathfinder/PathFinder.h0000644000175000001440000000467407724430453012536 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PATHFINDER_H #define PATHFINDER_H #include "tiles.h" /* * This class provides A* cost methods. */ class Pathfinder_client { private: int move_flags; public: // Figure when to give up. virtual int get_max_cost(int cost_to_goal); // Figure cost for a single step. virtual int get_step_cost(Tile_coord from, Tile_coord& to) = 0; // Estimate cost between two points. virtual int estimate_cost(Tile_coord& from, Tile_coord& to) = 0; // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); int get_move_flags() { return move_flags; } void set_move_flags(int m) { move_flags = m;} }; /* * Base class for all PathFinders. */ class PathFinder { protected: Tile_coord src; // Source tile. Tile_coord dest; // Destination. public: // Find a path from sx,sy,sz to dx,dy,dz // Return 0 if no path can be traced. // Return !0 if path found PathFinder() : src(),dest() { } virtual int NewPath(Tile_coord s, Tile_coord d, Pathfinder_client *client)=0; // Retrieve starting point (set by subclasses). Tile_coord get_src() { return src; } // Retrieve current destination (set by subclasses). Tile_coord get_dest() { return dest; } // Retrieve the coordinates of the next step on the path virtual int GetNextStep(Tile_coord& n, bool& done)=0; int GetNextStep(Tile_coord& n) { // If you don't care about last step. bool d; return GetNextStep(n, d); } // Set to retrieve in opposite order. virtual int set_backwards() { return 0; } // Default: Can't do it. virtual int following_smart_path() // Astar? { return 0; } virtual int get_num_steps() = 0;// # of steps left to take. virtual ~PathFinder(); }; #endif exult-1.2/pathfinder/Makefile.am0000644000175000001440000000046107344552064012364 INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../objs $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libpathfinder.la libpathfinder_la_SOURCES = \ Astar.cc \ Astar.h \ PathFinder.cc \ PathFinder.h \ Zombie.cc \ Zombie.h \ path.cc CLEANFILES = *~ exult-1.2/pathfinder/Makefile.in0000644000175000001440000002414610061527055012373 # Makefile.in generated automatically by automake 1.5 from Makefile.am. # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_alias = @host_alias@ host_triplet = @host@ AMTAR = @AMTAR@ AS = @AS@ AWK = @AWK@ CC = @CC@ CPP = @CPP@ CXX = @CXX@ DEBUG_FLAGS = @DEBUG_FLAGS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ EXEEXT = @EXEEXT@ EXE_TARGET = @EXE_TARGET@ EXULT_DATADIR = @EXULT_DATADIR@ FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ FT2CONFIG = @FT2CONFIG@ GIMPTOOL = @GIMPTOOL@ GIMP_INCLUDES = @GIMP_INCLUDES@ GIMP_LIBS = @GIMP_LIBS@ GIMP_PLUGIN_PREFIX = @GIMP_PLUGIN_PREFIX@ GLADE_INCLUDES = @GLADE_INCLUDES@ GLADE_LIBS = @GLADE_LIBS@ HAVE_TIMIDITY_BIN = @HAVE_TIMIDITY_BIN@ ICON_FILE = @ICON_FILE@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMID_INCLUDES = @KMID_INCLUDES@ KMID_LIBS = @KMID_LIBS@ LEX = @LEX@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENGL_LIBS = @OPENGL_LIBS@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STRIP = @STRIP@ SYSLIBS = @SYSLIBS@ VERSION = @VERSION@ WARNINGS = @WARNINGS@ WINDOWING_SYSTEM = @WINDOWING_SYSTEM@ YACC = @YACC@ ZLIB_LIBS = @ZLIB_LIBS@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ x_libraries = @x_libraries@ INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../objs $(SDL_CFLAGS) $(INCDIRS) \ $(WINDOWING_SYSTEM) $(DEBUG_FLAGS) $(CPPFLAGS) noinst_LTLIBRARIES = libpathfinder.la libpathfinder_la_SOURCES = \ Astar.cc \ Astar.h \ PathFinder.cc \ PathFinder.h \ Zombie.cc \ Zombie.h \ path.cc CLEANFILES = *~ subdir = pathfinder mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libpathfinder_la_LDFLAGS = libpathfinder_la_LIBADD = am_libpathfinder_la_OBJECTS = Astar.lo PathFinder.lo Zombie.lo path.lo libpathfinder_la_OBJECTS = $(am_libpathfinder_la_OBJECTS) DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/Astar.Plo $(DEPDIR)/PathFinder.Plo \ @AMDEP_TRUE@ $(DEPDIR)/Zombie.Plo $(DEPDIR)/path.Plo CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXFLAGS = @CXXFLAGS@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libpathfinder_la_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libpathfinder_la_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu pathfinder/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && \ CONFIG_HEADERS= CONFIG_LINKS= \ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) libpathfinder.la: $(libpathfinder_la_OBJECTS) $(libpathfinder_la_DEPENDENCIES) $(CXXLINK) $(libpathfinder_la_LDFLAGS) $(libpathfinder_la_OBJECTS) $(libpathfinder_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Astar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/PathFinder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/Zombie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/path.Plo@am__quote@ distclean-depend: -rm -rf $(DEPDIR) .cc.o: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< .cc.obj: @AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CXXCOMPILE) -c -o $@ `cygpath -w $<` .cc.lo: @AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$< CXXDEPMODE = @CXXDEPMODE@ uninstall-info-am: tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) GTAGS: here=`CDPATH=: && cd $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ $(mkinstalldirs) "$(distdir)/$$dir"; \ fi; \ if test -d $$d/$$file; then \ cp -pR $$d/$$file $(distdir) \ || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-libtool distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool uninstall-am: uninstall-info-am .PHONY: GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES distclean \ distclean-compile distclean-depend distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool tags uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: exult-1.2/pathfinder/Astar.cc0000644000175000001440000000401507724430453011707 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Astar.h" /* * Find path from source to destination. * * Output: 1 if successful, else 0. */ int Astar::NewPath(Tile_coord s, Tile_coord d, Pathfinder_client *client) { extern Tile_coord *Find_path(Tile_coord, Tile_coord, Pathfinder_client *client, int& plen); src = s; // Store start, destination. dest = d; path.clear(); // Clear out old path, if there. Tile_coord *t = Find_path(s, d, client, pathlen); bool success = (t != 0); for(int i=0;i #endif #include #include "hash_utils.h" #include "PathFinder.h" #include "exult_constants.h" #include "vec.h" using std::cout; using std::endl; using std::size_t; Tile_coord *Find_path ( Tile_coord start, // Where to start from. Tile_coord goal, // Where to end up. Pathfinder_client *client, // Provides costs. int& pathlen // Length of path returned. ); /* * Iterate through neighbors of a tile (in 2 dimensions). */ class Neighbor_iterator { Tile_coord tile; // Original tile. static int coords[16]; // Coords to go through ((x,y) pairs) int index; // 0-7. public: Neighbor_iterator(Tile_coord t) : tile(t), index(0) { } // Get next neighbor. int operator()(Tile_coord& newt) { if (index < 8) { newt = Tile_coord(tile.tx + coords[2*index], tile.ty + coords[2*index + 1], tile.tz); index++; // Handle world-wrapping. newt.tx = (newt.tx + c_num_tiles)%c_num_tiles; newt.ty = (newt.ty + c_num_tiles)%c_num_tiles; return (1); } return (0); } }; /* * Statics: */ int Neighbor_iterator::coords[16] = { -1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 1 }; /* * A node for our search: */ class Search_node { Tile_coord tile; // The coords (x, y, z) in tiles. short start_cost; // Actual cost from start. short goal_cost; // Estimated cost to goal. short total_cost; // Sum of the two above. Search_node *parent; // Prev. in path. Search_node *priority_next; // ->next with same total_cost, or // NULL if not in 'open' set. public: Search_node(Tile_coord& t, short scost, short gcost, Search_node *p) : tile(t), start_cost(scost), goal_cost(gcost), parent(p), priority_next(0) { total_cost = gcost + scost; } // For creating a key to search for. Search_node(Tile_coord& t) : tile(t) { } Tile_coord get_tile() const { return tile; } int get_start_cost() { return start_cost; } int get_goal_cost() { return goal_cost; } int get_total_cost() { return total_cost; } int is_open() // In 'open' priority queue? { return priority_next != 0; } void update(short scost, short gcost, Search_node *p) { start_cost = scost; goal_cost = gcost; total_cost = gcost + scost; parent = p; } // Create path back to start. Tile_coord *create_path(int& pathlen) { int cnt = 1; // This. // Count back to start. Search_node *each = this; while ((each = each->parent) != 0) cnt++; pathlen = cnt - 1; // Don't want starting tile. Tile_coord *result = new Tile_coord[pathlen]; each = this; for (int i = pathlen - 1; i >= 0; i--) { result[i] = each->tile; each = each->parent; } return result; } #if VERIFYCHAIN // Returns 0 if bad chain. int verify_chain(Search_node *last, int removed = 0) { if (!last) return (1); int found = 0; Search_node *prev = last; int cnt = 0; do { Search_node *next = prev->priority_next; if (next == this) found = 1; prev = next; if (cnt > 10000) break; } while (prev != last); if (!found && !removed) return (0); if (cnt == 10000) return (0); return (1); } #endif // Add to chain of same priorities. void add_to_chain(Search_node *&last) { if (last) { priority_next = last->priority_next; last->priority_next = this; } else { last = this; priority_next = this; } #if VERIFYCHAIN if (!verify_chain(last)) cout << "Bad chain after adding." << endl; #endif } // Remove this from its chain. void remove_from_chain(Search_node *&last) { #if VERIFYCHAIN if (!verify_chain(last)) cout << "Bad chain before removing." << endl; #endif if (priority_next == this) // Only one in chain? last = 0; else { // Got to find prev. to this. Search_node *prev = last; do { Search_node *next = prev->priority_next; if (next == this) break; prev = next; } while (prev != last); if (prev) { prev->priority_next = priority_next; if (last == this) last = priority_next; } } priority_next = 0; // No longer in 'open'. #if VERIFYCHAIN if (!verify_chain(last, 1)) cout << "Bad chain after removing." << endl; #endif } // Remove 1st from a priority chain. static Search_node *remove_first_from_chain(Search_node *&last) { Search_node *first = last->priority_next; if (first == last) // Last entry? last = 0; else last->priority_next = first->priority_next; first->priority_next = 0; return first; } }; #ifndef DONT_HAVE_HASH_SET /* * Hash function for nodes: */ class Hash_node { public: size_t operator() (const Search_node *a) const { const Tile_coord t = a->get_tile(); return ((t.tz << 24) + (t.ty << 12) + t.tx); } }; /* * For testing if two nodes match. */ class Equal_nodes { public: bool operator() (const Search_node *a, const Search_node *b) const { Tile_coord ta = a->get_tile(), tb = b->get_tile(); return ta == tb; } }; #else /* * "Less than" relation for nodes */ class Less_nodes { public: bool operator() (const Search_node *a, const Search_node *b) const { Tile_coord ta = a->get_tile(), tb = b->get_tile(); uint32 apos = ta.tx << 16, bpos = tb.tx << 16; apos |= ta.ty << 4; bpos |= tb.ty << 4; apos |= ta.tz; bpos |= tb.tz; /* Because #(short x short) is <= #int, we can define an injective projection, ** which is all we need. */ return apos < bpos; } }; #endif /* * The priority queue for the A* algorithm: */ class A_star_queue { Exult_vector open;// Nodes to be done, by priority. Each // is a ->last node in chain. int best; // Index of 1st non-null ent. in open. // For finding each tile's node: #ifndef DONT_HAVE_HASH_SET typedef hash_set Lookup_set; #else typedef std::set Lookup_set; #endif Lookup_set lookup; public: #ifndef DONT_HAVE_HASH_SET A_star_queue() : open(256), lookup(1000) #else A_star_queue() : open(256), lookup() #endif { open.insert(open.begin(), 256, (Search_node *) 0); best = open.size(); // Best is past end. } ~A_star_queue() { #if 1 /* This _should_ work, but might hang some hash_set implementations. The problem is that on deleting the Search_node, the hash_set can no longer properly evaluate the hash value (since the hash function dereferences the Search_node* stored). This might cause an endless loop. */ for(Lookup_set::iterator X = lookup.begin(); X != lookup.end();) { Search_node *sn = *X; X++; delete sn; // only delete this _after_ iterating } #endif lookup.clear(); // Remove all nodes. } void add_back(Search_node *nd) // Add an existing node back to 'open'. { int total_cost = nd->get_total_cost(); Search_node *last = total_cost < open.size() ? open[total_cost] : 0; nd->add_to_chain(last); // Add node to this chain. open.put(total_cost, last); if (total_cost < best) best = total_cost; } void add(Search_node *nd) // Add new node to 'open' set. { lookup.insert(nd); add_back(nd); } // Remove node from 'open' set. void remove_from_open(Search_node *nd) { if (!nd->is_open()) return; // Nothing to do. int total_cost = nd->get_total_cost(); Search_node *last = total_cost < open.size() ? open[total_cost] : 0; nd->remove_from_chain(last); // Store updated 'last'. open.put(total_cost, last); if (!last) // Last in chain? { if (total_cost == best) { int cnt = open.size(); for (best++; best < cnt; best++) if (open[best] != 0) break; } } } Search_node *pop() // Pop best from priority queue. { Search_node *last = best < open.size() ? open[best] : 0; if (!last) return (0); // Return 1st in list. Search_node *node = Search_node::remove_first_from_chain(last); // Store updated 'last'. open.put(best, last); if (!last) // List now empty? { int cnt = open.size(); for (best++; best < cnt; best++) if (open[best] != 0) break; } return node; } // Find node for given tile. Search_node *find(Tile_coord tile) { Search_node key(tile); #ifndef DONT_HAVE_HASH_SET hash_set::iterator it = lookup.find(&key); #else std::set::iterator it = lookup.find(&key); #endif if (it != lookup.end()) return *it; else return 0; } }; static int tracing = 0; /* * First cut at using the A* pathfinding algorithm. * * Output: ->(allocated) array of Tile_coords to follow, or 0 if failed. */ Tile_coord *Find_path ( Tile_coord start, // Where to start from. Tile_coord goal, // Where to end up. Pathfinder_client *client, // Provides costs. int& pathlen // Length of path returned. ) { A_star_queue nodes; // The priority queue & hash table. int max_cost = client->estimate_cost(start, goal); // Create start node. nodes.add(new Search_node(start, 0, max_cost, 0)); // Figure when to give up. max_cost = client->get_max_cost(max_cost); Search_node *node; // Try 'best' node each iteration. while ((node = nodes.pop()) != 0) { if (tracing) cout << "Goal: (" << goal.tx << ", " << goal.ty << "), Node: (" << node->get_tile().tx << ", " << node->get_tile().ty << ")" << endl; Tile_coord curtile = node->get_tile(); if (client->at_goal(curtile, goal)) // Success. return node->create_path(pathlen); // Go through surrounding tiles. Neighbor_iterator get_next(curtile); Tile_coord ntile(0, 0, 0); while (get_next(ntile)) { // Get cost to next tile. int step_cost = client->get_step_cost(curtile, ntile); // Blocked? if (step_cost == -1) continue; // Get cost from start to ntile. int new_cost = node->get_start_cost() + step_cost; // See if next tile already seen. Search_node *next = nodes.find(ntile); // Already there, and cheaper? if (next && next->get_start_cost() <= new_cost) continue; int new_goal_cost = client->estimate_cost(ntile, goal); // Skip nodes too far away. if (new_cost + new_goal_cost >= max_cost) continue; if (!next) // Create if necessary. { next = new Search_node(ntile, new_cost, new_goal_cost, node); nodes.add(next); } else { // It's going to move. nodes.remove_from_open(next); next->update(new_cost, new_goal_cost, node); nodes.add_back(next); } } } pathlen = 0; // Failed if here. return 0; } exult-1.2/pathfinder/Zombie.cc0000644000175000001440000000574407724430453012074 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "Zombie.h" /* * Find path from source to destination. * * Output: 1 if successful, else 0. */ int Zombie::NewPath(Tile_coord s, Tile_coord d, Pathfinder_client *) { src = s; // Store start, destination. dest = d; cur = s; // Get current coords. sum = 0; // Clear accumulator. long deltax = Tile_coord::delta(cur.tx, dest.tx); long deltay = Tile_coord::delta(cur.ty, dest.ty); if (!deltax && !deltay) // Going nowhere? { major_distance = 0; return (0); } unsigned int abs_deltax, abs_deltay; int x_dir, y_dir; if (deltay >= 0) // Figure directions. { y_dir = 1; abs_deltay = deltay; } else { y_dir = -1; abs_deltay = -deltay; } if (deltax >= 0) { x_dir = 1; abs_deltax = deltax; } else { x_dir = -1; abs_deltax = -deltax; } if (abs_deltay >= abs_deltax) // Moving faster along y? { major_coord = &cur.ty; minor_coord = &cur.tx; major_dir = y_dir; minor_dir = x_dir; major_delta = abs_deltay; minor_delta = abs_deltax; } else // Moving faster along x? { major_coord = &cur.tx; minor_coord = &cur.ty; major_dir = x_dir; minor_dir = y_dir; major_delta = abs_deltax; minor_delta = abs_deltay; } major_distance = major_delta; // How far to go. return (1); } /* * Get next point on path to go to (in tile coords). * * Output: 0 if all done. */ int Zombie::GetNextStep(Tile_coord& n, bool& done) { if (major_distance <= 0) { done = true; return (0); } // Subtract from distance to go. major_distance -= major_frame_incr; // Accumulate change. sum += major_frame_incr * minor_delta; // Figure change in slower axis. int minor_frame_incr = sum/major_delta; sum = sum % major_delta; // Remove what we used. // Update coords. within world. *major_coord += major_dir*major_frame_incr; *minor_coord += minor_dir*minor_frame_incr; // Watch for wrapping. *major_coord = (*major_coord + c_num_tiles)%c_num_tiles; *minor_coord = (*minor_coord + c_num_tiles)%c_num_tiles; n = cur; // Return new tile. // ++++++For now, ignore tz. done = (major_distance <= 0); // Indicate if this is the last one. return (1); } /* * Delete. */ Zombie::~Zombie ( ) { } exult-1.2/pathfinder/PathFinder.cc0000644000175000001440000000261407724430453012664 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "PathFinder.h" /* * Given the estimated cost from start to goal, figure the max. cost * before the pathfinder should quit. */ int Pathfinder_client::get_max_cost ( int cost_to_goal // From estimate_cost(start, goal). ) { int max_cost = 3*cost_to_goal; // (Raised from 64 on 9/4/2000). return (max_cost < 74 ? 74 : max_cost); } /* * Is tile at goal? */ int Pathfinder_client::at_goal ( Tile_coord& tile, Tile_coord& goal ) { return (tile.tx == goal.tx && tile.ty == goal.ty && (goal.tz == -1 || tile.tz == goal.tz)); } PathFinder::~PathFinder() {} exult-1.2/pathfinder/Zombie.h0000644000175000001440000000370307724430453011727 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ZOMBIE_H #define ZOMBIE_H #include "PathFinder.h" class Zombie: public virtual PathFinder { int major_distance; // Distance in tiles to go. int major_frame_incr; // # steps to take in faster dir. Tile_coord cur; // Current pos. within world. // ->'s to cur.tx, cur.ty. short *major_coord, *minor_coord; int major_dir, minor_dir; // 1 or -1 for dir. along each axis. int major_delta, minor_delta; // For each tile we move along major // axis, we add 'minor_delta'. When // the sum >= 'major_delta', we move // 1 tile along minor axis, and // subtract 'major_delta' from sum. int sum; // Sum of 'minor_delta''s. public: Zombie(int major_incr = 1) : major_distance(0), major_frame_incr(major_incr) { } // Find a path from sx,sy,sz to dx,dy,dz // Return 0 if no path can be traced. // Return !0 if path found virtual int NewPath(Tile_coord s, Tile_coord d, Pathfinder_client *client); // Retrieve the coordinates of the next step on the path virtual int GetNextStep(Tile_coord& n, bool& done); virtual int get_num_steps() // # of steps left to take. { return major_distance/major_frame_incr; } virtual ~Zombie(); }; #endif exult-1.2/keyactions.cc0000644000175000001440000005000610061526460010653 /* * Copyright (C) 2001-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "keyactions.h" #include "keys.h" #include "gump_utils.h" #include "gamewin.h" #include "mouse.h" #include "actors.h" #include "game.h" #include "exult.h" #include "exult_types.h" #include "exult_constants.h" #include "File_gump.h" #include "Scroll_gump.h" #include "cheat.h" #include "combat_opts.h" #include "ucmachine.h" #include "party.h" #include "Audio.h" #include "Gamemenu_gump.h" #include "Newfile_gump.h" #include "Face_stats.h" #include "Gump_manager.h" #include "effects.h" #include "palette.h" /* * Get the i'th party member, with the 0'th being the Avatar. */ static Actor *Get_party_member ( int num // 0=avatar. ) { int npc_num = 0; // Default to Avatar if (num > 0) npc_num = Game_window::get_instance()->get_party_man()->get_member(num - 1); return Game_window::get_instance()->get_npc(npc_num); } // { ActionQuit, 0, "Quit", true, false, NONE }, void ActionQuit(int *params) { Game_window::get_instance()->get_gump_man()->okay_to_quit(); } // { ActionOldFileGump, 0, "Save/restore", true, false, NONE }, void ActionOldFileGump(int *params) { File_gump *fileio = new File_gump(); Game_window::get_instance()->get_gump_man()->do_modal_gump(fileio, Mouse::hand); delete fileio; } // { ActionMenuGump, 0, "GameMenu", true, false, NONE }, void ActionMenuGump(int *params) { Gamemenu_gump *gmenu = new Gamemenu_gump(); Game_window::get_instance()->get_gump_man()->do_modal_gump(gmenu, Mouse::hand); delete gmenu; } // { ActionFileGump, 0, "Save/restore", true, false, NONE }, void ActionFileGump(int *params) { Newfile_gump *fileio = new Newfile_gump(); Game_window::get_instance()->get_gump_man()->do_modal_gump(fileio, Mouse::hand); delete fileio; } // { ActionQuicksave, 0, "Quick-save", true, false, NONE }, void ActionQuicksave(int *params) { Game_window *gwin = Game_window::get_instance(); try { gwin->write(); } catch(exult_exception &e) { gwin->get_effects()->center_text("Saving game failed!"); return; } gwin->get_effects()->center_text("Game saved"); } // { ActionQuickrestore, 0, "Quick-restore", true, false, NONE }, void ActionQuickrestore(int *params) { Game_window *gwin = Game_window::get_instance(); try { gwin->read(); } catch(exult_exception &e) { gwin->get_effects()->center_text("Restoring game failed!"); return; } gwin->get_effects()->center_text("Game restored"); gwin->paint(); } // { ActionAbout, 0, "About Exult", true, false, NONE }, void ActionAbout(int *params) { Game_window *gwin = Game_window::get_instance(); Scroll_gump *scroll; scroll = new Scroll_gump(); scroll->add_text("Exult V"VERSION"\n"); scroll->add_text("(C) 1998-2004 Exult Team\n\n"); scroll->add_text("Available under the terms of the "); scroll->add_text("GNU General Public License\n\n"); scroll->add_text("http://exult.sourceforge.net\n"); scroll->paint(); do { int x, y; Get_click(x,y, Mouse::hand); } while (scroll->show_next_page()); gwin->paint(); delete scroll; } // { ActionHelp, 0, "List keys", true, false, NONE }, void ActionHelp(int *params) { keybinder->ShowHelp(); } // { ActionCloseGumps, 0, "Close gumps", false, false, NONE }, void ActionCloseGumps(int *params) { Game_window::get_instance()->get_gump_man()->close_all_gumps(); } // { ActionCloseOrMenu, "Game menu", true, false, NONE }, void ActionCloseOrMenu(int* params) { Game_window *gwin = Game_window::get_instance(); if (gwin->get_gump_man()->showing_gumps(true)) gwin->get_gump_man()->close_all_gumps(); else ActionMenuGump(0); } // { ActionScreenshot, 0, "Take screenshot", true, false, NONE }, void ActionScreenshot(int *params) { make_screenshot(); } // { ActionRepaint, 0, "Repaint screen", false, false, NONE }, void ActionRepaint(int *params) { Game_window::get_instance()->paint(); } // { ActionResIncrease, 0, "Increase resolution", true, true, NONE }, void ActionResIncrease(int *params) { increase_resolution(); } // { ActionResDecrease, 0, "Decrease resolution", true, true, NONE }, void ActionResDecrease(int *params) { decrease_resolution(); } // { ActionBrighter, 0, "Increase brightness", true, false, NONE }, void ActionBrighter(int *params) { change_gamma(true); } // { ActionDarker, 0, "Decrease brightness", true, false, NONE }, void ActionDarker(int *params) { change_gamma(false); } // { ActionFullscreen, 0, "Toggle fullscreen", true, false, NONE }, void ActionFullscreen(int *params) { Game_window *gwin = Game_window::get_instance(); gwin->get_win()->toggle_fullscreen(); gwin->paint(); } // { ActionUseItem, 3, "Use item", false, false, NONE }, // params[0] = shape nr. // params[1] = frame nr. // params[2] = quality void ActionUseItem(int *params) { if (params[1] == -1) params[1] = c_any_framenum; if (params[2] == -1) params[2] = c_any_qual; Game_window::get_instance()->activate_item(params[0], params[1], params[2]); Mouse::mouse->set_speed_cursor(); } // { ActionUseItem, 3, "Use food", false, false, NONE }, void ActionUseFood(int *params) { Game_window *gwin = Game_window::get_instance(); if (!gwin->activate_item(377) && // First try normal food items. GAME_SI) // SI has 'everlasting goblet'. gwin->activate_item(0x268, 20); Mouse::mouse->set_speed_cursor(); } // { ActionCombat, 0, "Toggle combat", true, false, NONE }, void ActionCombat(int *params) { Game_window *gwin = Game_window::get_instance(); gwin->toggle_combat(); gwin->paint(); Mouse::mouse->set_speed_cursor(); } // { ActionCombatPause, 0, "Pause combat", true, false, NONE }, void ActionCombatPause(int *params) { Combat::toggle_pause(); Mouse::mouse->set_speed_cursor(); } // { ActionTarget, 0, "Target mode", true, false, NONE }, void ActionTarget(int *params) { int x, y; if (!Get_click(x, y, Mouse::greenselect)) return; Game_window::get_instance()->double_clicked(x, y); Mouse::mouse->set_speed_cursor(); } // { ActionInventory, 1, "Show inventory", true, false, NONE }, // params[0] = party member (0-7), or -1 for 'next' void ActionInventory(int *params) { Game_window *gwin = Game_window::get_instance(); static int inventory_page = -1; Actor *actor; if (params[0] == -1) { Gump_manager *gump_man = gwin->get_gump_man(); int party_count = gwin->get_party_man()->get_count(); int shapenum; for(int i=0;i<=party_count;++i) { actor = Get_party_member(i); if (!actor) continue; shapenum = actor->inventory_shapenum(); // Check if this actor's inventory page is open or not if (!gump_man->find_gump(actor, shapenum)) { gump_man->add_gump(actor, shapenum); //force showing inv. inventory_page = i; return; } } inventory_page = (inventory_page+1)%(party_count+1); } else { inventory_page = params[0]; if (inventory_page < 0 || inventory_page > gwin->get_party_man()->get_count()) return; } actor = Get_party_member(inventory_page); if (actor) { actor->show_inventory(); //force showing inv. } Mouse::mouse->set_speed_cursor(); } // { ActionTryKeys, 0, "Try keys", true, false, NONE }, void ActionTryKeys(int *params) { Game_window *gwin = Game_window::get_instance(); int x, y; // Allow dragging. if (!Get_click(x, y, Mouse::greenselect, 0, true)) return; // Look for obj. in open gump. Gump *gump = gwin->get_gump_man()->find_gump(x, y); Game_object *obj; if (gump) obj = gump->find_object(x, y); else // Search rest of world. obj = gwin->find_object(x, y); if (!obj) return; int qual = obj->get_quality(); // Key quality should match. Actor *party[10]; // Get ->party members. int party_cnt = gwin->get_party(&party[0], 1); for (int i = 0; i < party_cnt; i++) { Actor *act = party[i]; Game_object_vector keys; // Get keys. if (act->get_objects(keys, 641, qual, c_any_framenum)) { // intercept the click_on_item call made by the key-usecode gwin->get_usecode()->intercept_click_on_item(obj); keys[0]->activate(); return; } } Mouse::mouse->flash_shape(Mouse::redx); // Nothing matched. } // { ActionStats, 1, "Show stats", true, false, NONE }, // params[0] = party member (0-7), or -1 for 'next' void ActionStats(int *params) { Game_window *gwin = Game_window::get_instance(); static int stats_page = -1; Actor *actor; if (params[0] == -1) { Gump_manager *gump_man = gwin->get_gump_man(); int party_count = gwin->get_party_man()->get_count(); int shapenum = game->get_shape("gumps/statsdisplay"); for(int i=0;i<=party_count;++i) { actor = Get_party_member(i); if (!actor) continue; // Check if this actor's stats page is open or not if (!gump_man->find_gump(actor, shapenum)) { gump_man->add_gump(actor, shapenum); //force showing stats. stats_page = i; return; } } stats_page = (stats_page+1)%(party_count+1); } else { stats_page = params[0]; if (stats_page < 0 || stats_page >= gwin->get_party_man()->get_count()) stats_page = 0; } actor = Get_party_member(stats_page); if (actor) gwin->get_gump_man()->add_gump(actor, game->get_shape("gumps/statsdisplay")); Mouse::mouse->set_speed_cursor(); } // { ActionCombatStats, 0, "Show Combat stats", true, false, SERPENT_ISLE } void ActionCombatStats(int* params) { Game_window *gwin = Game_window::get_instance(); int cnt = gwin->get_party_man()->get_count(); gwin->get_gump_man()->add_gump(gwin->get_main_actor(), game->get_shape("gumps/cstats/1") + cnt); } // { ActionFaceStats, 0, "Change Face Stats State", true, false, NONE } void ActionFaceStats(int* params) { Face_stats::AdvanceState(); Face_stats::save_config(config); } // { ActionSIIntro, 0, "Show SI intro", true, true, SERPENT_ISLE }, void ActionSIIntro(int *params) { Game_window *gwin = Game_window::get_instance(); game->set_jive(); game->play_intro(); game->clear_jive(); gwin->clear_screen(true); gwin->get_pal()->set(0); gwin->paint(); gwin->get_pal()->fade(50, 1, 0); } // { ActionEndgame, 1, "Show endgame", true, true, BLACK_GATE }, // params[0] = -1,0 = won, 1 = lost void ActionEndgame(int *params) { Game_window *gwin = Game_window::get_instance(); game->end_game(params[0] != 1); gwin->clear_screen(true); gwin->get_pal()->set(0); gwin->paint(); gwin->get_pal()->fade(50, 1, 0); } // { ActionScrollLeft, 0, "Scroll left", true, true, NONE }, void ActionScrollLeft(int *params) { Game_window *gwin = Game_window::get_instance(); for (int i = 16; i; i--) gwin->view_left(); } // { ActionScrollRight, 0, "Scroll right", true, true, NONE }, void ActionScrollRight(int *params) { Game_window *gwin = Game_window::get_instance(); for (int i = 16; i; i--) gwin->view_right(); } // { ActionScrollUp, 0, "Scroll up", true, true, NONE }, void ActionScrollUp(int *params) { Game_window *gwin = Game_window::get_instance(); for (int i = 16; i; i--) gwin->view_up(); } // { ActionScrollDown, 0, "Scroll down", true, true, NONE }, void ActionScrollDown(int *params) { Game_window *gwin = Game_window::get_instance(); for (int i = 16; i; i--) gwin->view_down(); } // { ActionWalkWest, 0, "Walk west", true, false, NONE }, void ActionWalkWest(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2-50, gwin->get_height()/2,speed); } // { ActionWalkEast, 0, "Walk east", true, false, NONE }, void ActionWalkEast(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2+50, gwin->get_height()/2, speed); } // { ActionWalkNorth, 0, "Walk north", true, false, NONE }, void ActionWalkNorth(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2, gwin->get_height()/2-50, speed); } // { ActionWalkSouth, 0, "Walk south", true, false, NONE }, void ActionWalkSouth(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2, gwin->get_height()/2+50, speed); } // { ActionWalkNorthEast, 0, "Walk north-east", true, false, NONE }, void ActionWalkNorthEast(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2+50, gwin->get_height()/2-50, speed); } // { ActionWalkSouthEast, 0, "Walk south-east", true, false, NONE }, void ActionWalkSouthEast(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2+50, gwin->get_height()/2+50, speed); } // { ActionWalkNorthWest, 0, "Walk north-west", true, false, NONE }, void ActionWalkNorthWest(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2-50, gwin->get_height()/2-50, speed); } // { ActionWalkSouthWest, 0, "Walk south-west", true, false, NONE }, void ActionWalkSouthWest(int *params) { Game_window *gwin = Game_window::get_instance(); int speed = params[0]<0?166:50; gwin->start_actor(gwin->get_width()/2-50, gwin->get_height()/2+50, speed); } // { ActionStopWalking, 0, "Stop Walking", true, true, NONE }, void ActionStopWalking(int *params) { Game_window *gwin = Game_window::get_instance(); gwin->stop_actor(); } // { ActionCenter, 0, "Center screen", true, true, NONE }, void ActionCenter(int *params) { Game_window *gwin = Game_window::get_instance(); gwin->center_view(gwin->get_camera_actor()->get_tile()); gwin->paint(); } // { ActionShapeBrowser, 0, "Shape browser", true, true, NONE }, void ActionShapeBrowser(int *params) { cheat.shape_browser(); } // { ActionCreateShape, 3, "Create last shape", true, true, NONE }, // params[0] = shape nr., or -1 for 'last selected shape in browser' // params[1] = frame nr. // params[2] = quantity // params[3] = quality void ActionCreateShape(int *params) { if (params[0] == -1) { cheat.create_last_shape(); } else { Game_window *gwin = Game_window::get_instance(); if (params[1] == -1) params[1] = 0; if (params[2] == -1) params[2] = 1; if (params[3] == -1) params[3] = c_any_qual; gwin->get_main_actor()->add_quantity(params[2], params[0], params[3], params[1]); gwin->get_effects()->center_text("Object created"); } } // { ActionDeleteObject, 0, "Delete object", true, true, NONE }, void ActionDeleteObject(int *params) { cheat.delete_object(); } // { ActionDeleteSelected, "Delete selected", true, ture, NONE, false }, void ActionDeleteSelected(int *params) { cheat.delete_selected(); } // { ActionMoveSelected, 3, "Move selected", true, true, NONE }, // params[0] = deltax (tiles) // params[1] = deltay // params[2] = deltaz void ActionMoveSelected(int *params) { cheat.move_selected(params[0], params[1], params[2]); } // { ActionToggleEggs, 0, "Toggle egg display", true, true, NONE }, void ActionToggleEggs(int *params) { cheat.toggle_eggs(); } // { ActionGodMode, 1, "Toggle god mode", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionGodMode(int *params) { if (params[0] == -1) cheat.toggle_god(); else cheat.set_god(params[0] != 0); } // { ActionGender, 0, "Change gender", true, true, NONE }, void ActionGender(int *params) { cheat.change_gender(); } // { ActionCheatHelp, 0, "List cheat keys", true, true, NONE }, void ActionCheatHelp(int *params) { keybinder->ShowCheatHelp(); } // { ActionInfravision, 1, "Toggle infravision", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionInfravision(int *params) { if (params[0] == -1) cheat.toggle_infravision(); else cheat.set_infravision(params[0] != 0); } // { ActionSkipLift, 1, "Change skiplift", true, true, NONE }, // params[0] = level, or -1 to decrease one void ActionSkipLift(int *params) { if (params[0] == -1) cheat.dec_skip_lift(); else cheat.set_skip_lift(params[0]); } // { ActionLevelup, 1, "Level-up party", true, true, NONE }, // params[0] = nr. of levels (or -1 for one) void ActionLevelup(int *params) { if (params[0] == -1) params[0] = 1; for (int i=0; i < params[0]; i++) cheat.levelup_party(); } // { ActionMapEditor, 1, "Toggle map-editor mode", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionMapEditor(int *params) { if (params[0] == -1) cheat.toggle_map_editor(); else cheat.set_map_editor(params[0] != 0); } // { ActionHackMover, "Toggle hack-mover mode", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionHackMover(int *params) { if (params[0] == -1) cheat.toggle_hack_mover(); else cheat.set_hack_mover(params[0] != 0); } // { ActionMapTeleport, 0, "Map teleport", true, true, NONE }, void ActionMapTeleport(int *params) { cheat.map_teleport(); } // { ActionTeleport, 0, "Teleport to cursor", true, true, NONE }, void ActionTeleport(int *params) { cheat.cursor_teleport(); } // { ActionTime, 0, "Next time period", true, true, NONE }, void ActionTime(int *params) { cheat.fake_time_period(); } // { ActionWizard, 1, "Toggle archwizard mode", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionWizard(int *params) { if (params[0] == -1) cheat.toggle_wizard(); else cheat.set_wizard(params[0] != 0); } // { ActionHeal, 0, "Heal party", true, true, NONE }, void ActionHeal(int *params) { cheat.heal_party(); } // { ActionCheatScreen, 0, "Cheat Screen", true, true, NONE }, void ActionCheatScreen(int *params) { cheat.cheat_screen(); } // { ActionPickPocket, 1, "Toggle Pickpocket", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionPickPocket(int *params) { if (params[0] == -1) cheat.toggle_pickpocket(); else cheat.set_pickpocket(params[0] != 0); } // { ActionPickPocket, 1, "Toggle Pickpocket", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionNPCNumbers(int *params) { if (params[0] == -1) cheat.toggle_number_npcs(); else cheat.set_number_npcs(params[0] != 0); } // { ActionGrabActor, 1, "Grab Actor for Cheatscreen", true, true, NONE }, // params[0] = -1 for toggle, 0 for off, 1 for on void ActionGrabActor(int *params) { if (params[0] == -1) cheat.toggle_grab_actor(); else cheat.set_grab_actor(params[0] != 0); } // { ActionCut, "Cut Selected Objects", true, false, NONE, true}, void ActionCut(int *params) { cheat.cut(false); } // { ActionCopy, "Copy Selected Objects", true, false, NONE, true}, void ActionCopy(int *params) { cheat.cut(true); } // { ActionPaste, "Paste Selected Objects", true, false, NONE, true}, void ActionPaste(int *params) { cheat.paste(); } // { ActionPlayMusic, 1, "Play song", false, true, NONE }, // params[0] = song nr., or -1 for next, -2 for previous void ActionPlayMusic(int *params) { static int mnum = 0; if (params[0] == -1) { Audio::get_ptr()->start_music(mnum++, 0); } else if (params[0] == -2) { if (mnum > 0) Audio::get_ptr()->start_music(--mnum, 0); } else { mnum = params[0]; Audio::get_ptr()->start_music(mnum, 0); } } // { ActionNaked, 0, "Toggle naked mode", true, true, SERPENT_ISLE }, void ActionNaked(int *params) { cheat.toggle_naked(); } // { ActionPetra, 0, "Toggle Petra mode", true, true, SERPENT_ISLE }, void ActionPetra(int *params) { cheat.toggle_Petra(); } // { ActionSkinColour, 0 "Change skin colour", true, true, NONE }, void ActionSkinColour(int *params) { cheat.change_skin(); } // { ActionSoundTester, 0, "Sound tester", false, true, NONE } void ActionSoundTester(int *params) { cheat.sound_tester(); } void ActionTest(int *params) { } exult-1.2/exulticon.h0000644000175000001440000001534410043526650010365 /* GIMP header image file format (INDEXED): /tmp/icon32x32.h */ static unsigned int width = 32; static unsigned int height = 32; /* Call this macro repeatedly. After each use, the pixel data can be extracted */ #define HEADER_PIXEL(data,pixel) {\ pixel[0] = header_data_cmap[(unsigned char)data[0]][0]; \ pixel[1] = header_data_cmap[(unsigned char)data[0]][1]; \ pixel[2] = header_data_cmap[(unsigned char)data[0]][2]; \ data ++; } static char header_data_cmap[256][3] = { { 0,128,128}, { 34, 34, 34}, { 0, 0, 0}, {119,119,119}, {160,160,164}, {134,134,134}, { 66, 66, 66}, {102,102,102}, {204,204,204}, {192,192,192}, {150,150,150}, {215,215,215}, { 95, 95, 95}, {178,178,178}, { 57, 57, 57}, { 28, 28, 28}, { 41, 41, 41}, { 85, 85, 85}, { 22, 22, 22}, {221,221,221}, { 51, 51, 51}, { 77, 77, 77}, {153,153,153}, {227,227,227}, {234,234,234}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255}, {255,255,255} }; static char header_data[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2, 2,2,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,2,2,1,3,4, 5,6,2,2,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,2,7,8,9,9, 9,8,10,2,2,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,6,11,9,5,12, 4,8,8,3,2,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,2,13,9,4,14,2, 15,13,9,4,15,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,14,9,9,7,2,0, 2,6,8,9,7,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,5,9,13,14,2,0, 2,2,4,9,4,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,5,9,9,16,0,0, 0,2,10,9,13,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,17,9,9,18,0,0, 0,2,13,9,4,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,14,8,13,16,0,0, 0,2,8,9,7,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,2,11,8,17,2,0, 2,18,19,9,20,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,5,8,5,2,0, 2,21,8,10,2,2,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,18,9,4,16,2, 2,9,9,14,2,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,2,2,2,2,2,2,17,8,9,18, 10,8,3,2,2,2,2,2,2,0,0,0,0,0,0,0, 0,0,0,0,0,0,2,10,4,4,22,4,4,13,8,9, 23,4,13,4,4,4,13,5,1,0,0,0,0,0,0,0, 0,0,0,0,0,0,2,15,8,19,8,4,10,22,13,19, 8,10,4,8,11,8,8,8,2,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,2,12,5,14,2,2,2,3,11, 8,2,2,2,16,12,5,2,2,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,2,2,2,2,2,0,2,7,23, 8,2,0,2,2,2,2,2,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,19, 8,2,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,2,3,23, 8,2,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,2,5,23, 11,18,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,2,10,19, 11,18,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,2,4,23, 11,1,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,2,11,19, 8,14,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,2,1,24,19, 11,17,2,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,2,3,19,19, 11,4,2,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,18,8,11,11, 11,11,6,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,1,4,11,8, 11,5,16,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,2,2,10,8, 5,18,2,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,2,18,9, 20,2,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,2,6, 2,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,2, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; exult-1.2/sigame.cc0000644000175000001440000010050510054030532007737 /* * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "SDL_events.h" #include "files/U7file.h" #include "files/utils.h" #include "flic/playfli.h" #include "gamewin.h" #include "Audio.h" #include "sigame.h" #include "palette.h" #include "databuf.h" #include "font.h" #include "txtscroll.h" #include "exult_types.h" #include "mappatch.h" #include "shapeid.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::rand; using std::strlen; using std::toupper; #endif SI_Game::SI_Game() { add_shape("gumps/check",2); add_shape("gumps/fileio",3); add_shape("gumps/fntext",4); add_shape("gumps/loadbtn",5); add_shape("gumps/savebtn",6); add_shape("gumps/halo",7); add_shape("gumps/disk",19); add_shape("gumps/heart",20); add_shape("gumps/statatts",23); add_shape("gumps/musicbtn",24); add_shape("gumps/speechbtn",25); add_shape("gumps/soundbtn",26); add_shape("gumps/spellbook",38); add_shape("gumps/combat",41); add_shape("gumps/statsdisplay",42); add_shape("gumps/quitbtn",50); add_shape("gumps/yesnobox",51); add_shape("gumps/yesbtn",52); add_shape("gumps/nobtn",53); add_shape("gumps/book",27); add_shape("gumps/scroll",49); add_shape("gumps/combat_stats",91); add_shape("gumps/combatmode",12); add_shape("gumps/slider",14); add_shape("gumps/slider_diamond",15); add_shape("gumps/slider_right",16); add_shape("gumps/slider_left",17); add_shape("gumps/box", 0); add_shape("gumps/crate", 1); add_shape("gumps/barrel", 8); add_shape("gumps/bag", 9); add_shape("gumps/backpack", 10); add_shape("gumps/basket", 11); add_shape("gumps/chest", 18); add_shape("gumps/shipshold", 21); add_shape("gumps/drawer", 22); add_shape("gumps/woodsign", 44); add_shape("gumps/tombstone", 45); add_shape("gumps/goldsign", 46); add_shape("gumps/body", 48); add_shape("gumps/tree", 64); add_shape("gumps/cstats/1",58); add_shape("gumps/cstats/2",59); add_shape("gumps/cstats/3",60); add_shape("gumps/cstats/4",61); add_shape("gumps/cstats/5",62); add_shape("gumps/cstats/6",63); add_shape("sprites/map", 22); add_shape("sprites/cheatmap", 0); // Need to be done add_shape("gumps/spell_scroll",65); add_shape("gumps/jawbone", 56); add_shape("gumps/tooth", 57); add_resource("files/shapes/count", 0, 8); add_resource("files/shapes/0", "/shapes.vga", 0); add_resource("files/shapes/1", "/faces.vga", 0); add_resource("files/shapes/2", "/gumps.vga", 0); add_resource("files/shapes/3", "/sprites.vga", 0); add_resource("files/shapes/4", MAINSHP_FLX, 0); add_resource("files/shapes/5", "/paperdol.vga", 0); add_resource("files/shapes/6", "/exult.flx", 0); add_resource("files/shapes/7", "/fonts.vga", 0); add_resource("files/gameflx", "/exult_si.flx", 0); add_resource("config/defaultkeys", "/exult_si.flx", 1); add_resource("palettes/count", 0, 14); add_resource("palettes/0", PALETTES_FLX, 0); add_resource("palettes/1", PALETTES_FLX, 1); add_resource("palettes/2", PALETTES_FLX, 2); add_resource("palettes/3", PALETTES_FLX, 3); add_resource("palettes/4", PALETTES_FLX, 4); add_resource("palettes/5", PALETTES_FLX, 5); add_resource("palettes/6", PALETTES_FLX, 6); add_resource("palettes/7", PALETTES_FLX, 7); add_resource("palettes/8", PALETTES_FLX, 8); add_resource("palettes/9", PALETTES_FLX, 9); add_resource("palettes/10", PALETTES_FLX, 10); add_resource("palettes/11", PALETTES_FLX, 11); add_resource("palettes/12", PALETTES_FLX, 12); add_resource("palettes/13", MAINSHP_FLX, 1); add_resource("palettes/14", MAINSHP_FLX, 26); fontManager.add_font("MENU_FONT", MAINSHP_FLX, 9, 1); fontManager.add_font("SIINTRO_FONT", "/intro.dat", 14, 0); Map_patch_collection *mp = gwin->get_map_patches(); // Egg by "PC pirate" in forest: mp->add(new Map_patch_remove(Object_spec( Tile_coord(647, 1899, 0), 275, 7, 1))); // Carpets above roof in Monitor: mp->add(new Map_patch_remove(Object_spec( Tile_coord(1035, 2572, 8), 483, 1, 0), true)); mp->add(new Map_patch_remove(Object_spec( Tile_coord(1034, 2571, 6), 483, 1, 0))); mp->add(new Map_patch_remove(Object_spec( Tile_coord(1034, 2571, 5), 483, 1, 0), true)); // Neyobi under a fur: mp->add(new Map_patch_modify(Object_spec( Tile_coord(1012, 873, 0), 867, 13, 0), Object_spec( Tile_coord(1013, 873, 1), 867, 13, 0))); } SI_Game::~SI_Game() { } // Little weighted random function for lightning on the castle static int get_frame (void) { int num = rand() % 9; if (num >= 8) return 2; else if (num >= 6) return 1; return 0; } void SI_Game::play_intro() { int next = 0; size_t flisize; char *fli_b = 0; uint8 *buffer = 0; size_t size; size_t shapesize; char * shape_buf = 0; int i,j; Font *font = fontManager.get_font("MENU_FONT"); Font *sifont = fontManager.get_font("SIINTRO_FONT"); bool speech = Audio::get_ptr()->is_speech_enabled(); gwin->clear_screen(true); Audio::get_ptr()->stop_music(); // Lord British presents... try { U7object lbflic("/intro.dat", 0); fli_b = lbflic.retrieve(flisize); playfli fli0(fli_b+8, flisize-8); fli0.info(); const char *txt_msg[] = { "with help from", "The Exult Team", "Driven by Exult" }; for (j = 0; j < 20; j++) { next = fli0.play(win, 0, 0, next, j*5); font->center_text(ibuf, centerx, centery+50, txt_msg[0]); font->center_text(ibuf, centerx, centery+65, txt_msg[1]); win->show(); } next = fli0.play(win, 0, 0, next, 100); font->center_text(ibuf, centerx, centery+50, txt_msg[0]); font->center_text(ibuf, centerx, centery+65, txt_msg[1]); win->show(); if (wait_delay (3000)) throw UserBreakException(); for (j = 20; j; j--) { next = fli0.play(win, 0, 0, next, j*5); font->center_text(ibuf, centerx, centery+50, txt_msg[0]); font->center_text(ibuf, centerx, centery+65, txt_msg[1]); win->show(); } FORGET_ARRAY(fli_b); if (wait_delay (0)) throw UserBreakException(); gwin->clear_screen(true); // Castle Outside // Start Music Audio *audio = Audio::get_ptr(); if (audio) { const char *fn = "/r_sintro.xmi"; MyMidiPlayer *midi = audio->get_midi(); if (midi && midi->is_fm_synth()) fn = "/a_sintro.xmi"; audio->start_music (fn, 0, false); } // Thunder, note we use the buffer again later so it's not freed here if (speech) { U7object voc_thunder("/intro.dat", 15); buffer = (uint8 *) voc_thunder.retrieve(size); Audio::get_ptr()->play (buffer+8, size-8, false); } U7object flic("/intro.dat", 1); fli_b = flic.retrieve(flisize); playfli fli1(fli_b+8, flisize-8); fli1.info(); fli1.play(win, 0, 1, 0, 0); next = SDL_GetTicks(); int prev = -1; int num; for (j = 0; j < 20; j++) { num = get_frame(); if (prev != num) for (i = 0; i < num+1; i++) fli1.play(win, i, i, next); prev = num; next += 75; win->show(); if (wait_delay (1)) throw UserBreakException(); } const char *lb_cas = "Lord British's Castle"; const char *db_cas = "Dick British's Castle"; for (j = 0; j < 50; j++) { num = get_frame(); if (prev != num) for (i = 0; i < num+1; i++) fli1.play(win, i, i, next); if (jive) sifont->center_text(ibuf, centerx, centery+50, db_cas); else sifont->center_text(ibuf, centerx, centery+50, lb_cas); prev = num; next += 75; win->show(); if (wait_delay (1)) throw UserBreakException(); } for (j = 0; j < 10; j++) { num = get_frame(); if (prev != num) for (i = 0; i < num+1; i++) fli1.play(win, i, i, next); // Thunder again, we free the buffer here if (speech && j == 5) { Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } prev = num; next += 75; win->show(); if (wait_delay (1)) throw UserBreakException(); } const char *bg_fellow[] = { "Eighteen months after the destruction", "of the Black Gate and the", "dismantling of The Fellowship"}; for (j = 0; j < 75; j++) { num = get_frame(); if (prev != num) for (i = 0; i < num+1; i++) fli1.play(win, i, i, next); for(i=0; i<3; i++) { sifont->center_text(ibuf, centerx, centery+50+15*i, bg_fellow[i]); } prev = num; next += 75; win->show(); if (wait_delay (1)) throw UserBreakException(); } for (j = 20; j; j--) { next = fli1.play(win, 0, 0, next, j*5); win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(fli_b); if (wait_delay (0)) throw UserBreakException(); // Do this! Prevents palette corruption gwin->clear_screen(true); // Guard walks in U7object flic2("/intro.dat", 2); fli_b = flic2.retrieve(flisize); playfli fli2(fli_b+8, flisize-8); fli2.info(); for (j = 0; j < 20; j++) { next = fli2.play(win, 0, 0, next, j*5); win->show(); if (wait_delay (0)) throw UserBreakException(); } // Guard walks in for (j = 0; j < 37; j++) { next = fli2.play(win, j, j, next); win->show(); if (wait_delay (0)) throw UserBreakException(); } // Guard walks in const char *my_leige = "My leige"; const char *yo_homes = "Yo, homes"; if (speech && !jive) { U7object voc_my_leige("/intro.dat", 16); buffer = (uint8 *) voc_my_leige.retrieve (size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } for (; j < 55; j++) { next = fli2.play(win, j, j, next); if (jive) sifont->draw_text(ibuf, centerx+30, centery+87, yo_homes); else if (!speech) sifont->draw_text(ibuf, centerx+30, centery+87, my_leige); win->show(); if (wait_delay (0)) throw UserBreakException(); } next = fli2.play(win, j, j, next); win->show(); const char *all_we[2] = { "All we found among Batlin's", "belongings was this enchanted scroll.." }; if (speech && !jive) { U7object voc_all_we("/intro.dat", 17); buffer = (uint8 *) voc_all_we.retrieve (size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } for (; j < 73; j++) { next = fli2.play(win, j, j, next); if (!speech || jive) { sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(all_we[0]), centery+74, all_we[0]); sifont->draw_text(ibuf, centerx+160-sifont->get_text_width(all_we[1]), centery+87, all_we[1]); } win->show(); if (wait_delay (0)) throw UserBreakException(); } for (i = 0; i < 220; i++) if (wait_delay (10)) throw UserBreakException(); const char *and_a[2] = { "and a map showing the way to", "a place called the Serpent Isle" }; next = fli2.play(win, j, j, next); if (!speech || jive) { sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(and_a[0]), centery+74, and_a[0]); sifont->draw_text(ibuf, centerx+150-sifont->get_text_width(and_a[1]), centery+87, and_a[1]); } win->show(); j++; for (i = 0; i < 290; i++) if (wait_delay (10)) throw UserBreakException(); fli2.play(win, j, j); j++; for (i = 0; i < 50; i++) if (wait_delay (10)) throw UserBreakException(); const char *indeed[2] = { "Indeed.", "Put it on the table." }; const char *iree = "Iree. Slap it down there!"; if (speech && !jive) { U7object voc_indeed("/intro.dat", 18); buffer = (uint8 *) voc_indeed.retrieve(size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } next = fli2.play(win, j, j); j++; for (; j < 81; j++) { next = fli2.play(win, j, j, next); if (jive) sifont->draw_text(ibuf, topx+40, centery+74, iree); else if (!speech) { sifont->draw_text(ibuf, topx+40, centery+74, indeed[0]); sifont->draw_text(ibuf, topx+40, centery+87, indeed[1]); } win->show(); if (wait_delay (0)) throw UserBreakException(); } for (i = 0; i < 200; i++) if (wait_delay (10)) throw UserBreakException(); FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Scroll opens U7object flic3("/intro.dat", 3); fli_b = flic3.retrieve(flisize); playfli fli3(fli_b+8, flisize-8); fli3.info(); next = 0; // Scroll opens for (j = 0; j < 20; j++) { next = fli3.play(win, j, j, next)+20; win->show(); if (wait_delay (0)) throw UserBreakException(); } // 'Stand Back' const char *stand_back = "Stand Back!"; const char *jump_back = "Jump Back!"; if (speech && !jive) { U7object voc_stand_back("/intro.dat", 19); buffer = (uint8 *) voc_stand_back.retrieve(size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } for (; j < 61; j++) { next = fli3.play(win, j, j, next)+20; if (jive) sifont->draw_text(ibuf, topx+70, centery+60, jump_back); else if (!speech) sifont->draw_text(ibuf, topx+70, centery+60, stand_back); win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Big G speaks U7object flic4("/intro.dat", 4); fli_b = flic4.retrieve(flisize); playfli fli4(fli_b+8, flisize-8); fli4.info(); U7object shapes("/intro.dat", 30); shape_buf = shapes.retrieve(shapesize); BufferDataSource gshape_ds(shape_buf+8, shapesize-8); Shape_frame *sf; Shape_file gshape(&gshape_ds); cout << "Shape in intro.dat has " << gshape.get_num_frames() << endl; if (speech && !jive) { U7object voc_big_g("/intro.dat", 20); buffer = (uint8 *) voc_big_g.retrieve ( size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } next = 0; // Batlin... const char *batlin[2] = { "Batlin! In the event that the", "Avatar destroys the Black Gate" }; const char *you_shall[2] = { "you shall follow the unwitting", "human Gwenno to the Serpent Isle" }; const char *there_i[2] = { "There I shall outline my plan", "to destroy Britannia!" }; const char *batlin2[2] = { "Batlin! Know that my face is most", "muppet like!" }; const char *you_must[2] = { "You must go to the Serpent Isle", "to learn the secret of Acne Medication" }; const char *soon_i[2] = { "Soon I and my horde of muppets will", "destroy Britannia!" }; for (j = 0; j < 320; j++) { next = fli4.play(win, j%40, j%40, next); if (j < 300) sf = gshape.get_frame((j/2)%7); else sf = gshape.get_frame(0); if (sf) sman->paint_shape (centerx-36, centery, sf); if (j < 100 && jive) { sifont->center_text(ibuf, centerx, centery+74, batlin2[0]); sifont->center_text(ibuf, centerx, centery+87, batlin2[1]); } else if (j < 200 && jive) { sifont->center_text(ibuf, centerx, centery+74, you_must[0]); sifont->center_text(ibuf, centerx, centery+87, you_must[1]); } else if (j < 300 && jive) { sifont->center_text(ibuf, centerx, centery+74, soon_i[0]); sifont->center_text(ibuf, centerx, centery+87, soon_i[1]); } else if (j < 100 && !speech) { sifont->center_text(ibuf, centerx, centery+74, batlin[0]); sifont->center_text(ibuf, centerx, centery+87, batlin[1]); } else if (j < 200 && !speech) { sifont->center_text(ibuf, centerx, centery+74, you_shall[0]); sifont->center_text(ibuf, centerx, centery+87, you_shall[1]); } else if (j < 300 && !speech) { sifont->center_text(ibuf, centerx, centery+74, there_i[0]); sifont->center_text(ibuf, centerx, centery+87, there_i[1]); } win->show(); if (wait_delay (0)) throw UserBreakException(); } sf = gshape.get_frame(0); for (j = 20; j; j--) { next = fli4.play(win, 0, 0, next, j*5); if (sf) sman->paint_shape (centerx-36, centery, sf); win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(shape_buf); FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Tis LBs's Worst fear U7object flic5("/intro.dat", 5); fli_b = flic5.retrieve(flisize); playfli fli5(fli_b+8, flisize-8); fli5.info(); for (j=0; j < 20; j++) { next = fli5.play(win, 0, 0, next, j*5); win->show(); if (wait_delay (0)) throw UserBreakException(); } const char *tis_my[3] = {"'Tis my worst fear!", "I must send the Avatar through", "the pillars to the Serpent Isle!" }; if (speech && !jive) { U7object voc_tis_my("/intro.dat", 21); buffer = (uint8 *) voc_tis_my.retrieve(size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); } for (j=0; j < 61; j++) { next = fli5.play(win, j, j, next)+30; if (j < 20 && (!speech || jive)) { sifont->center_text(ibuf, centerx, centery+74, tis_my[0]); } else if (j > 22 && (!speech || jive)) { sifont->center_text(ibuf, centerx, centery+74, tis_my[1]); sifont->center_text(ibuf, centerx, centery+87, tis_my[2]); } win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Boat 1 U7object flic6("/intro.dat", 6); fli_b = flic6.retrieve(flisize); playfli fli6(fli_b+8, flisize-8); fli6.info(); for (j=0; j < 61; j++) { next = fli6.play(win, j, j, next)+30; win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Boat 2 U7object flic7("/intro.dat", 7); fli_b = flic7.retrieve(flisize); playfli fli7(fli_b+8, flisize-8); fli7.info(); const char *zot = "Zot!"; for (j=0; j < 61; j++) { next = fli7.play(win, j, j, next)+30; if (j > 55 && jive) sifont->center_text(ibuf, centerx, centery+74, zot); win->show(); if (wait_delay (0)) throw UserBreakException(); } FORGET_ARRAY(fli_b); // Do this! Prevents palette corruption gwin->clear_screen(true); // Ultima VII Part 2 U7object flic8("/intro.dat", 8); fli_b = flic8.retrieve(flisize); playfli fli8(fli_b+8, flisize-8); fli8.info(); for (j = 0; j < 20; j++) { next = fli8.play(win, 0, 0, next, j*5); font->center_text(ibuf, centerx, centery+75, txt_msg[2]); win->show(); } next = fli8.play(win, 0, 0, next, 100); font->center_text(ibuf, centerx, centery+75, txt_msg[2]); win->show(); for (i = 0; i < 300; i++) if (wait_delay (10)) throw UserBreakException(); for (j = 20; j; j--) { next = fli8.play(win, 0, 0, next, j*5); font->center_text(ibuf, centerx, centery+75, txt_msg[2]); win->show(); } FORGET_ARRAY(fli_b); } catch(const UserBreakException &x) { FORGET_ARRAY(shape_buf); FORGET_ARRAY(fli_b); FORGET_ARRAY(buffer); } // Fade out the palette... // pal.fade_out(c_fade_out_time); // this doesn't work right ATM since the FLIC player has its own palette handling // ... and clean the screen. gwin->clear_screen(true); // Stop all audio output Audio::get_ptr()->cancel_streams(); } void SI_Game::top_menu() { play_midi(28, true); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); pal->load(MAINSHP_FLX,26); pal->fade_in(60); } void SI_Game::show_journey_failed() { pal->fade_out(50); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); journey_failed_text(); } /* * ExCineLite */ // ExCineEvent struct ExCineEvent { uint32 time; // Time to start, In MS char *file; int index; virtual bool play_it(Image_window *win, int time) = 0; // Return true if screen updated bool can_play() { return file != 0; } ExCineEvent(uint32 t, char*f, int i) : time(t), file(f), index(i) { } virtual ~ExCineEvent() { } }; // // ExCineFlic // struct ExCineFlic : public ExCineEvent { private: int start; // First frame to play int count; // Number of frames bool repeat; // Repeat? int cur; // Frame currently being displayed (note, it's not the actual frame) int speed; // Speed of playback (ms per frame) // Data info U7object *flic_obj; size_t size; char *buffer; playfli *player; public: virtual bool play_it(Image_window *win, int t); void load_flic(void); void free_flic(void); void fade_out(int cycles); ExCineFlic(uint32 time, char *file, int i, int s, int c, bool r, int spd) : ExCineEvent(time, file, i), start(s), count(c), repeat(r), cur(-1), speed(spd), flic_obj(0), size(0), buffer(0), player(0) { } ExCineFlic(uint32 time) : ExCineEvent(time, 0, 0), start(0), count(0), repeat(false), cur(0), speed(0), flic_obj(0), size(0), buffer(0), player(0) { } virtual ~ExCineFlic() { free_flic(); } }; void ExCineFlic::load_flic() { free_flic(); if (file) COUT("Loading " << file << ":" << index); flic_obj = new U7object(file, index); buffer = flic_obj->retrieve(size); player = new playfli(buffer+8, size-8); player->info(); } void ExCineFlic::free_flic() { if (file) COUT("Freeing " << file << ":" << index); FORGET_OBJECT(player); FORGET_ARRAY(buffer); size = 0; FORGET_OBJECT(flic_obj); } bool ExCineFlic::play_it(Image_window *win, int t) { if (t < time) return false; if (cur+1 < count || repeat) { // Only advance frame if we can int time_next = time + (cur+1) * speed; if (time_next <= t) { cur++; // The actual frame number int actual = start + (cur%count); player->play(win, actual, actual, 0); return true; } } player->put_buffer(win); return false; } void ExCineFlic::fade_out(int cycles) { if (player) player->get_palette()->fade_out(cycles); } // // ExCineVoc // struct ExCineVoc : public ExCineEvent { private: bool played; public: virtual bool play_it(Image_window *win, int t); ExCineVoc(uint32 time, char *f, int index) : ExCineEvent(time, file, index), played(false) { } virtual ~ExCineVoc() { } }; bool ExCineVoc::play_it(Image_window *win, int t) { size_t size; U7object voc("/intro.dat", index); uint8 *buffer = (uint8 *) voc.retrieve (size); Audio::get_ptr()->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); played = true; return false; } // // Serpent Isle Endgame // void SI_Game::end_game(bool success) { int next = 0; Font *font = fontManager.get_font("MENU_FONT"); Font *sifont = fontManager.get_font("SIINTRO_FONT"); bool speech = Audio::get_ptr()->is_speech_enabled(); gwin->clear_screen(true); /* Endgame General Timings (in ms) 0 - Avatar floating right 6350 - Begin Serpent Swirling 10850 - Serpent Comes on screen 14643 - Balanced, and "there we are done" 17281 - "balance is restored" 21300 - "serpent isle" 22900 - "briatnnia" 24300 - "your earth" 26000 - "the entire universe" 28600 - "all are phased" 31600 - Avatar floating right, "worry not about your friend dupre" 35100 - "he is one with us" 37000 - "and content" 39800 - "good bye avatar" 42040 - "we thank you" 48550 - "well well well avatar" 48900 - Avatar floating left 51750 - "You have managed to thawt me one again" 55500 - "by restoring balance..." 62500 - floating far, "but now here you are" 64500 - "poised at the edge of eternity" 67000 - "where would you go?" 70250 - floating left, "back to britannia?" 72159 - "to earth?" 74750 - "perhaps you would join me.." 75500 - big g's hand 78000 - "we do have a score to settle" Flic Index 9 = Avfloat 10 = snake1 11 = snake2 12 = avfar 13 = xavgrab Frame count : 61 Width : 320 Height : 200 Depth : 8 Speed : 5 Frame count : 156 Width : 320 Height : 200 Depth : 8 Speed : 8 Frame count : 4 Width : 320 Height : 200 Depth : 8 Speed : 10 Frame count : 61 Width : 320 Height : 200 Depth : 8 Speed : 5 Frame count : 121 Width : 320 Height : 200 Depth : 8 Speed : 5 Sound Index 22 = "there we are done, balance is restored" 23 = "serpent isle...." 24 = "goodbye avatar..." 25 = "well well well avatar..." 26 = "by restoring balance..." 27 = "but now here you are..." 28 = "back to britannia..." 29 = "perhaps you..." 0 - Repeat 9 6350 - Play 10 14643 - Repeat 10, Play 22 21300 - Play 23 31600 - Repeat 9 39800 - Repeat 11, Play 24 48550 - Play 25 48900 - Repeat 13 55500 - Play 26 62500 - Repeat 12, play 27 70250 - Play 13, play 28 72159 - "to earth?" 74750 - play 29 75500 - big g's hand 78000 - "we do have a score to settle" */ // Flic List ExCineFlic flics[] = { ExCineFlic(0, "/intro.dat", 9, 0, 61, true, 75), ExCineFlic(6350, "/intro.dat", 10, 0, 156, false, 95), ExCineFlic(21170, "/intro.dat", 9, 0, 61, true, 75), ExCineFlic(39800, "/intro.dat", 11, 0, 4, true, 75), ExCineFlic(48900, "/intro.dat", 13, 0, 61, true, 75), ExCineFlic(62500, "/intro.dat", 12, 0, 61, true, 75), ExCineFlic(70250, "/intro.dat", 13, 0, 121, false, 75), ExCineFlic(82300) }; int last_flic = 7; int cur_flic = -1; ExCineFlic *flic = 0; ExCineFlic *pal_flic = 0; // Voc List ExCineVoc vocs[] = { ExCineVoc(14700, "/intro.dat", 22), ExCineVoc(21300, "/intro.dat", 23), ExCineVoc(39800, "/intro.dat", 24), ExCineVoc(47700, "/intro.dat", 25), ExCineVoc(55400, "/intro.dat", 26), ExCineVoc(62500, "/intro.dat", 27), ExCineVoc(70250, "/intro.dat", 28), ExCineVoc(74750, "/intro.dat", 29) }; int last_voc = 7; int cur_voc = -1; // Stop previous music Audio::get_ptr()->stop_music(); // Start the music Audio *audio = Audio::get_ptr(); if (audio) { const char *fn = "/r_send.xmi"; MyMidiPlayer *midi = audio->get_midi(); if (midi && midi->is_fm_synth()) fn = "/a_send.xmi"; audio->start_music (fn, 0, false); } int start_time = SDL_GetTicks(); while (1) { int time = SDL_GetTicks() - start_time; // Need to go to the next flic? if (cur_flic < last_flic && flics[cur_flic+1].time <= time) { bool next_play = flics[cur_flic+1].can_play(); // Can play the new one, don't need the old one anymore if(next_play) { // Free it if (flic) flic->free_flic(); // Free the palette too, if we need to if (pal_flic && pal_flic != flic) pal_flic->free_flic(); pal_flic = 0; } // Set palette to prev if required else if (flic && flic->can_play()) { pal_flic = flic; } // Previous flic didn't have a palette, so free it anyway else if (flic) { flic->free_flic(); } cur_flic++; flic = flics+cur_flic; if (next_play) { // Clear the screen to prevent palette corruption gwin->clear_screen(true); // Load the flic, and set pal_flic (pal_flic = flic)->load_flic(); } else COUT("Teminator "); COUT("Flic at time: " << flic->time); } // Need to go to the next voc? if (cur_voc < last_voc && vocs[cur_voc+1].time <= time) { cur_voc++; ExCineVoc *voc = vocs+cur_voc; // Just play it! voc->play_it(NULL, time); //else COUT("Teminator "); COUT("voc at time: " << voc->time); } // We've finished if (cur_flic == last_flic && cur_voc == last_voc) { // Do a fade out if (pal_flic && pal_flic->can_play()) pal_flic->fade_out(100); COUT("Finished!" << std::endl); break; } // Play the flic if possible bool updated = false; if (flic->can_play()) updated = flic->play_it(win, time); if (updated) win->show(); if (wait_delay (0)) { // Do a quick fade out if (pal_flic && pal_flic->can_play()) pal_flic->fade_out(20); break; } } gwin->clear_screen(true); // Stop all sounds Audio::get_ptr()->cancel_streams(); // Stop music Audio::get_ptr()->stop_music(); } void SI_Game::show_quotes() { play_midi(32); TextScroller quotes(MAINSHP_FLX, 0x10, fontManager.get_font("MENU_FONT"), menushapes.extract_shape(0x14) ); quotes.run(gwin); } void SI_Game::show_credits() { play_midi(30); TextScroller credits(MAINSHP_FLX, 0x0E, fontManager.get_font("MENU_FONT"), menushapes.extract_shape(0x14) ); if(credits.run(gwin)) { // Watched through the entire sequence? std::ofstream quotesflg; U7open(quotesflg, "/quotes.flg"); quotesflg.close(); } } bool SI_Game::new_game(Vga_file &shapes) { SDL_EnableUNICODE(1); int menuy = topy+110; Font *font = fontManager.get_font("MENU_FONT"); Vga_file faces_vga(FACES_VGA); const int max_len = 16; char npc_name[max_len+1]; char disp_name[max_len+2]; npc_name[0] = 0; int sex = 0; int selected = 0; int num_choices = 4; //pal.load("/intropal.dat",6); SDL_Event event; bool editing = true; bool redraw = true; bool ok = true; do { if (redraw) { gwin->clear_screen(); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); sman->paint_shape(topx+10,menuy+10,shapes.get_shape(0xC, selected==0?1:0)); sman->paint_shape(topx+10,menuy+25,shapes.get_shape(0x19, selected==1?1:0)); Shape_frame *sh = faces_vga.get_shape(0,sex); sman->paint_shape(topx+300,menuy+50,sh); sman->paint_shape(topx+10,topy+180,shapes.get_shape(0x8,selected==2?1:0)); sman->paint_shape(centerx+10,topy+180,shapes.get_shape(0x7,selected==3?1:0)); if(selected==0) snprintf(disp_name, max_len+2, "%s_", npc_name); else snprintf(disp_name, max_len+2, "%s", npc_name); font->draw_text(ibuf, topx+60, menuy+10, disp_name); pal->apply(); redraw = false; } SDL_WaitEvent(&event); if(event.type==SDL_KEYDOWN) { redraw = true; switch(event.key.keysym.sym) { case SDLK_SPACE: if(selected==0) { int len = strlen(npc_name); if(len5) sex = 0; } break; case SDLK_LEFT: if(selected==1) { --sex; if(sex<0) sex = 5; } break; case SDLK_RIGHT: if(selected==1) { ++sex; if(sex>5) sex = 0; } break; case SDLK_ESCAPE: editing = false; ok = false; break; case SDLK_DOWN: ++selected; if(selected==num_choices) selected = 0; break; case SDLK_UP: --selected; if(selected<0) selected = num_choices-1; break; case SDLK_RETURN: if(selected<2) ++selected; else if(selected==2) { editing=false; ok = true; } else { editing = false; ok = false; } break; case SDLK_BACKSPACE: if(selected==0) { if(strlen(npc_name)>0) npc_name[strlen(npc_name)-1] = 0; } break; default: { if (selected == 0) // on the text input field? { int len = strlen(npc_name); char chr = 0; if ((event.key.keysym.unicode & 0xFF80) == 0) chr = event.key.keysym.unicode & 0x7F; if (chr >= ' ' && len < max_len) { npc_name[len] = chr; npc_name[len+1] = 0; } } else { redraw = false; } } break; } } } while(editing); gwin->clear_screen(); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); if(ok) { set_avname (npc_name); set_avsex (1-(sex%2)); set_avskin (sex/2); pal->fade_out(c_fade_out_time); gwin->clear_screen(true); ok = gwin->init_gamedat(true); } SDL_EnableUNICODE(0); return ok; } bool SI_Game::is_installed() { std::string buf("/sispeech.spc"); bool foundsi = U7exists(buf); bool foundsiflx = U7exists("/exult_si.flx"); if (foundsi) std::cout << "Serpent Isle : found" << std::endl; else std::cout << "Serpent Isle : not found (" << get_system_path(buf) << ")" << std::endl; if (foundsiflx) std::cout << "exult_si.flx : found" << std::endl; else std::cout << "exult_si.flx : not found (" << get_system_path("/exult_si.flx") << ")" << std::endl; return (foundsi && foundsiflx); } exult-1.2/npctime.h0000644000175000001440000000363107724430450010012 /* * Npctime.h - Timed-even handlers for NPC's. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NPCTIME_H #define NPCTIME_H 1 #include "tqueue.h" class Game_window; class Actor; class Npc_hunger_timer; class Npc_poison_timer; class Npc_sleep_timer; class Npc_invisibility_timer; class Npc_protection_timer; class Npc_flag_timer; /* * List of references to timers for an NPC. */ class Npc_timer_list { Actor *npc; Npc_hunger_timer *hunger; Npc_poison_timer *poison; Npc_sleep_timer *sleep; Npc_invisibility_timer *invisibility; Npc_protection_timer *protection; Npc_flag_timer *might, *curse, *paralyze; public: friend class Npc_hunger_timer; friend class Npc_poison_timer; friend class Npc_sleep_timer; friend class Npc_invisibility_timer; friend class Npc_protection_timer; friend class Npc_flag_timer; Npc_timer_list(Actor *n) : npc(n), hunger(0), poison(0), sleep(0), invisibility(0), protection(0), might(0), curse(0), paralyze(0) { } ~Npc_timer_list(); void start_hunger(); void start_poison(); void start_sleep(); void start_invisibility(); void start_protection(); void start_might(); void start_curse(); void start_paralyze(); }; #endif /* INCL_NPCTIME */ exult-1.2/party.h0000644000175000001440000000445507724430450007517 /** ** Party.h - Manage the party. ** ** Written: 4/8/02 - JSF **/ /* Copyright (C) 2000-2003 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCL_PARTY_H #define INCL_PARTY_H 1 #include "singles.h" #include "tiles.h" class Actor; #define EXULT_PARTY_MAX 8 /* * Manage the party. */ class Party_manager : public Game_singletons { int party[EXULT_PARTY_MAX]; // NPC #'s of party members. int party_count; // # of NPC's in party. int dead_party[16]; // NPC #'s of dead party members. int dead_party_count; Actor *valid[EXULT_PARTY_MAX]; // NPC's able to walk with Avatar. int validcnt; // Formation-walking: void move_followers(Actor *npc, int vindex, int dir); int step(Actor *npc, Actor *leader, int dir, Tile_coord dest); public: Party_manager(); void set_count(int n) // For initializing from file. { party_count = n; } void set_member(int i, int npcnum) { party[i] = npcnum; } int get_count() // Get # party members. { return party_count; } int get_member(int i) // Get npc# of i'th party member. { return party[i]; } int get_dead_count() // Same for dead party members. { return dead_party_count; } int get_dead_member(int i) { return dead_party[i]; } // Add/remove party member. bool add_to_party(Actor *npc); bool remove_from_party(Actor *npc); int in_dead_party(Actor *npc); bool add_to_dead_party(Actor *npc); bool remove_from_dead_party(Actor *npc); // Update status of NPC that died or // was resurrected. void update_party_status(Actor *npc); void link_party(); // Set party's id's. // Formation-walking: void get_followers(int dir); }; #endif exult-1.2/paths.h0000644000175000001440000001061007724430450007465 /* * Paths.h - Various pathfinding clients. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PATHS_H #define PATHS_H 1 #include "PathFinder.h" #include "tiles.h" #include "rect.h" #include "chunks.h" class Actor; class Game_object; class Game_window; /* * This class provides A* cost methods. */ class Actor_pathfinder_client : public Pathfinder_client { int dist; // Distance for success. Actor *npc; // Who this represents. public: // Actor_pathfinder_client(Actor *npc, int d = 0) : dist(d) // { set_move_flags(mf); } Actor_pathfinder_client(Actor *npc, int d = 0); // Figure when to give up. virtual int get_max_cost(int cost_to_goal); // Figure cost for a single step. virtual int get_step_cost(Tile_coord from, Tile_coord& to); // Estimate cost between two points. virtual int estimate_cost(Tile_coord& from, Tile_coord& to); // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); }; /* * This client succeeds when the path makes it to just one X/Y coord. * It assumes that a -1 was placed in the coord. that we should ignore. */ class Onecoord_pathfinder_client : public Actor_pathfinder_client { public: Onecoord_pathfinder_client(Actor *n) : Actor_pathfinder_client(n) { } // Estimate cost between two points. virtual int estimate_cost(Tile_coord& from, Tile_coord& to); // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); }; /* * This client succeeds when the path makes it offscreen. * Only the tz coord. of the dest. is used. */ class Offscreen_pathfinder_client : public Actor_pathfinder_client { Rectangle screen; // Screen rect. in tiles. Tile_coord best; // Best offscreen pt. to aim for. public: Offscreen_pathfinder_client(Actor *n); Offscreen_pathfinder_client(Actor *n, Tile_coord b); // Figure cost for a single step. virtual int get_step_cost(Tile_coord from, Tile_coord& to); // Estimate cost between two points. virtual int estimate_cost(Tile_coord& from, Tile_coord& to); // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); }; /* * This client is supposed to fail quickly, so that it can be used to * test for when an object can be grabbed. */ class Fast_pathfinder_client : public Pathfinder_client { int dist; // Succeeds at this distance from goal. public: Fast_pathfinder_client(int d = 0, int mf = 1 << 5) : dist(d) { set_move_flags(mf); } // Figure when to give up. virtual int get_max_cost(int cost_to_goal); // Figure cost for a single step. virtual int get_step_cost(Tile_coord from, Tile_coord& to); // Estimate cost between two points. virtual int estimate_cost(Tile_coord& from, Tile_coord& to); // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); static int is_grabable(Tile_coord from, Tile_coord to); // Check for unblocked straight path. static int is_straight_path(Tile_coord from, Tile_coord to); }; /* * Pathfinding for monsters, who may be bigger than 1x1: */ class Monster_pathfinder_client : public Fast_pathfinder_client { Rectangle destbox; // Got to intersect this box. int intelligence; // NPC's intelligence. int axtiles, aytiles, aztiles; // NPC's dims. in tiles. public: Monster_pathfinder_client(Actor *npc, Tile_coord dest, int dist); // For combat: Monster_pathfinder_client(Actor *attacker, int reach, Game_object *opponent); // Figure when to give up. virtual int get_max_cost(int cost_to_goal); // Is tile at the goal? virtual int at_goal(Tile_coord& tile, Tile_coord& goal); // Figure cost for a single step. virtual int get_step_cost(Tile_coord from, Tile_coord& to); }; #endif /* INCL_PATHS */ exult-1.2/gamemap.cc0000644000175000001440000012063510054030531010106 /** ** Gamemap.cc - X-windows Ultima7 map browser. **/ /* * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include # include # include #endif #include "gamemap.h" #include "objs.h" #include "chunks.h" #include "mappatch.h" #include "fnames.h" #include "utils.h" #include "shapeinf.h" #include "objiter.h" #include "Flex.h" #include "exceptions.h" #include "animate.h" #include "barge.h" #include "spellbook.h" #include "virstone.h" #include "egg.h" #include "jawbone.h" #include "actors.h" /* For Dead_body, which should be moved. */ #include "ucsched.h" #include "gamewin.h" /* With some work, could get rid of this. */ #include "bodies.h" #include "game.h" #include "effects.h" #include "objiter.cc" /* Yes we #include the .cc here on purpose! Please don't "fix" this */ #include "databuf.h" #include #ifndef UNDER_CE using std::cerr; using std::cout; using std::endl; using std::istream; using std::ifstream; using std::ios; using std::memcpy; using std::memset; using std::ofstream; using std::rand; using std::strcmp; using std::strcpy; using std::string; using std::strlen; using std::srand; using std::vector; #endif /* * Create a chunk. */ Map_chunk *Game_map::create_chunk ( int cx, int cy ) { return (objects[cx][cy] = new Map_chunk(cx, cy)); } /* * Read in a terrain chunk. */ Chunk_terrain *Game_map::read_terrain ( int chunk_num // Want this one from u7chunks. ) { assert(chunk_num >= 0 && chunk_num < chunk_terrains.size()); unsigned char buf[16*16*2]; chunks->seekg(chunk_num * 512); chunks->read(reinterpret_cast(buf), sizeof(buf)); Chunk_terrain *ter = new Chunk_terrain(&buf[0]); chunk_terrains.put(chunk_num, ter); return ter; } /* * Create game window. */ Game_map::Game_map ( ) : chunk_terrains(0), read_all_terrain(false), map_modified(false), map_patches(new Map_patch_collection), chunks(0) { } /* * Deleting map. */ Game_map::~Game_map ( ) { clear(); // Delete all objects, chunks. delete chunks; delete map_patches; } /* * Initialize for new/restored game. */ void Game_map::init ( ) { if (chunks) delete chunks; chunks = new ifstream; int num_chunk_terrains; bool patch_exists = is_system_path_defined(""); if (patch_exists && U7exists(PATCH_U7CHUNKS)) U7open(*chunks, PATCH_U7CHUNKS); else try { U7open(*chunks, U7CHUNKS); } catch(const file_exception & f) { if (!Game::is_editing() || // Ok if map-editing. !patch_exists) // But only if patch exists. throw f; ofstream ochunks; // Create one in 'patch'. U7open(ochunks, PATCH_U7CHUNKS); unsigned char buf[16*16*2]; memset(&buf[0], 0, sizeof(buf)); ochunks.write((char *) buf, sizeof(buf)); ochunks.close(); U7open(*chunks, PATCH_U7CHUNKS); } // Get to end so we can get length. chunks->seekg(0, ios::end); // 2 bytes/tile. num_chunk_terrains = chunks->tellg()/ (c_tiles_per_chunk*c_tiles_per_chunk*2); // Resize list to hold all. chunk_terrains.resize(num_chunk_terrains); read_all_terrain = map_modified = false; std::ifstream u7map; // Read in map. bool nomap = false; if (is_system_path_defined("") && U7exists(PATCH_U7MAP)) U7open(u7map, PATCH_U7MAP); else try { U7open(u7map, U7MAP); } catch(const file_exception & f) { if (!Game::is_editing()) // Ok if map-editing. throw f; nomap = true; } for (int schunk = 0; schunk < c_num_schunks*c_num_schunks; schunk++) { // Read in the chunk #'s. unsigned char buf[16*16*2]; if (nomap) memset(&buf[0], 0, sizeof(buf)); else u7map.read(reinterpret_cast(buf), sizeof(buf)); int scy = 16*(schunk/12);// Get abs. chunk coords. int scx = 16*(schunk%12); uint8 *mapdata = buf; // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) terrain_map[scx+cx][scy+cy] = Read2(mapdata); } u7map.close(); // Clear object lists, flags. // No casting _should_ be necessary at this point. // Who needs this? memset(reinterpret_cast(objects), 0, sizeof(objects)); memset(reinterpret_cast(schunk_read), 0, sizeof(schunk_read)); memset(reinterpret_cast(schunk_modified), 0, sizeof(schunk_modified)); memset(schunk_cache, 0, sizeof (schunk_cache)); memset(schunk_cache_sizes, -1, sizeof(schunk_cache_sizes)); } /* * Clear out world's contents. Should be used during a 'restore'. */ void Game_map::clear ( ) { // Delete all chunks (& their objs). for (int y = 0; y < c_num_chunks; y++) for (int x = 0; x < c_num_chunks; x++) { delete objects[x][y]; objects[x][y] = 0; } int cnt = chunk_terrains.size(); int i; for (i = 0; i < cnt; i++) delete chunk_terrains[i]; chunk_terrains.resize(0); delete chunks; // Close 'u7chunks'. chunks = 0; map_modified = false; // Clear 'read' flags. memset(reinterpret_cast(schunk_read), 0, sizeof(schunk_read)); memset(reinterpret_cast(schunk_modified), 0, sizeof(schunk_modified)); for (i = 0; i < 144; i++) delete [] schunk_cache[i]; memset(schunk_cache, 0, sizeof (schunk_cache)); memset(schunk_cache_sizes, -1, sizeof(schunk_cache_sizes)); } /* * Read in superchunk data to cover the screen. */ void Game_map::read_map_data ( ) { Game_window *gwin = Game_window::get_instance(); int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty(); int w = gwin->get_width(), h = gwin->get_height(); // Start one tile to left. int firstsx = (scrolltx - 1)/c_tiles_per_schunk, firstsy = (scrollty - 1)/c_tiles_per_schunk; // End 8 tiles to right. int lastsx = (scrolltx + (w + c_tilesize - 2)/c_tilesize + c_tiles_per_chunk/2)/c_tiles_per_schunk; int lastsy = (scrollty + (h + c_tilesize - 2)/c_tilesize + c_tiles_per_chunk/2)/c_tiles_per_schunk; // Watch for wrapping. int stopsx = (lastsx + 1)%c_num_schunks, stopsy = (lastsy + 1)%c_num_schunks; // Read in "map", "ifix" objects for // all visible superchunks. for (int sy = firstsy; sy != stopsy; sy = (sy + 1)%c_num_schunks) for (int sx = firstsx; sx != stopsx; sx = (sx + 1)%c_num_schunks) { // Figure superchunk #. int schunk = 12*sy + sx; // Read it if necessary. if (!schunk_read[schunk]) get_superchunk_objects(schunk); } } /* * Get the map objects and scenery for a superchunk. */ void Game_map::get_map_objects ( int schunk // Superchunk # (0-143). ) { int scy = 16*(schunk/12); // Get abs. chunk coords. int scx = 16*(schunk%12); // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) get_chunk_objects(scx + cx, scy + cy); } /* * Read in terrain graphics data into window's image. (May also be * called during map-editing if the chunknum changes.) */ void Game_map::get_chunk_objects ( int cx, int cy // Chunk index within map. ) { // Get list we'll store into. Map_chunk *chunk = get_chunk(cx, cy); int chunk_num = terrain_map[cx][cy]; Chunk_terrain *ter = get_terrain(chunk_num); chunk->set_terrain(ter); } /* * Read in all terrain chunks (for editing). */ void Game_map::get_all_terrain ( ) { if (read_all_terrain) return; // Already done. int num_chunk_terrains = chunk_terrains.size(); for (int i = 0; i < num_chunk_terrains; i++) if (!chunk_terrains[i]) read_terrain(i); read_all_terrain = true; } /* * Set a chunk to a new terrain (during map-editing). */ void Game_map::set_chunk_terrain ( int cx, int cy, // Coords. of chunk to change. int chunknum // New chunk #. ) { terrain_map[cx][cy] = chunknum; // Set map. get_chunk_objects(cx, cy); // Set chunk to it. } /* * Get the name of an ireg or ifix file. * * Output: ->fname, where name is stored. */ char *Game_map::get_schunk_file_name ( char *prefix, // "ireg" or "ifix". int schunk, // Superchunk # (0-143). char *fname // Name is stored here. ) { strcpy(fname, prefix); int len = strlen(fname); fname[len] = '0' + schunk/16; int lb = schunk%16; fname[len + 1] = lb < 10 ? ('0' + lb) : ('a' + (lb - 10)); fname[len + 2] = 0; return (fname); } /* * Write out the 'static' map files. */ void Game_map::write_static ( ) { U7mkdir("", 0755); // Create dir if not already there. Don't // use PATCHDAT define cause it has a // trailing slash int schunk; // Write each superchunk to 'static'. for (schunk = 0; schunk < c_num_schunks*c_num_schunks; schunk++) // Only write what we've modified. if (schunk_modified[schunk]) write_ifix_objects(schunk); int cnt = chunk_terrains.size(); int i; // Any terrains modified? for (i = 0; i < cnt; i++) if (chunk_terrains[i] && chunk_terrains[i]->is_modified()) break; if (i < cnt) // Got to update. { get_all_terrain(); // IMPORTANT: Get all in memory. ofstream ochunks; // Open file for chunks data. // This truncates the file. U7open(ochunks, PATCH_U7CHUNKS); for (i = 0; i < cnt; i++) { Chunk_terrain *ter = chunk_terrains[i]; unsigned char data[512]; if (ter) { ter->write_flats(data); ter->set_modified(false); } else { memset(&data[0], 0, 512); cerr << "NULL terrain. U7chunks may be bad." << endl; } ochunks.write(reinterpret_cast(data), 512); } if (!ochunks.good()) throw file_write_exception(U7CHUNKS); ochunks.close(); } std::ofstream u7map; // Write out map. U7open(u7map, PATCH_U7MAP); for (schunk = 0; schunk < c_num_schunks*c_num_schunks; schunk++) { int scy = 16*(schunk/12);// Get abs. chunk coords. int scx = 16*(schunk%12); uint8 buf[16*16*2]; uint8 *mapdata = buf; // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) Write2(mapdata, terrain_map[scx+cx][scy+cy]); u7map.write(reinterpret_cast(buf), sizeof(buf)); } if (!u7map.good()) throw file_write_exception(U7MAP); u7map.close(); map_modified = false; } /* * Write out one of the "u7ifix" files. * * Output: Errors reported. */ void Game_map::write_ifix_objects ( int schunk // Superchunk # (0-143). ) { char fname[128]; // Set up name. ofstream ifix_stream; // There it is. U7open(ifix_stream, get_schunk_file_name(PATCH_U7IFIX, schunk, fname)); StreamDataSource ifix(&ifix_stream); // +++++Use game title. const int count = c_chunks_per_schunk*c_chunks_per_schunk; Flex::write_header(&ifix, "Exult", count); uint8 table[2*count*4]; uint8 *tptr = &table[0]; int scy = 16*(schunk/12); // Get abs. chunk coords. int scx = 16*(schunk%12); // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) { // Store file position in table. long start = ifix.getPos(); Write4(tptr, start); Map_chunk *chunk = get_chunk(scx + cx, scy + cy); // Restore original order (sort of). Object_iterator_backwards next(chunk); Game_object *obj; while ((obj = next.get_next()) != 0) obj->write_ifix(&ifix); // Store IFIX data length. Write4(tptr, ifix.getPos() - start); } ifix.seek(0x80); // Write table. ifix.write(reinterpret_cast(&table[0]), sizeof(table)); ifix_stream.flush(); int result = ifix_stream.good(); if (!result) throw file_write_exception(fname); schunk_modified[schunk] = false; return; } /* * Read in the objects for a superchunk from one of the "u7ifix" files. */ void Game_map::get_ifix_objects ( int schunk // Superchunk # (0-143). ) { char fname[128]; // Set up name. ifstream ifix_stream; // There it is. if (is_system_path_defined("") && // First check for patch. U7exists(get_schunk_file_name(PATCH_U7IFIX, schunk, fname))) U7open(ifix_stream, fname); else try { U7open(ifix_stream, get_schunk_file_name(U7IFIX, schunk, fname)); } catch(const file_exception & f) { if (!Game::is_editing()) // Ok if map-editing. throw f; return; } StreamDataSource ifix(&ifix_stream); int scy = 16*(schunk/12); // Get abs. chunk coords. int scx = 16*(schunk%12); // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) { // Get to index entry for chunk. int chunk_num = cy*16 + cx; ifix.seek(0x80 + chunk_num*8); // Get location, length. long shapesoff = ifix.read4(); if (!shapesoff) // Nothing there? continue; unsigned long shapeslen = ifix.read4(); get_ifix_chunk_objects(&ifix, shapesoff, shapeslen/4, scx + cx, scy + cy); } } /* * Get the objects from one ifix chunk entry onto the screen. */ void Game_map::get_ifix_chunk_objects ( DataSource* ifix, long filepos, // Where chunk's data lies. int cnt, // # entries (objects). int cx, int cy // Absolute chunk #'s. ) { Game_window *gwin = Game_window::get_instance(); ifix->seek(filepos); // Get to actual shape. // Get buffer to hold entries' indices. unsigned char *entries = new unsigned char[4*cnt]; unsigned char *ent = entries; // Read them in. ifix->read(reinterpret_cast(entries), 4*cnt); // Get object list for chunk. Map_chunk *olist = get_chunk(cx, cy); for (int i = 0; i < cnt; i++, ent += 4) { Ifix_game_object *obj; int shnum = ent[2]+256*(ent[3]&3); Shape_info& info = ShapeID::get_info(shnum); if (info.is_animated() || info.has_sfx()) obj = new Animated_ifix_object(ent); else obj = new Ifix_game_object(ent); olist->add(obj); } delete[] entries; // Done with buffer. olist->setup_dungeon_levels(); // Should have all dungeon pieces now. } /* * Constants for IREG files: */ #define IREG_SPECIAL 255 // Precedes special entries. #define IREG_UCSCRIPT 1 // Saved Usecode_script for object. #define IREG_ENDMARK 2 // Just an 'end' mark. /* * Write out scheduled usecode for an object. */ void Game_map::write_scheduled ( DataSource* ireg, Game_object *obj, bool write_mark // Write an IREG_ENDMARK if true. ) { for (Usecode_script *scr = Usecode_script::find(obj); scr; scr = Usecode_script::find(obj, scr)) { unsigned char buf[256]; int len = scr->save(buf, sizeof(buf)); if (len < 0) cerr << "Error saving Usecode script" << endl; else if (len > 0) { ireg->write1(IREG_SPECIAL); ireg->write1(IREG_UCSCRIPT); ireg->write2(len); // Store length. ireg->write(reinterpret_cast(buf), len); } } if (write_mark) { ireg->write1(IREG_SPECIAL); ireg->write1(IREG_ENDMARK); } } /* * Write modified 'u7ireg' files. */ void Game_map::write_ireg ( ) { // Write each superchunk to Iregxx. for (int schunk = 0; schunk < c_num_schunks*c_num_schunks; schunk++) // Only write what we've read. if (schunk_cache[schunk] && schunk_cache_sizes[schunk] >= 0) { // It's loaded in a memory buffer char fname[128]; // Set up name. ofstream ireg_stream; U7open(ireg_stream, get_schunk_file_name(U7IREG, schunk, fname)); ireg_stream.write(schunk_cache[schunk], schunk_cache_sizes[schunk]); } else if (schunk_read[schunk]) { // It's active write_ireg_objects(schunk); } } /* * Write out one of the "u7ireg" files. * * Output: 0 if error, which is reported. */ void Game_map::write_ireg_objects ( int schunk // Superchunk # (0-143). ) { char fname[128]; // Set up name. ofstream ireg_stream; // There it is. U7open(ireg_stream, get_schunk_file_name(U7IREG, schunk, fname)); StreamDataSource ireg(&ireg_stream); write_ireg_objects (schunk, &ireg); ireg_stream.flush(); int result = ireg_stream.good(); if (!result) throw file_write_exception(fname); return; } /* * Write out one of the "u7ireg" files. * * Output: 0 if error, which is reported. */ void Game_map::write_ireg_objects ( int schunk, // Superchunk # (0-143). DataSource *ireg ) { int scy = 16*(schunk/12); // Get abs. chunk coords. int scx = 16*(schunk%12); // Go through chunks. for (int cy = 0; cy < 16; cy++) for (int cx = 0; cx < 16; cx++) { Map_chunk *chunk = get_chunk(scx + cx, scy + cy); Game_object *obj; // Restore original order (sort of). Object_iterator_backwards next(chunk); while ((obj = next.get_next()) != 0) obj->write_ireg(ireg); ireg->write2(0);// End with 2 0's. } } /* * Read in the objects for a superchunk from one of the "u7ireg" files. * (These are the moveable objects.) */ void Game_map::get_ireg_objects ( int schunk // Superchunk # (0-143). ) { char fname[128]; // Set up name. ifstream ireg_stream; // There it is. DataSource *ireg = 0; if (schunk_cache[schunk] && schunk_cache_sizes[schunk] >= 0) { // No items if (schunk_cache_sizes[schunk] == 0) return; ireg = new BufferDataSource (schunk_cache[schunk], schunk_cache_sizes[schunk]); #ifdef DEBUG std::cout << "Reading " << get_schunk_file_name(U7IREG, schunk, fname) << " from memory" << std::endl; #endif } else { try { U7open(ireg_stream, get_schunk_file_name(U7IREG, schunk, fname)); } catch(const file_exception & f) { return; // Just don't show them. } ireg = new StreamDataSource (&ireg_stream); } int scy = 16*(schunk/12); // Get abs. chunk coords. int scx = 16*(schunk%12); read_ireg_objects(ireg, scx, scy); // A fixup: if (schunk == 10*12 + 11 && Game::get_game_type() == SERPENT_ISLE) { // Lever in SilverSeed: Game_object_vector vec; if (Game_object::find_nearby(vec, Tile_coord(2936, 2726, 0), 787, 0, 0, c_any_qual, 5)) vec[0]->move(2937, 2727, 2); } delete ireg; if (schunk_cache[schunk]) { delete [] schunk_cache[schunk]; schunk_cache[schunk] = 0; schunk_cache_sizes[schunk] = -1; } } /* * Read in a 'special' IREG entry (one starting with 255). */ void Read_special_ireg ( DataSource *ireg, Game_object *obj // Last object read. ) { int type = ireg->read1(); // Get type. int len = ireg->read2(); // Length of rest. unsigned char *buf = new unsigned char[len]; ireg->read(reinterpret_cast(buf), len); if (type == IREG_UCSCRIPT) // Usecode script? { Usecode_script *scr = Usecode_script::restore(obj, buf, len); if (scr) { scr->start(scr->get_delay()); #if 0 COUT("Restored script for '" << item_names[obj->get_shapenum()] << "'" << endl); scr->print(cout); cout << endl; #endif } } else cerr << "Unknown special IREG entry: " << type << endl; delete [] buf; } /* * Read in a 'special' IREG entry (one starting with 255). */ void Game_map::read_special_ireg ( DataSource *ireg, Game_object *obj // Last object read. ) { unsigned char entlen; while ((entlen = ireg->peek()) == IREG_SPECIAL && !ireg->eof()) { ireg->read1(); // Eat the IREG_SPECIAL. unsigned char type = ireg->peek(); if (type == IREG_ENDMARK) { // End of list. ireg->read1(); return; } Read_special_ireg(ireg, obj); } } /* * Create an "egg". */ static Egg_object *Create_egg ( unsigned char *entry, // 1-byte ireg entry. bool animated ) { int shnum = entry[2]+256*(entry[3]&3); int frnum = entry[3] >> 2; unsigned short type = entry[4] + 256*entry[5]; int prob = entry[6]; // Probability (1-100). int data1 = entry[7] + 256*entry[8]; int lift = entry[9] >> 4; int data2 = entry[10] + 256*entry[11]; Egg_object *obj = animated ? new Animated_egg_object(shnum, frnum, entry[0]&0xf, entry[1]&0xf, lift, type, prob, data1, data2) : new Egg_object(shnum, frnum, entry[0]&0xf, entry[1]&0xf, lift, type, prob, data1, data2); return (obj); } /* * Containers and items classed as 'quality_flags' have a byte of flags. * This routine returns them converted into Object_flags. */ inline unsigned long Get_quality_flags ( unsigned char qualbyte // Quality byte containing flags. ) { return ((qualbyte&1) << Obj_flags::invisible) | (((qualbyte>>3)&1) << Obj_flags::okay_to_take); } /* * Read a list of ireg objects. They are either placed in the desired * game chunk, or added to their container. */ void Game_map::read_ireg_objects ( DataSource *ireg, // File to read from. int scx, int scy, // Abs. chunk coords. of superchunk. Game_object *container, // Container, or null. unsigned long flags // Usecode item flags. ) { int entlen; // Gets entry length. sint8 index_id = -1; Game_object *last_obj = 0; // Last one read in this call. Game_window *gwin = Game_window::get_instance(); // Go through entries. while (((entlen = ireg->read1(), !ireg->eof()))) { // Skip 0's & ends of containers. if (!entlen || entlen == 1) { if (container) return; // Skip 0's & ends of containers. else continue; } // Detect the 2 byte index id else if (entlen == 2) { index_id = (sint8) ireg->read2(); continue; } else if (entlen == IREG_SPECIAL) { Read_special_ireg(ireg, last_obj); continue; } // Get copy of flags. unsigned long oflags = flags & ~(1<getPos(); cout << "Unknown entlen " << entlen << " at pos. " << pos << endl; ireg->seek(pos + entlen); continue; // Only know these two types. } unsigned char entry[18];// Get entry. ireg->read(reinterpret_cast(entry), entlen); int cx = entry[0] >> 4; // Get chunk indices within schunk. int cy = entry[1] >> 4; // Get coord. #'s where shape goes. int tilex = entry[0] & 0xf; int tiley = entry[1] & 0xf; // Get shape #, frame #. int shnum = entry[2]+256*(entry[3]&3); int frnum = entry[3] >> 2; Shape_info& info = ShapeID::get_info(shnum); unsigned int lift, quality, type; Ireg_game_object *obj; int is_egg = 0; // Fields are eggs. // An "egg"? // Has flag byte(s) if (entlen == 10) { // Temporary if (entry[6] & 1) oflags |= 1<add_egg(egg); last_obj = egg; continue; } else if (entlen == 6 || entlen == 10) // Simple entry? { type = 0; lift = entry[4] >> 4; quality = entry[5]; obj = create_ireg_object(info, shnum, frnum, tilex, tiley, lift); is_egg = obj->is_egg(); // Wierd use of flag: if (info.has_quantity()) { if (!(quality&0x80)) oflags &= ~(1<> 4; quality = entry[7]; oflags = // Override flags (I think). Get_quality_flags(entry[11]); if (shnum == 330)// Virtue stone? { Virtue_stone_object *v = new Virtue_stone_object(shnum, frnum, tilex, tiley, lift); v->set_pos(entry[4], entry[5], entry[6], entry[7]); obj = v; type = 0; } else if (shnum == 961) { Barge_object *b = new Barge_object( shnum, frnum, tilex, tiley, lift, entry[4], entry[5], (quality>>1)&3); obj = b; if (!gwin->get_moving_barge() && (quality&(1<<3))) gwin->set_moving_barge(b); } else if (Game::get_game_type() == SERPENT_ISLE && shnum == 555) // serpent jawbone { obj = new Jawbone_object(shnum, frnum, tilex, tiley, lift, entry[10]); } else if (Game::get_game_type() == SERPENT_ISLE && shnum == 400 && frnum == 8 && quality == 1) // Gwenno. Ugly hack to fix bug without having to start // a new game. Remove someday... (added 20010820) { Dead_body *b = new Dead_body(400, 8, tilex, tiley, lift, 149); obj = b; gwin->set_body(149, b); } else if (quality == 1 && (entry[8] >= 0x80 || Game::get_game_type() == SERPENT_ISLE)) { // NPC's body. int npc_num = (entry[8] - 0x80) & 0xFF; Dead_body *b = new Dead_body(shnum, frnum, tilex, tiley, lift, npc_num); obj = b; gwin->set_body(npc_num, b); } else if (Is_body(shnum)) { obj = new Dead_body( shnum, frnum, tilex, tiley, lift, -1); } else obj = new Container_game_object( shnum, frnum, tilex, tiley, lift, entry[10]); // Read container's objects. if (type) // (0 if empty.) { // Don't pass along invisibility! read_ireg_objects(ireg, scx, scy, obj, oflags & ~(1<elements_read(); } } else // Length 18 means it's a spellbook. { // Get all 9 spell bytes. quality = 0; unsigned char circles[9]; memcpy(&circles[0], &entry[4], 5); lift = entry[9] >> 4; memcpy(&circles[5], &entry[10], 4); uint8 *ptr = &entry[14]; // 3 unknowns, then bookmark. unsigned char bmark = ptr[3]; obj = new Spellbook_object( shnum, frnum, tilex, tiley, lift, &circles[0], bmark); } obj->set_quality(quality); obj->set_flags(oflags); last_obj = obj; // Save as last read. // Add, but skip volume check. if (container) { if (index_id != -1 && container->add_readied(obj, index_id, 1, 1)) continue; else if (container->add(obj, 1)) continue; } Map_chunk *chunk = get_chunk(scx + cx, scy + cy); if (is_egg) chunk->add_egg((Egg_object *) obj); else chunk->add(obj); } } /* * Create non-container IREG objects. */ Ireg_game_object *Game_map::create_ireg_object ( Shape_info& info, // Info. about shape. int shnum, int frnum, // Shape, frame. int tilex, int tiley, // Tile within chunk. int lift // Desired lift. ) { if (info.is_field()) // (These are all animated.) { // Check shapes. if (shnum == 895 || // Fire. shnum == 561) // SI - blue flame. return new Field_object(shnum, frnum, tilex, tiley, lift, Egg_object::fire_field); else if (shnum == 900) // Poison. return new Field_object(shnum, frnum, tilex, tiley, lift, Egg_object::poison_field); else if (shnum == 902) // Sleep. return new Field_object(shnum, frnum, tilex, tiley, lift, Egg_object::sleep_field); else if (shnum == 756) // Caltrops. return new Field_object(shnum, frnum, tilex, tiley, lift, Egg_object::caltrops_field); } if (info.is_animated() || info.has_sfx()) return new Animated_ireg_object( shnum, frnum, tilex, tiley, lift); if (shnum == 607) // Path. return new Egglike_game_object( shnum, frnum, tilex, tiley, lift); if (shnum == 848 || shnum == 268) // Mirror return new Mirror_object(shnum, frnum, tilex, tiley, lift); else if (shnum == 761) // Spellbook. { static unsigned char circles[9] = {0}; return new Spellbook_object( shnum, frnum, tilex, tiley, lift, &circles[0], 0); } else if (info.get_shape_class() == Shape_info::container) { if (shnum == 555 && GAME_SI) return new Jawbone_object(shnum, frnum, tilex, tiley, lift); else return new Container_game_object(shnum, frnum, tilex, tiley, lift); } else return new Ireg_game_object(shnum, frnum, tilex, tiley, lift); } /* * Create non-container IREG objects. */ Ireg_game_object *Game_map::create_ireg_object ( int shnum, int frnum // Shape, frame. ) { return create_ireg_object(ShapeID::get_info(shnum), shnum, frnum, 0, 0, 0); } /* * Create 'fixed' (landscape, building) objects. */ Ifix_game_object *Game_map::create_ifix_object ( int shnum, int frnum // Shape, frame. ) { Shape_info& info = ShapeID::get_info(shnum); return (info.is_animated() || info.has_sfx()) ? new Animated_ifix_object(shnum, frnum, 0, 0, 0) : new Ifix_game_object(shnum, frnum, 0, 0, 0); } /* * Read in the objects in a superchunk. */ void Game_map::get_superchunk_objects ( int schunk // Superchunk #. ) { // CYCLE_RED_PLASMA(); get_map_objects(schunk); // Get map objects/scenery. // CYCLE_RED_PLASMA(); get_ifix_objects(schunk); // Get objects from ifix. // CYCLE_RED_PLASMA(); get_ireg_objects(schunk); // Get moveable objects. // CYCLE_RED_PLASMA(); schunk_read[schunk] = 1; // Done this one now. map_patches->apply(schunk); // Move/delete objects. } /* * Locate a chunk with a given terrain # and center the view on it. * * Output: true if found, else 0. */ bool Game_map::locate_terrain ( int tnum, // # in u7chunks. int& cx, int& cy, // Chunk to start at, or (-1,-1). // Updated with chunk found. bool upwards // If true, search upwards. ) { int cnum; // Chunk #, counting L-R, T-B. int cstop; // Stop when cnum == cstop. int dir; if (upwards) { cstop = -1; dir = -1; if (cx == -1) // Start at end? cnum = c_num_chunks*c_num_chunks - 1; else cnum = cy*c_num_chunks + cx - 1; } else { cstop = c_num_chunks*c_num_chunks; dir = 1; cnum = (cx == -1) ? 0 : cy*c_num_chunks + cx + 1; } while (cnum != cstop) { int chunky = cnum/c_num_chunks; int chunkx = cnum%c_num_chunks; if (terrain_map[chunkx][chunky] == tnum) { // Return chunk # found. cx = chunkx; cy = chunky; // Center window over chunk found. Game_window::get_instance()->center_view(Tile_coord( cx*c_tiles_per_chunk + c_tiles_per_chunk/2, cy*c_tiles_per_chunk + c_tiles_per_chunk/2, 0)); return true; } cnum += dir; } return false; // Failed. } /* * Swap two adjacent terrain #'s, keeping the map looking the same. * * Output: false if unsuccessful. */ bool Game_map::swap_terrains ( int tnum // Swap tnum and tnum + 1. ) { if (tnum < 0 || tnum >= chunk_terrains.size() - 1) return false; // Out of bounds. map_modified = true; // Swap in list. Chunk_terrain *tmp = get_terrain(tnum); tmp->set_modified(); chunk_terrains[tnum] = get_terrain(tnum + 1); chunk_terrains[tnum]->set_modified(); chunk_terrains[tnum + 1] = tmp; // Update terrain map. for (int cy = 0; cy < c_num_chunks; cy++) for (int cx = 0; cx < c_num_chunks; cx++) { if (terrain_map[cx][cy] == tnum) terrain_map[cx][cy]++; else if (terrain_map[cx][cy] == tnum + 1) terrain_map[cx][cy]--; } Game_window::get_instance()->set_all_dirty(); return true; } /* * Insert a new terrain after a given one, and push all the others up * so the map looks the same. The new terrain is filled with * (shape, frame) == (0, 0) unless 'dup' is passed 'true'. * * Output: False if unsuccessful. */ bool Game_map::insert_terrain ( int tnum, // Insert after this one (may be -1). bool dup // If true, duplicate #tnum. ) { if (tnum < -1 || tnum >= chunk_terrains.size()) return false; // Invalid #. get_all_terrain(); // Need all of 'u7chunks' read in. map_modified = true; unsigned char buf[16*16*2]; // Set up buffer with shape #'s. if (dup && tnum >= 0) { // Want to duplicate given terrain. Chunk_terrain *ter = chunk_terrains[tnum]; unsigned char *data = &buf[0]; for (int ty = 0; ty < c_tiles_per_chunk; ty++) for (int tx = 0; tx < c_tiles_per_chunk; tx++) { ShapeID id = ter->get_flat(tx, ty); *data++ = id.get_shapenum()&0xff; *data++ = ((id.get_shapenum()>>8)&3) | (id.get_framenum()<<2); } } else memset(reinterpret_cast(buf), 0, sizeof(buf)); Chunk_terrain *new_terrain = new Chunk_terrain(&buf[0]); // Insert in list. chunk_terrains.insert(chunk_terrains.begin() + tnum + 1, new_terrain); // Indicate terrains are modified. int num_chunk_terrains = chunk_terrains.size(); for (int i = tnum + 1; i < num_chunk_terrains; i++) chunk_terrains[i]->set_modified(); if (tnum + 1 == num_chunk_terrains - 1) return true; // Inserted at end of list. // Update terrain map. for (int cy = 0; cy < c_num_chunks; cy++) for (int cx = 0; cx < c_num_chunks; cx++) { if (terrain_map[cx][cy] > tnum) terrain_map[cx][cy]++; } Game_window::get_instance()->set_all_dirty(); return true; } /* * Remove a terrain, updating the map. * * Output: false if unsuccessful. */ bool Game_map::delete_terrain ( int tnum ) { if (tnum < 0 || tnum >= chunk_terrains.size()) return false; // Out of bounds. map_modified = true; int sz = chunk_terrains.size(); delete chunk_terrains[tnum]; for (int i = tnum + 1; i < sz; i++) { // Move the rest downwards. Chunk_terrain *tmp = get_terrain(i); tmp->set_modified(); chunk_terrains[i - 1] = tmp; } chunk_terrains.resize(sz - 1); // Update terrain map. for (int cy = 0; cy < c_num_chunks; cy++) for (int cx = 0; cx < c_num_chunks; cx++) { if (terrain_map[cx][cy] >= tnum) terrain_map[cx][cy]--; } Game_window::get_instance()->set_all_dirty(); return true; } /* * Commit edits made to terrain chunks. */ void Game_map::commit_terrain_edits ( ) { int num_terrains = chunk_terrains.size(); // Create list of flags. unsigned char *ters = new unsigned char[num_terrains]; memset(ters, 0, num_terrains); // Commit edits. for (int i = 0; i < num_terrains; i++) if (chunk_terrains[i] && chunk_terrains[i]->commit_edits()) ters[i] = 1; // Update terrain map. for (int cy = 0; cy < c_num_chunks; cy++) for (int cx = 0; cx < c_num_chunks; cx++) { Map_chunk *chunk = objects[cx][cy]; if (chunk && ters[terrain_map[cx][cy]] != 0 && chunk->get_terrain()) // Reload objects. chunk->set_terrain(chunk->get_terrain()); } delete [] ters; } /* * Abort edits made to terrain chunks. */ void Game_map::abort_terrain_edits ( ) { int num_terrains = chunk_terrains.size(); // Abort edits. for (int i = 0; i < num_terrains; i++) if (chunk_terrains[i]) chunk_terrains[i]->abort_edits(); } /* * Find all unused shapes in game. This can take a while!! */ void Game_map::find_unused_shapes ( unsigned char *found, // Bits set for shapes found. int foundlen // # bytes. ) { memset(found, 0, foundlen); Game_window *gwin = Game_window::get_instance(); Shape_manager *sman = Shape_manager::get_instance(); cout << "Reading all chunks"; // Read in EVERYTHING! for (int sc = 0; sc < c_num_schunks*c_num_schunks; sc++) { cout << '.'; cout.flush(); char msg[80]; snprintf(msg, sizeof(msg), "Scanning superchunk %d", sc); gwin->get_effects()->center_text(msg); gwin->paint(); gwin->show(); if (!schunk_read[sc]) get_superchunk_objects(sc); } cout << endl; int maxbits = foundlen*8; // Total #bits in 'found'. int nshapes = sman->get_shapes().get_num_shapes(); if (maxbits > nshapes) maxbits = nshapes; // Go through chunks. for (int cy = 0; cy < c_num_chunks; cy++) for (int cx = 0; cx < c_num_chunks; cx++) { Map_chunk *chunk = get_chunk(cx, cy); Recursive_object_iterator all(chunk->get_objects()); Game_object *obj; while ((obj = all.get_next()) != 0) { int shnum = obj->get_shapenum(); if (shnum >= 0 && shnum < maxbits) found[shnum/8] |= (1<<(shnum%8)); } } int i; for (i = 0; i < maxbits; i++) // Add all possible monsters. { Shape_info& info = ShapeID::get_info(i); Monster_info *minf = info.get_monster_info(); if (minf) found[i/8] |= (1<<(i%8)); Weapon_info *winf = info.get_weapon_info(); if (winf) // Get projectiles for weapons. { int proj = winf->get_projectile(); if (proj > 0 && proj < maxbits) found[proj/8] |= (1<<(proj%8)); } } for (i = 0x96; i < maxbits; i++) // Ignore flats (<0x96). if (!(found[i/8]&(1<<(i%8)))) cout << "Shape " << i << " not found in game" << endl; } /* * Look throughout the map for a given shape. The search starts at * the first currently-selected shape, if possible. * * Output: ->object if found, else 0. */ Game_object *Game_map::locate_shape ( int shapenum, // Desired shape. bool upwards, // If true, search upwards. Game_object *start // Start here if !0. ) { int cx = -1, cy = 0; // Before chunk to search. int dir = 1; // Direction to increment. int stop = c_num_chunks; if (upwards) { dir = -1; stop = -1; cx = c_num_chunks; // Past last chunk. cy = c_num_chunks - 1; } Game_object *obj = 0; if (start) // Start here. { Game_object *owner = start->get_outermost(); cx = owner->get_cx(); cy = owner->get_cy(); if (upwards) { Recursive_object_iterator_backwards next(start); while ((obj = next.get_next()) != 0) if (obj->get_shapenum() == shapenum) break; } else { Recursive_object_iterator next(start); while ((obj = next.get_next()) != 0) if (obj->get_shapenum() == shapenum) break; } } while (!obj) // Not found yet? { cx += dir; // Next chunk. if (cx == stop) // Past (either) end? { cy += dir; if (cy == stop) break; // All done. cx -= dir*c_num_chunks; } Map_chunk *chunk = get_chunk(cx, cy); // Make sure objs. are read. int sx = cx/c_chunks_per_schunk, sy = cy/c_chunks_per_schunk; int schunk = sy*c_num_schunks + sx; if (!schunk_read[schunk]) get_superchunk_objects(schunk); if (upwards) { Recursive_object_iterator_backwards next( chunk->get_objects()); while ((obj = next.get_next()) != 0) if (obj->get_shapenum() == shapenum) break; } else { Recursive_object_iterator next(chunk->get_objects()); while ((obj = next.get_next()) != 0) if (obj->get_shapenum() == shapenum) break; } } return obj; } /* * Do a cache out. (x, y) is the center */ void Game_map::cache_out(int cx, int cy) { int sx = cx / c_chunks_per_schunk; int sy = cy / c_chunks_per_schunk; bool chunk_flags[12][12]; #ifdef DEBUG std::cout << "Want to cache out around super chunk: " << (sy*12 + sx) << " = " << sx << ", " << sy << std::endl; #endif std::memset(chunk_flags, 0, sizeof(chunk_flags)); // We cache out all but the 9 directly around the pov chunk_flags[(sy+11)%12][(sx+11)%12] = true; chunk_flags[(sy+11)%12][sx] = true; chunk_flags[(sy+11)%12][(sx+1)%12] = true; chunk_flags[sy][(sx+11)%12] = true; chunk_flags[sy][sx] = true; chunk_flags[sy][(sx+1)%12] = true; chunk_flags[(sy+1)%12][(sx+11)%12] = true; chunk_flags[(sy+1)%12][sx] = true; chunk_flags[(sy+1)%12][(sx+1)%12] = true; for (sy = 0; sy < 12; sy++) for (sx = 0; sx < 12; sx++) { if (chunk_flags[sy][sx]) continue; int schunk = sy*12 + sx; if (schunk_read[schunk] && !schunk_modified[schunk]) cache_out_schunk(schunk); } } void Game_map::cache_out_schunk(int schunk) { // Get abs. chunk coords. const int scy = 16*(schunk/12); const int scx = 16*(schunk%12); int cy, cx; bool save_map_modified = map_modified; if (schunk_modified[schunk]) return; // NEVER cache out modified chunks. // Our vectors Game_object_vector removes; Actor_vector actors; int buf_size = 0; #ifdef DEBUG std::cout << "Killing superchunk: " << schunk << std::endl; #endif // Go through chunks and get all the items for (cy = 0; cy < 16; cy++) for (cx = 0; cx < 16; cx++) { int size = objects[scx + cx][scy + cy]->get_obj_actors(removes, actors); if (size < 0) { #ifdef DEBUG std::cerr << "Failed attempting to kill superchunk" << std::endl; #endif return; } buf_size += size + 2; } schunk_read[schunk] = false; #ifdef DEBUG std::cout << "Buffer size of " << buf_size << " bytes required to store super chunk" << std::endl; #endif // Clear old (this shouldn't happen) if (schunk_cache[schunk]) { delete [] schunk_cache[schunk]; schunk_cache[schunk] = 0; schunk_cache_sizes[schunk] = -1; } // Create new schunk_cache[schunk] = new char[buf_size]; schunk_cache_sizes[schunk] = buf_size; BufferDataSource ds(schunk_cache[schunk], schunk_cache_sizes[schunk]); write_ireg_objects(schunk, &ds); #ifdef DEBUG std::cout << "Wrote " << ds.getPos() << " bytes" << std::endl; #endif // Now remove the objects for (Game_object_vector::const_iterator it=removes.begin(); it!=removes.end(); ++it) { (*it)->delete_contents(); (*it)->remove_this(); } // Now disable the actors for (Actor_vector::const_iterator act=actors.begin(); act!=actors.end(); ++act) { (*act)->cache_out(); } // Go through chunks and finish up for (cy = 0; cy < 16; cy++) for (cx = 0; cx < 16; cx++) { objects[scx + cx][scy + cy]->kill_cache(); } // Removing objs. sets these flags. schunk_modified[schunk] = false; map_modified = save_map_modified; } exult-1.2/README.BeOS0000644000175000001440000000235107316667410007654 Exult instructions for BeOS ---------------------------- To play ------- First you need to get Ultima 7. Either you own it already, or you buy it somewhere. Then you must install it on a DOS/Windows machine to get the data files. Alternatively, the 'Ultima Collection' already contains a pre-installed version of U7. (in the directory /ultima7) When you run Exult for the first time, it will generate a default ~/config/settings/exult.cfg. (Quit from the main menu, since Exult won't be able to find U7). You need point the paths in this file to the ultima7 directory and the Exult data directory. The relevant entries should read something like this: /path/to/ultima7/directory blackgate /path/to/exult/data/directory (rest of the config file) When the paths are set correctly, you can run Exult in BeOS. Have fun! Notes ------ * You can build exult from source yourself if you want. To do this, you obviously need the Exult source code. You'll also need the development SDL binaries or the SDL source. (available from www.libsdl.org) To build exult: copy Makefile.be to Makefile, and run 'make'. exult-1.2/README.Qtopia0000644000175000001440000000704207711505356010322 HOW TO COMPILE EXULT FOR A QTOPIA PLATFORM By Artaxerxes (artaxerxes2@iname.com) note: I'll mostly discuss the Sharp Zaurus SL5500, although I believe any Qtopia platform would do. Let me know otherwise. Steps: 0- Get the Zlib compiled for the ARM platform 1- Get the SDL compiled for the ARM platform AND for the platform on which you will cross-compile 2- Get all the cross-compiling environment up and running 3- Get the CVS source from exult 4- Modify the source where mentioned herein 5- Compile, strip (don't forget that) and copy to the PDA 6- Run and enjoy Steps 0, 1, 2, 3 will not be discussed here. However here are the link you need to know: NOTE: install the development files in /opt/Qtopia/sharp/lib and /opt/Qtopia/sharp/include 0- Zlib: http://www.gzip.org/zlib/ 1- libSDL from Alexandre Courbot: http://www.gnurou.org/zaurus/feed/libSDL_1.2.5cvs-1_arm.ipk and http://www.gnurou.org/zaurus/feed/libSDL-mixer_1.2.5cvs-1_arm.ipk 2- Cross-compiling: http://www.zauruszone.farplanet.net/howtos/linux_compiler_setup_howto.shtml 3- Exult: http://exult.sf.net/ CHANGES TO APPLY TO THE SOURCE CODE sdl-config: ---------- make sure the -Dmain=SDL_main is _REMOVED_ COMPILATION CAVEATS Don't forget to activate the cross-compiling environment before any cross-compiling work! ( $ source ~/dev-arm-qpe.sh ) ./autogen.sh should work on its own ./configure should be passed in the following manner: NOTE: updated the 2003/07/29 NM=arm-linux-nm LD=arm-linux-ld CC=arm-linux-gcc CXX=arm-linux-g++ RANLIB=arm-linux-ranlib AR=arm-linux-ar CPPFLAGS=-I/opt/Qtopia/sharp/include/ LDFLAGS=-L/opt/Qtopia/sharp/lib/ ./configure -host=arm-embeddix-linux-gnu --disable-exult-studio-support --disable-debug --disable-exult-studio --disable-gimp-plugin --disable-tools --disable-compiler --enable-data --disable-timidity --disable-kmid --prefix=/opt/Qtopia NOTE: updated the 2003/02/05 NM=arm-linux-nm LD=arm-linux-ld CC=arm-linux-gcc CXX=arm-linux-g++ RANLIB=arm-linux-ranlib AR=arm-linux-ar ./configure arm-embeddix-linux-gnu --disable-exult-studio-support --disable-debug --disable-exult-studio --disable-gimp-plugin --disable-tools --disable-compiler --enable-data --disable-timidity --disable-kmid (it's all on one line) [and no more NM=arm-linux-nm LD=arm-linux-ld CC=arm-linux-gcc CXX=arm-linux-g++ RANLIB=arm-linux-ranlib AR=arm-linux-ar ./configure --prefix=/opt/QtPalmtop --disable-tools --enable-debug arm-zaurus-linux-gnu] Exult uses some tools for its compilation. Of course, those tools get compiled by the ARM cross compiler so it won't work on your platform. Make sure you put a hand on "expack" (compiled for your platform) before any work. It is useless to do a "make install". Don't forget to strip your binary (it should be around 30MB now). The stripped binary is around 2 or 3 MB big. $ pwd /path/to/exult/sources $ /opt/Embeddix/tools/arm-linux/bin/strip exult Copy the binary to the PDA with the method you prefer. Don't forget to copy the exult.flx, exult_bg.flx, exult_si.flx to the PDA also. They should go to the /opt/QtPalmtop/data/ directory. I find that with or without a swap file, you get a random crash or a random hang. Launch exult, edit the ~/.exult.cfg created so that it points to where your BG or SI data files are and restart exult! Congratulations, you are running Exult on your PDA! Artaxerxes artaxerxes2@iname.com DISCLAIMER: this is just an overall indication of the steps to follow. As far as I know, I'm not missing any point. If I do, let me know. I claim no responsabilities for any damage, trouble, distress, frustration caused by cross-compiling exult. exult-1.2/INSTALL0000644000175000001440000002234007633741146007237 Exult Installation ================== If you're reading this you have either downloaded a source distribution and untarred it, or you've checked out the latest tree from CVS. Good. Make sure you have the following things installed: - SDL The Simple DirectMedia Library by Sam Lantinga of Loki Games. http://www.libsdl.org - SDL_mixer http://www.libsdl.org - Timidity patches If you want MIDI music, SDL_mixer needs Timidity patches. Your distribution might already provide these. http://www.goice.co.jp/member/mo/timidity/ Make sure you get the sound patches required by this (also known as GUS patches) http://www.libsdl.org/projects/SDL_mixer/timidity/timidity.tar.gz If you're building from CVS you'll also need recent versions of: automake autoconf libtool Run the autogen.sh file to generate configure and other necessary scripts. Got everything? Excellent. Now you can build your own binary of Exult. From the top directory type the following: ./configure make If everything goes well, you should end up with an 'exult' binary. See the documentation at http://exult.sourceforge.net/docs.php or the included README file for information on how to create an exult config file to indicate where you have installed Ultima VII, and you're ready to run Exult. Please report any bugs on Exult's SourceForge bug-tracking system: http://sourceforge.net/bugs/?group_id=2335 If you want to work on Exult, just contact us on the Exult developer's mailing list: http://lists.sourceforge.net/mailman/listinfo/exult-general -------------------------------------------------- Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. exult-1.2/schedule.cc0000644000175000001440000023537510054030532010304 /* * Schedule.cc - Schedules for characters. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_timer.h" #include "schedule.h" #include "actors.h" #include "Zombie.h" #include "gamewin.h" #include "gameclk.h" #include "gamemap.h" #include "actions.h" #include "dir.h" #include "items.h" #include "game.h" #include "paths.h" #include "ucmachine.h" #include "ucsched.h" #include "ucscriptop.h" #include "monstinf.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::rand; #endif /* * Create. */ Schedule::Schedule ( Actor *n ) : npc(n), blocked(-1, -1, -1), street_maintenance_failures(0), street_maintenance_time(0) { prev_type = npc ? npc->get_schedule_type() : -1; } /* * Set up an action to get an actor to a location (via pathfinding), and * then execute another action when he gets there. */ void Schedule::set_action_sequence ( Actor *actor, // Whom to activate. Tile_coord dest, // Where to walk to. Actor_action *when_there, // What to do when he gets there. bool from_off_screen, // Have actor walk from off-screen. int delay // Msecs. to delay. ) { actor->set_action(Actor_action::create_action_sequence( actor, dest, when_there, from_off_screen)); actor->start(250, delay); // Get into time queue. } /* * Look for lamps to light/unlight and shutters to open/close. * * Output: 1 if successful, which means npc's schedule has changed! */ int Schedule::try_street_maintenance ( ) { // What to look for: static int night[] = {322, 372, 889}; static int sinight[] = {290, 291, 889}; static int day[] = {290, 291, 526}; long curtime = Game::get_ticks(); if (curtime < street_maintenance_time) return 0; // Not time yet. if (npc->Actor::get_npc_num() <= 0 || npc == gwin->get_camera_actor()) return 0; // Only want normal NPC's. // At least 30secs. before next one. street_maintenance_time = curtime + 30000 + street_maintenance_failures*5000; int *shapes; int hour = gclock->get_hour(); bool bg = (Game::get_game_type() == BLACK_GATE); if (hour >= 9 && hour < 18) shapes = &day[0]; else if (hour >= 18 || hour < 6) shapes = bg ? &night[0] : &sinight[0]; else return 0; // Dusk or dawn. Tile_coord npcpos = npc->get_tile(); // Look at screen + 1/2. Rectangle winrect = gwin->get_win_tile_rect(); winrect.enlarge(winrect.w/4); if (!winrect.has_point(npcpos.tx, npcpos.ty)) return 0; // Get to within 1 tile. Actor_pathfinder_client cost(npc, 1); Game_object *found = 0; // Find one we can get to. Actor_action *pact; // Gets ->action to walk there. for (int i = 0; !found && i < sizeof(night)/sizeof(night[0]); i++) { Game_object_vector objs;// Find nearby. int cnt = npc->find_nearby(objs, shapes[i], 20, 0); int j; for (j = 0; j < cnt; j++) { Game_object *obj = objs[j]; int shnum = obj->get_shapenum(); if (!bg && // Serpent isle? Shutters? (shnum == 290 || shnum == 291)) // Want closed during day. if ((shapes == day) != (obj->get_framenum() <= 3)) continue; if ((pact = Path_walking_actor_action::create_path( npcpos, obj->get_tile(), cost)) != 0) { found = obj; break; } street_maintenance_failures++; } } if (!found) return 0; // Failed. // Set actor to walk there. npc->set_schedule_type(Schedule::street_maintenance, new Street_maintenance_schedule(npc, pact, found)); street_maintenance_failures = 0;// We did it, so clear failures. return 1; } /* * Get actual schedule (for Usecode intrinsic). */ int Schedule::get_actual_type ( Actor *npc ) { return npc->get_schedule_type(); } /* * Create schedule to turn lamps on/off, open/close shutters. */ Street_maintenance_schedule::Street_maintenance_schedule ( Actor *n, Actor_action *p, Game_object *o ) : Schedule(n), obj(o), shapenum(o->get_shapenum()), framenum(o->get_framenum()), paction(p) { } /* * Street-maintenance schedule. */ void Street_maintenance_schedule::now_what ( ) { if (paction) // First time? { // Set to follow given path. cout << npc->get_name() << " walking for street maintenance" << endl; npc->set_action(paction); npc->start(250); paction = 0; return; } if (npc->distance(obj) == 1 && // We're there. obj->get_shapenum() == shapenum && obj->get_framenum() == framenum) { cout << npc->get_name() << " about to perform street maintenance" << endl; int dir = npc->get_direction(obj); signed char frames[2]; frames[0] = npc->get_dir_framenum(dir, Actor::standing); frames[1] = npc->get_dir_framenum(dir, 3); signed char standframe = frames[0]; npc->set_action(new Sequence_actor_action( new Frames_actor_action(frames, sizeof(frames)), new Activate_actor_action(obj), new Frames_actor_action(&standframe, 1))); npc->start(250); switch (shapenum) { case 322: // Closing shutters. case 372: npc->say(first_close_shutters, last_close_shutters); break; case 290: // Open shutters (or both for SI). case 291: if (Game::get_game_type() == BLACK_GATE) npc->say(first_open_shutters, last_open_shutters); else // SI. if (framenum <= 3) npc->say(first_open_shutters, last_open_shutters); else npc->say(first_close_shutters, last_close_shutters); break; case 889: // Turn on lamp. npc->say(first_lamp_on, last_lamp_on); break; case 526: // Turn off lamp. npc->say(lamp_off, lamp_off); break; } shapenum = 0; // Don't want to repeat. return; } cout << npc->get_name() << " done with street maintenance" << endl; // Set back to old schedule. int period = gclock->get_hour()/3; npc->update_schedule(period, 7, 0); } /* * Get actual schedule (for Usecode intrinsic). */ int Street_maintenance_schedule::get_actual_type ( Actor * /* npc */ ) { return prev_type; } /* * What do we do now? */ void Follow_avatar_schedule::now_what ( ) { bool is_blocked = blocked.tx != -1; blocked = Tile_coord(-1, -1, -1); if (npc->get_flag(Obj_flags::asleep) || npc->is_dead() || npc->get_flag(Obj_flags::paralyzed) || gwin->main_actor_dont_move()) // Under Usecode control. return; // Disabled. Actor *av = gwin->get_main_actor(); Tile_coord leaderpos = av->get_tile(); Tile_coord pos = npc->get_tile(); int dist2lead = leaderpos.distance(pos); if (!av->is_moving() && // Avatar stopped. dist2lead <= 6) // And we're already close enough. return; uint32 curtime = SDL_GetTicks();// Want the REAL time here. if (!is_blocked) // Not blocked? { npc->follow(av); // Then continue following. return; } if (curtime < next_path_time) // Failed pathfinding recently? { // Wait a bit. npc->start(gwin->get_std_delay(), next_path_time - curtime); return; } // Find a free spot within 3 tiles. Map_chunk::Find_spot_where where = Map_chunk::anywhere; // And try to be inside/outside. where = gwin->is_main_actor_inside() ? Map_chunk::inside : Map_chunk::outside; Tile_coord goal = Map_chunk::find_spot(leaderpos, 3, npc, 0, where); if (goal.tx == -1) // No free spot? Give up. { cout << npc->get_name() << " can't find free spot" << endl; next_path_time = SDL_GetTicks() + 1000; return; } // Get his speed. int speed = av->get_frame_time(); if (!speed) // Avatar stopped? speed = gwin->get_std_delay(); if (pos.distance(goal) <= 3) return; // Already close enough! #if 0 #ifdef DEBUG cout << npc->get_name() << " at distance " << dist2lead << " trying to catch up." << endl; #endif #endif // Succeed if within 3 tiles of goal. if (npc->walk_path_to_tile(goal, speed - speed/4, 0, 3, 1)) return; // Success. cout << "... but failed to find path." << endl; // On screen (roughly)? int ok; // Get window rect. in tiles. Rectangle wrect = gwin->get_win_tile_rect(); if (wrect.has_point(pos.tx - pos.tz/2, pos.ty - pos.tz/2)) // Try walking off-screen. ok = npc->walk_path_to_tile(Tile_coord(-1, -1, -1), speed - speed/4, 0); else // Off screen already? ok = npc->approach_another(av); if (!ok) // Failed? Don't try again for a bit. next_path_time = SDL_GetTicks() + 1000; } /* * Waiting... */ void Wait_schedule::now_what ( ) { } /* * Create a horizontal pace schedule. */ Pace_schedule *Pace_schedule::create_horiz ( Actor *n ) { Tile_coord t = n->get_tile(); // Get his position. return (new Pace_schedule(n, Tile_coord(t.tx - 4, t.ty, t.tz), Tile_coord(t.tx + 4, t.ty, t.tz))); } /* * Create a vertical pace schedule. */ Pace_schedule *Pace_schedule::create_vert ( Actor *n ) { Tile_coord t = n->get_tile(); // Get his position. return (new Pace_schedule(n, Tile_coord(t.tx, t.ty - 4, t.tz), Tile_coord(t.tx, t.ty + 4, t.tz))); } /* * Schedule change for pacing: */ void Pace_schedule::now_what ( ) { if (rand() % 6 == 0) // Check for lamps, etc. if (try_street_maintenance()) return; // We no longer exist. which = !which; // Flip direction. int delay = 750; // Delay .75 secs. if (blocked.tx != -1) // Blocked? { Game_object *obj = Game_object::find_blocking(blocked); blocked.tx = -1; Monster_info *minfo = npc->get_info().get_monster_info(); if (obj && obj->as_actor() != 0 && (!minfo || !minfo->cant_yell())) { npc->say(first_move_aside, last_move_aside); delay = 1200; // Wait longer. } } // Wait 1 sec. before moving. npc->walk_to_tile(which ? p1 : p0, gwin->get_std_delay(), delay); } /* * Eat at inn. */ void Eat_at_inn_schedule::now_what ( ) { int frnum = npc->get_framenum(); if ((frnum&0xf) != Actor::sit_frame) { // First have to sit down. if (!Sit_schedule::set_action(npc)) { // Try again in a while. npc->start(250, 5000); return; } } Game_object_vector foods; // Food nearby? int cnt = npc->find_nearby(foods, 377, 2, 0); if (cnt) // Found? { // Find closest. Game_object *food = 0; int dist = 500; for (Game_object_vector::const_iterator it = foods.begin(); it != foods.end(); ++it) { Game_object *obj = *it; int odist = obj->distance(npc); if (odist < dist) { dist = odist; food = obj; } } if (rand()%5 == 0) { gwin->add_dirty(food); food->remove_this(); } if (rand()%4) npc->say(first_munch, last_munch); } else if (rand()%4) npc->say(first_more_food, last_more_food); // Wake up in a little while. npc->start(250, 5000 + rand()%12000); } /* * Find someone listening to the preacher. */ Actor *Find_congregant ( Actor *npc ) { Actor_vector vec, vec2; if (!npc->find_nearby_actors(vec, c_any_shapenum, 16)) return 0; vec2.reserve(vec.size()); // Get list of ones to consider. for (Actor_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Actor *act = *it; if (act->get_schedule_type() == Schedule::sit && !act->is_in_party()) vec2.push_back(act); } return vec2.size() ? vec2[rand()%vec2.size()] : 0; } /* * Preach: */ void Preach_schedule::now_what ( ) { switch (state) { case find_podium: { Game_object_vector vec; if (!npc->find_nearby(vec, 697, 17, 0)) { npc->set_schedule_type(loiter); return; } Game_object *podium = vec[0]; Tile_coord pos = podium->get_tile(); static int deltas[4][2] = {{-1, 0},{1, 0},{0, -2},{0, 1}}; int frnum = podium->get_framenum()%4; pos.tx += deltas[frnum][0]; pos.ty += deltas[frnum][1]; Actor_pathfinder_client cost(npc, 0); Actor_action *pact = Path_walking_actor_action::create_path( npc->get_tile(), pos, cost); if (pact) { state = at_podium; npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action(podium, 200))); npc->start(gwin->get_std_delay()); return; } npc->start(250, 5000 + rand()%5000); // Try again later. return; } case at_podium: if (rand()%2) // Just wait a little. npc->start(gwin->get_std_delay(), rand()%3000); else { if (rand()%3) state = exhort; else if ((GAME_SI) || rand()%3) state = visit; else state = find_icon; npc->start(gwin->get_std_delay(), 2000 + rand()%2000); } return; case exhort: { signed char frames[8]; // Frames. int cnt = 1 + rand()%(sizeof(frames) - 1); // Frames to choose from: static char choices[3] = {0, 8, 9}; for (int i = 0; i < cnt - 1; i++) frames[i] = npc->get_dir_framenum( choices[rand()%(sizeof(choices))]); // Make last one standing. frames[cnt - 1] = npc->get_dir_framenum(Actor::standing); npc->set_action(new Frames_actor_action(frames, cnt, 250)); npc->start(gwin->get_std_delay()); npc->say(first_preach, last_preach); state = at_podium; Actor *member = Find_congregant(npc); if (member) { Usecode_script *scr = new Usecode_script(member); scr->add(Ucscript::delay_ticks, 3); scr->add(Ucscript::face_dir, member->get_dir_facing()); scr->add(Ucscript::npc_frame + Actor::standing); scr->add(Ucscript::say, item_names[first_amen + rand()%(last_amen - first_amen + 1)]); scr->add(Ucscript::delay_ticks, 2); scr->add(Ucscript::npc_frame + Actor::sit_frame); scr->start(); // Start next tick. } return; } case visit: { state = find_podium; npc->start(gwin->get_std_delay(), 1000 + rand()%2000); Actor *member = Find_congregant(npc); if (!member) return; Tile_coord pos = member->get_tile(); Actor_pathfinder_client cost(npc, 1); Actor_action *pact = Path_walking_actor_action::create_path( npc->get_tile(), pos, cost); if (!pact) return; npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action(member, 200))); state = talk_member; return; } case talk_member: state = find_podium; npc->say(first_preach2, last_preach2); npc->start(250, 2000); return; case find_icon: { state = find_podium; // In case we fail. npc->start(2*gwin->get_std_delay()); Game_object *icon = npc->find_closest(724); if (!icon) return; Tile_coord pos = icon->get_tile(); pos.tx += 2; pos.ty -= 1; Actor_pathfinder_client cost(npc, 0); Actor_action *pact = Path_walking_actor_action::create_path( npc->get_tile(), pos, cost); if (pact) { static char f[] = {Actor::standing, Actor::bow_frame, Actor::kneel_frame, Actor::kneel_frame, Actor::kneel_frame, Actor::kneel_frame, Actor::bow_frame, Actor::standing}; npc->set_action(pact); state = pray; } return; } case pray: { Usecode_script *scr = new Usecode_script(npc); (*scr) << Ucscript::face_dir << 6 // Face west. << (Ucscript::npc_frame + Actor::standing) << (Ucscript::npc_frame + Actor::bow_frame) << Ucscript::delay_ticks << 3 << (Ucscript::npc_frame + Actor::kneel_frame); scr->add(Ucscript::say, item_names[first_amen + rand()%2]); (*scr) << Ucscript::delay_ticks << 5 << (Ucscript::npc_frame + Actor::bow_frame) << Ucscript::delay_ticks << 3 << (Ucscript::npc_frame + Actor::standing); scr->start(); // Start next tick. state = find_podium; npc->start(2*gwin->get_std_delay(), 4000); return; } default: state = find_podium; npc->start(250); return; } } /* * Schedule change for patroling: */ void Patrol_schedule::now_what ( ) { if (sitting) // Sitting? { // Stay 5-15 secs. if ((npc->get_framenum()&0xf) == Actor::sit_frame) npc->start(250, 5000 + rand()%10000); else // Not sitting. npc->start(250, rand()%1000); sitting = false; // Continue on afterward. find_next = true; return; } if (rand() % 8 == 0) // Check for lamps, etc. if (try_street_maintenance()) return; // We no longer exist. const int PATH_SHAPE = 607; Game_object *path; if (!find_next && pathnum >= 0 && // Arrived at path? pathnum < paths.size() && (path = paths[pathnum]) != 0 && npc->distance(path) < 2) // Quality = type. (I think high bits // are flags. switch (path->get_quality()&31) { case 0: // None. break; case 1: // Wrap to 0. pathnum = -1; dir = 1; break; case 2: // Pause. break; //++++++++ case 3: // Sit. if (Sit_schedule::set_action(npc)) { sitting = true; return; } break; case 4: // Kneel at tombstone.+++++++ case 5: // Kneel+++++++++++ case 6: // Loiter.++++++ break; case 7: // Left about-face. case 8: // Right about-face. if (pathnum == 0 && dir == -1) dir = 1; else if (pathnum > 0 && dir == 1) dir = -1; // ++++Turn animations. break; case 9: // Horiz. pace.+++++++ case 10: // Vert. pace+++++++ case 11: // 50% reverse. case 12: // 50% skip next. case 13: // Hammer.++++++ case 14: // Check area. break; //++++++Implement above. case 15: // Usecode. { // Schedule so we don't get deleted. Usecode_script *scr = new Usecode_script(npc); // Don't let this script halt others, // as it messes up automaton in // SI-Freedom. (*scr) << Ucscript::dont_halt << Ucscript::usecode2 << npc->get_usecode() << static_cast(Usecode_machine::npc_proximity); scr->start(); // Start next tick. find_next = true; // THEN, find next path. npc->start(250, 500); return; } case 16: // Bow to ground. ++++Implement. case 17: // Bow from ground.+++++ case 18: // Wait for semaphore+++++ case 19: // Release semaphore+++++ case 20: // Ready weapon++++++++ case 21: // Unready weapon+++++++ case 22: // One-handed swing.+++++ case 23: // Two-handed swing. case 24: // Read++++++ case 25: // 50% wrap to 0.++++++ case 26: // Combat near?? case 27: // Repeat forever?? default: break; } pathnum += dir; // Find next path. find_next = false; // We're doing it. // Already know its location? path = pathnum >= 0 && pathnum < paths.size() ? paths[pathnum] : 0; if (!path) // No, so look around. { Game_object_vector nearby; npc->find_nearby(nearby, PATH_SHAPE, 25, 0); int best_dist = 1000; // Find closest. for (Game_object_vector::const_iterator it = nearby.begin(); it != nearby.end(); ++it) { Game_object *obj = *it; int framenum = obj->get_framenum(); int dist; if (framenum == pathnum && (dist = obj->distance(npc)) < best_dist) { // Found it. path = obj; best_dist = dist; } } if (path) // Save it. { failures = 0; paths.put(pathnum, path); } else // Turn back if at end. { failures++; dir = 1; if (pathnum == 0) // At start? Retry. { if (failures < 4) { pathnum = -1; npc->start(200, 500); return; } // After 4, fall through. } else // At end, go back to start. { pathnum = 0; path = paths.size() ? paths[0] : 0; } } if (!path) // Still failed? { // Wiggle a bit. Tile_coord pos = npc->get_tile(); int dist = failures + 2; Tile_coord delta = Tile_coord(rand()%dist - dist/2, rand()%dist - dist, 0); npc->walk_to_tile(pos + delta, gwin->get_std_delay(), failures*300); int pathcnt = paths.size(); pathnum = rand()%(pathcnt < 4 ? 4 : pathcnt); return; } } Tile_coord d = path->get_tile(); if (!npc->walk_path_to_tile(d, gwin->get_std_delay(), rand()%1000)) { // Look for free tile within 1 square. d = Map_chunk::find_spot(d, 1, npc->get_shapenum(), npc->get_framenum(), 1); if (d.tx == -1 || !npc->walk_path_to_tile(d, gwin->get_std_delay(), rand()%1000)) { // Failed. Later. npc->start(200, 2000); return; } } } /* * Schedule change for 'talk': */ void Talk_schedule::now_what ( ) { // Switch to phase 3 if we are reasonable close if (phase != 0 && phase != 4 && npc->distance(gwin->get_main_actor()) < 8) phase = 3; switch (phase) { case 0: // Start by approaching Avatar. { if (npc->distance(gwin->get_main_actor()) > 50) { // Too far? // Try a little later. npc->start(250, 5000); return; } // Aim for within 5 tiles. Actor_pathfinder_client cost(npc, 5); Actor_action *pact = Path_walking_actor_action::create_path( npc->get_tile(), gwin->get_main_actor()->get_tile(), cost); if (!pact) { #ifdef DEBUG cout << "Talk: Failed to find path for " << npc->get_name() << endl; #endif npc->follow(gwin->get_main_actor()); } else { // Walk there, and retry if // blocked. npc->set_action(pact); npc->start(400, 250); // Start walking. } phase++; return; } case 1: // Wait a second. case 2: { int dx = 1 - 2*(rand()%2); npc->walk_to_tile(npc->get_tile() + Tile_coord(dx, -dx, 0), 300, 500); // Wait til conversation is over. // if (ucmachine->get_num_faces_on_screen() == 0) // phase++; phase = 3; return; } case 3: // Talk. // Got to be reachable. if (!Fast_pathfinder_client::is_grabable( npc->get_tile(), gwin->get_main_actor()->get_tile())) { phase = 0; npc->start(250, 1000); return; } // But first face Avatar. npc->change_frame(npc->get_dir_framenum(npc->get_direction( gwin->get_main_actor()), Actor::standing)); phase++; npc->start(250, 250); // Wait another 1/4 sec. break; case 4: npc->stop(); // Stop moving. // NOTE: This could DESTROY us! if (Game::get_game_type() == SERPENT_ISLE) npc->activate(9); else npc->activate(1); // SO don't refer to any instance // variables from here on. gwin->paint(); return; default: break; } } /* * Create a loiter schedule. */ Loiter_schedule::Loiter_schedule ( Actor *n, int d // Distance in tiles to roam. ) : Schedule(n), center(n->get_tile()), dist(d) { } /* * Schedule change for 'loiter': */ void Loiter_schedule::now_what ( ) { if (rand() % 3 == 0) // Check for lamps, etc. if (try_street_maintenance()) return; // We no longer exist. int newx = center.tx - dist + rand()%(2*dist); int newy = center.ty - dist + rand()%(2*dist); // Wait a bit. npc->walk_to_tile(newx, newy, center.tz, 2*gwin->get_std_delay(), rand()%2000); } /* * Schedule change for kid games. */ void Kid_games_schedule::now_what ( ) { Tile_coord pos = npc->get_tile(); Actor *kid = 0; // Get a kid to chase. // But don't run too far. while (!kids.empty()) { kid = kids.pop(); if (npc->distance(kid) < 16) break; kid = 0; } if (kid) { Fast_pathfinder_client cost(1); Actor_action *pact = Path_walking_actor_action::create_path( pos, kid->get_tile(), cost); if (pact) { npc->set_action(pact); npc->start(100, 250); // Run. return; } } else // No more kids? Search. { Actor_vector vec; npc->find_nearby_actors(vec, c_any_shapenum, 16); for (Actor_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Actor *act = *it; if (act->get_schedule_type() == kid_games) kids.push(act); } } Loiter_schedule::now_what(); // Wander around the start. } /* * Schedule change for 'dance': */ void Dance_schedule::now_what ( ) { Tile_coord dest = center; // Pick new spot to walk to. dest.tx += -dist + rand()%(2*dist); dest.ty += -dist + rand()%(2*dist); Tile_coord cur = npc->get_tile(); int dir = static_cast(Get_direction4(cur.ty - dest.ty, dest.tx - cur.tx)); signed char frames[4]; for (int i = 0; i < 4; i++) // Spin with 'hands outstretched'. frames[i] = npc->get_dir_framenum((2*(dir + i))%8, npc->get_shapenum() == 846 ? 15 : 9); // Create action to walk. Actor_action *walk = new Path_walking_actor_action(new Zombie()); walk->walk_to_tile(npc, cur, dest); // Walk, then spin. npc->set_action(new Sequence_actor_action(walk, new Frames_actor_action(frames, sizeof(frames), 100))); npc->start(gwin->get_std_delay(), 500); // Start in 1/2 sec. } /* * Schedule change for mining/farming: */ void Tool_schedule::now_what ( ) { if (!tool) // First time? { tool = new Ireg_game_object(toolshape, 0, 0, 0, 0); // Free up both hands. Game_object *obj = npc->get_readied(Actor::rhand); if (obj) obj->remove_this(); if ((obj = npc->get_readied(Actor::lhand)) != 0) obj->remove_this(); if (!npc->add_readied(tool, Actor::lrhand)) npc->add_readied(tool, Actor::lhand); } if (rand()%4 == 0) // 1/4 time, walk somewhere. { Loiter_schedule::now_what(); return; } if (rand()%10 == 0) { Schedule_types ty = (Schedule_types) npc->get_schedule_type(); if (ty == Schedule::miner) npc->say(first_miner, last_miner); else if (ty == Schedule::farm) npc->say(first_farmer, last_farmer); } signed char frames[12]; // Use pick. int cnt = npc->get_attack_frames(toolshape, false, rand()%8, frames); npc->set_action(new Frames_actor_action(frames, cnt)); npc->start(); // Get back into time queue. } /* * End of mining/farming: */ void Tool_schedule::ending ( int ) { if (tool) tool->remove_this(); // Should safely remove from NPC. } /* * Schedule change for hounding the Avatar. */ void Hound_schedule::now_what ( ) { Actor *av = gwin->get_main_actor(); Tile_coord avpos = av->get_tile(), npcpos = npc->get_tile(); // How far away is Avatar? int dist = npcpos.distance(avpos); if (dist > 20 || dist < 3) // Too far, or close enough? { // Check again in a few seconds. npc->start(gwin->get_std_delay(), 500 + rand()%1000); return; } int newdist = 1 + rand()%2; // Aim for about 3 tiles from Avatar. Fast_pathfinder_client cost(newdist); avpos.tx += rand()%3 - 1; // Vary a bit randomly. avpos.ty += rand()%3 - 1; Actor_action *pact = Path_walking_actor_action::create_path(npcpos, avpos, cost); if (pact) { npc->set_action(pact); npc->start(gwin->get_std_delay(), 50); } else // Try again. npc->start(gwin->get_std_delay(), 2000 + rand()%3000); } /* * Schedule change for 'wander': */ void Wander_schedule::now_what ( ) { if (rand() % 2) // 1/2 time, check for lamps, etc. if (try_street_maintenance()) return; // We no longer exist. Tile_coord pos = npc->get_tile(); const int legdist = 32; // Go a ways from current pos. pos.tx += -legdist + rand()%(2*legdist); pos.ty += -legdist + rand()%(2*legdist); // Don't go too far from center. if (pos.tx - center.tx > dist) pos.tx = center.tx + dist; else if (center.tx - pos.tx > dist) pos.tx = center.tx - dist; if (pos.ty - center.ty > dist) pos.ty = center.ty + dist; else if (center.ty - pos.ty > dist) pos.ty = center.ty - dist; // Find a free spot. Tile_coord dest = Map_chunk::find_spot(pos, 4, npc->get_shapenum(), 0, 1); if (dest.tx == -1 || !npc->walk_path_to_tile(dest, gwin->get_std_delay(), rand()%2000)) // Failed? Try again a little later. npc->start(250, rand()%3000); } /* * Stand up if not already. */ static void Stand_up ( Actor *npc ) { if ((npc->get_framenum()&0xf) != Actor::standing) // Stand. npc->change_frame(Actor::standing); } /* * Create a sleep schedule. */ Sleep_schedule::Sleep_schedule ( Actor *n ) : Schedule(n), bed(0), state(0) { floorloc.tx = -1; // Set to invalid loc. if (Game::get_game_type() == BLACK_GATE) { spread0 = 3; spread1 = 16; } else // Serpent Isle. { spread0 = 7; spread1 = 20; } } /* * Schedule change for 'sleep': */ void Sleep_schedule::now_what ( ) { if (!bed && state == 0) // Always find bed. { // Find closest EW or NS bed. static int bedshapes[2] = {696, 1011}; Stand_up(npc); bed = npc->find_closest(bedshapes, 2); if (!bed && GAME_BG) // Check for Gargoyle beds. { static int gbeds[2] = {363, 312}; bed = npc->find_closest(gbeds, 2); } } int frnum = npc->get_framenum(); if ((frnum&0xf) == Actor::sleep_frame) return; // Already sleeping. switch (state) { case 0: // Find path to bed. { if (!bed) { // Just lie down at current spot. int dirbits = npc->get_framenum()&(0x30); npc->change_frame(Actor::sleep_frame|dirbits); return; } state = 1; Game_object_vector tops; // Want to find top of bed. bed->find_nearby(tops, bed->get_shapenum(), 1, 0); for (Game_object_vector::const_iterator it = tops.begin(); it != tops.end(); ++it) { Game_object *top = *it; int frnum = top->get_framenum(); if (frnum >= spread0 && frnum <= spread1) { bed = top; break; } } Tile_coord bloc = bed->get_tile(); bloc.tz -= bloc.tz%5; // Round down to floor level. Shape_info& info = bed->get_info(); bloc.tx -= info.get_3d_xtiles(bed->get_framenum())/2; bloc.ty -= info.get_3d_ytiles(bed->get_framenum())/2; // Get within 3 tiles. Actor_pathfinder_client cost(npc, 3); Actor_action *pact = Path_walking_actor_action::create_path( npc->get_tile(), bloc, cost); if (pact) npc->set_action(pact); npc->start(200); // Start walking. break; } case 1: // Go to bed. { npc->stop(); // Just to be sure. int bedshape = bed->get_shapenum(); int dir = (bedshape == 696 || bedshape == 363) ? west : north; npc->set_frame(npc->get_dir_framenum(dir, Actor::sleep_frame)); // Get bed info. Shape_info& info = bed->get_info(); Tile_coord bedloc = bed->get_tile(); floorloc = npc->get_tile(); int bedframe = bed->get_framenum();// Unmake bed. if (bedframe >= spread0 && bedframe < spread1 && (bedframe%2)) { bedframe++; bed->change_frame(bedframe); } int bedspread = (bedframe >= spread0 && !(bedframe%2)); // Put NPC on top of bed. npc->move(bedloc.tx, bedloc.ty, bedloc.tz + (bedspread ? 0 : info.get_3d_height())); state = 2; break; } default: break; } } /* * Wakeup time. */ void Sleep_schedule::ending ( int new_type // New schedule. ) { // Needed for Skara Brae. if (new_type == static_cast(wait) || // Not time to get up, Penumbra! new_type == static_cast(sleep)) return; // ++++Does this leave NPC's stuck?++++ if (bed && // Still in bed? (npc->get_framenum()&0xf) == Actor::sleep_frame && npc->distance(bed) < 8) { // Locate free spot. if (floorloc.tx == -1) // Want spot on floor. floorloc = npc->get_tile(); floorloc.tz -= floorloc.tz%5; Tile_coord pos = Map_chunk::find_spot(floorloc, 6, npc->get_shapenum(), static_cast(Actor::standing), 0); if (pos.tx == -1) // Failed? Allow change in lift. pos = Map_chunk::find_spot(floorloc, 6, npc->get_shapenum(), static_cast(Actor::standing), 1); floorloc = pos; // Make bed. int frnum = bed->get_framenum(); Actor_vector occ; // Unless there's another occupant. if (frnum >= spread0 && frnum <= spread1 && !(frnum%2) && bed->find_nearby_actors(occ, c_any_shapenum, 0) < 2) bed->set_frame(frnum - 1); } if (floorloc.tx >= 0) // Get back on floor. npc->move(floorloc); npc->set_frame(Actor::standing); gwin->set_all_dirty(); // Update all, since Av. stands up. state = 0; // In case we go back to sleep. } /* * Create a 'sit' schedule. */ Sit_schedule::Sit_schedule ( Actor *n, Game_object *ch // Chair, or null to find one. ) : Schedule(n), chair(ch), sat(false), did_barge_usecode(false) { } /* * Schedule change for 'sit': */ void Sit_schedule::now_what ( ) { int frnum = npc->get_framenum(); if (chair && (frnum&0xf) == Actor::sit_frame && npc->distance(chair) <= 1) { // Already sitting. // Seat on barge? if (!chair || chair->get_shapenum() != 292) return; if (did_barge_usecode) return; // But NOT more than once for party. did_barge_usecode = true; if (gwin->get_moving_barge()) return; // Already moving. if (!npc->is_in_party()) return; // Not a party member. Actor *party[9]; // See if all sitting. int cnt = gwin->get_party(&party[0], 1); for (int i = 0; i < cnt; i++) if ((party[i]->get_framenum()&0xf) != Actor::sit_frame) return; // Nope. // Find barge. Game_object *barge = chair->find_closest(961); if (!barge) return; int usefun = 0x634; // I hate using constants like this. did_barge_usecode = true; // Special usecode for barge pieces: // (Call with item=Avatar to avoid // running nearby barges.) ucmachine->call_usecode(usefun, gwin->get_main_actor(), Usecode_machine::double_click); return; } // Wait a while if we got up. if (!set_action(npc, chair, sat ? (2000 + rand()%3000) : 0, &chair)) npc->start(200, 5000); // Failed? Try again later. else sat = true; } /* * Action to sit in the chair NPC is in front of. */ class Sit_actor_action : public Frames_actor_action, public Game_singletons { Game_object *chair; // Chair. Tile_coord chairloc; // Original chair location. Tile_coord sitloc; // Actually where NPC sits. signed char frames[2]; static short offsets[8]; // Offsets where NPC should sit. signed char *init(Game_object *chairobj, Actor *actor) { // Frame 0 faces N, 1 E, etc. int dir = 2*(chairobj->get_framenum()%4); frames[0] = actor->get_dir_framenum(dir, Actor::bow_frame); frames[1] = actor->get_dir_framenum(dir, Actor::sit_frame); return frames; } static bool is_occupied(Tile_coord sitloc, Actor *actor) { Game_object_vector occ; // See if occupied. if (Game_object::find_nearby(occ, sitloc,c_any_shapenum, 0, 8)) for (Game_object_vector::const_iterator it = occ.begin(); it != occ.end(); ++it) { Game_object *npc = *it; if (npc == actor) continue; int frnum = npc->get_framenum() & 15; if (frnum == Actor::sit_frame || frnum == Actor::bow_frame) return true; } #if 1 /* Seems to work. Added Nov. 2, 2001 */ if (actor->get_tile() == sitloc) return false; // We're standing there. // See if spot is blocked. Tile_coord pos = sitloc;// Careful, .tz gets updated. if (Map_chunk::is_blocked(pos, actor->get_info().get_3d_height(), MOVE_WALK, 0)) return true; #endif return false; } public: Sit_actor_action(Game_object *o, Actor *actor) : chair(o), Frames_actor_action(init(o, actor), 2) { sitloc = chairloc = o->get_tile(); // Frame 0 faces N, 1 E, etc. int nsew = o->get_framenum()%4; sitloc.tx += offsets[2*nsew]; sitloc.ty += offsets[2*nsew + 1]; } Tile_coord get_sitloc() const { return sitloc; } static bool is_occupied(Game_object *chair, Actor *actor) { int dir = 2*(chair->get_framenum()%4); return is_occupied(chair->get_tile() + Tile_coord(offsets[dir], offsets[dir + 1], 0), actor); } // Handle time event. virtual int handle_event(Actor *actor); }; // Offsets where NPC should sit: short Sit_actor_action::offsets[8] = {0,-1, 1,0, 0,1, -1,0}; /* * Show frame for sitting down. */ int Sit_actor_action::handle_event ( Actor *actor ) { if (get_index() == 0) // First time? { if (is_occupied(sitloc, actor)) return 0; // Abort. if (chair->get_tile() != chairloc) { // Chair was moved! actor->say(first_chair_thief, last_chair_thief); return 0; } } return Frames_actor_action::handle_event(actor); } /* * Is chair occupied, other than by 'actor'? */ bool Sit_schedule::is_occupied ( Game_object *chairobj, Actor *actor ) { return Sit_actor_action::is_occupied(chairobj, actor); } /* * Set up action. * * Output: false if couldn't find a free chair. */ bool Sit_schedule::set_action ( Actor *actor, Game_object *chairobj, // May be 0 to find it. int delay, // Msecs. to delay. Game_object **chair_found // ->chair ret'd if not NULL. ) { static int chairshapes[] = {873,292}; Game_object_vector chairs; if (chair_found) *chair_found = 0; // Init. in case we fail. if (!chairobj) // Find chair if not given. { actor->find_closest(chairs, chairshapes, sizeof(chairs)/sizeof(chairs[0])); for (Game_object_vector::const_iterator it = chairs.begin(); it != chairs.end(); ++it) if (!Sit_actor_action::is_occupied((*it), actor)) { // Found an unused one. chairobj = *it; break; } if (!chairobj) return false; } else if (Sit_actor_action::is_occupied(chairobj, actor)) return false; // Given chair is occupied. Sit_actor_action *act = new Sit_actor_action(chairobj, actor); // Walk there, then sit. set_action_sequence(actor, act->get_sitloc(), act, false, delay); if (chair_found) *chair_found = chairobj; return true; } /* * Desk work. */ Desk_schedule::Desk_schedule ( Actor *n ) : Schedule(n), chair(0) { } /* * Schedule change for 'desk work': */ void Desk_schedule::now_what ( ) { if (!chair) // No chair found yet. { static int desks[2] = {283, 407}; static int chairs[2] = {873,292}; Stand_up(npc); Game_object *desk = npc->find_closest(desks, 2); if (desk) chair = desk->find_closest(chairs, 2); if (!chair) // Failed. { // Try again in a few seconds. npc->start(200, 5000); return; } } int frnum = npc->get_framenum(); if ((frnum&0xf) != Actor::sit_frame) { if (!Sit_schedule::set_action(npc, chair, 0)) { chair = 0; // Look for any nearby chair. npc->start(200, 5000); // Failed? Try again later. } else npc->start(250, 0); } else // Stand up a second. { signed char frames[3]; frames[0] = npc->get_dir_framenum(Actor::standing); frames[1] = npc->get_dir_framenum(Actor::bow_frame); frames[2] = npc->get_dir_framenum(Actor::sit_frame); npc->set_action(new Frames_actor_action(frames, sizeof(frames)/sizeof(frames[0]))); npc->start(250, 10000 + rand()%5000); } } /* * A class for indexing the perimeter of a rectangle. */ class Perimeter { Rectangle perim; // Outside given rect. int sz; // # squares. public: Perimeter(Rectangle &r) : sz(2*r.w + 2*r.h + 4) { perim = r; perim.enlarge(1); } int size() { return sz; } // Get i'th tile. void get(int i, Tile_coord& ptile, Tile_coord& atile); #if 0 static void test() { Rectangle r(10, 10, 3, 4); Perimeter p(r); int cnt = p.size(); for (int i = 0; i < cnt; i++) { Tile_coord pt, at; p.get(i, pt, at); cout << "pt.tx = " << pt.tx << ", pt.ty = " << pt.ty << ", at.tx = " << at.tx << ", at.ty = " << at.ty << endl; } } #endif }; /* * Get the i'th perimeter tile and the tile in the original rect. * that's adjacent. */ void Perimeter::get ( int i, Tile_coord& ptile, // Perim. tile returned. Tile_coord& atile // Adjacent tile returned. ) { if (i < perim.w - 1) // Spiral around from top-left. { ptile = Tile_coord(perim.x + i, perim.y, 0); atile = ptile + Tile_coord(!i ? 1 : 0, 1, 0); return; } i -= perim.w - 1; if (i < perim.h - 1) { ptile = Tile_coord(perim.x + perim.w - 1, perim.y + i, 0); atile = ptile + Tile_coord(-1, !i ? 1 : 0, 0); return; } i -= perim.h - 1; if (i < perim.w - 1) { ptile = Tile_coord(perim.x + perim.w - 1 - i, perim.y + perim.h - 1, 0); atile = ptile + Tile_coord(!i ? -1 : 0, -1, 0); return; } i -= perim.w - 1; { ptile = Tile_coord(perim.x, perim.y + perim.h - 1 - i, 0); atile = ptile + Tile_coord(1, !i ? -1 : 0, 0); return; } // Bad index if here. get(i%sz, ptile, atile); } /* * Initialize. */ void Lab_schedule::init ( ) { chair = book = 0; cauldron = npc->find_closest(995, 20); // Find 'lab' tables. npc->find_nearby(tables, 1003, 20, 0); npc->find_nearby(tables, 1018, 20, 0); int cnt = tables.size(); // Look for book, chair. for (int i = 0; (!book || !chair) && i < cnt; i++) { static int chairs[2] = {873,292}; Game_object *table = tables[i]; Rectangle foot = table->get_footprint(); // Book on table? if (!book && (book = table->find_closest(642, 4)) != 0) { Tile_coord p = book->get_tile(); if (!foot.has_point(p.tx, p.ty)) book = 0; } if (!chair) chair = table->find_closest(chairs, 2, 4); } } /* * Create lab schedule. */ Lab_schedule::Lab_schedule ( Actor *n ) : Schedule(n), state(start) { init(); } /* * Lab work. */ void Lab_schedule::now_what ( ) { Tile_coord npcpos = npc->get_tile(); int delay = 100; // 1/10 sec. to next action. // Often want to get within 1 tile. Actor_pathfinder_client cost(npc, 1); switch (state) { case start: default: { if (!cauldron) { // Try looking again. init(); if (!cauldron) // Again a little later. delay = 6000; break; } int r = rand()%5; // Pick a state. if (!r) // Sit less often. state = sit_down; else state = r <= 2 ? walk_to_cauldron : walk_to_table; break; } case walk_to_cauldron: { state = start; // In case we fail. if (!cauldron) break; Actor_action *pact = Path_walking_actor_action::create_path( npcpos, cauldron->get_tile(), cost); if (pact) { npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action(cauldron, 200))); state = use_cauldron; } break; } case use_cauldron: { int dir = npc->get_direction(cauldron); // Set random frame (skip last frame). cauldron->change_frame(rand()%(cauldron->get_num_frames() -1)); npc->change_frame( npc->get_dir_framenum(dir, Actor::bow_frame)); int r = rand()%5; state = !r ? use_cauldron : (r <= 2 ? sit_down : walk_to_table); break; } case sit_down: if (!chair || !Sit_schedule::set_action(npc, chair, 200)) state = start; else state = read_book; break; case read_book: { state = stand_up; if (!book || npc->distance(book) > 4) break; // Read a little while. delay = 1000 + 1000*(rand()%5); // Open book. int frnum = book->get_framenum(); book->change_frame(frnum - frnum%3); break; } case stand_up: { if (book && npc->distance(book) < 4) { // Close book. int frnum = book->get_framenum(); book->change_frame(frnum - frnum%3 + 1); } state = start; break; } case walk_to_table: { state = start; // In case we fail. int ntables = tables.size(); if (!ntables) break; Game_object *table = tables[rand()%ntables]; Rectangle r = table->get_footprint(); Perimeter p(r); // Find spot adjacent to table. Tile_coord spot; // Also get closest spot on table. p.get(rand()%p.size(), spot, spot_on_table); Actor_pathfinder_client cost0(npc, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, spot, cost0); if (!pact) break; // Failed. Shape_info& info = table->get_info(); spot_on_table.tz += info.get_3d_height(); npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action(spot_on_table, 200))); state = use_potion; break; } case use_potion: { state = start; Exult_vector potions; Game_object::find_nearby(potions, spot_on_table, 340, 0, 0); if (potions.size()) // Found a potion. Remove it. { gwin->add_dirty(potions[0]); potions[0]->remove_this(); } else // Create potion if spot is empty. { Tile_coord t = Map_chunk::find_spot(spot_on_table, 0, 340, 0, 0); if (t.tx != -1 && t.tz == spot_on_table.tz) { // create a potion randomly, but don't use the last frame int nframes = ShapeID(340, 0).get_num_frames() - 1; Game_object *p = gmap->create_ireg_object( ShapeID::get_info(340), 340, rand()%nframes, 0, 0, 0); p->move(t); } } signed char frames[2]; int dir = npc->get_direction(spot_on_table); // Reach out hand: frames[0] = npc->get_dir_framenum(dir, 1); frames[1] = npc->get_dir_framenum(dir, Actor::standing); npc->set_action(new Frames_actor_action(frames, 2)); break; } } npc->start(gwin->get_std_delay(), delay); // Back in queue. } /* * Schedule change for 'shy': */ void Shy_schedule::now_what ( ) { Actor *av = gwin->get_main_actor(); Tile_coord avpos = av->get_tile(), npcpos = npc->get_tile(); // How far away is Avatar? int dist = npcpos.distance(avpos); if (dist > 10) // Far enough? { // Check again in a few seconds. if (rand()%3) // Just wait. npc->start(250, 1000 + rand()%1000); else // Sometimes wander. npc->walk_to_tile( Tile_coord(npcpos.tx + rand()%6 - 3, npcpos.ty + rand()%6 - 3, npcpos.tz)); return; } // Get deltas. int dx = npcpos.tx - avpos.tx, dy = npcpos.ty - avpos.ty; int adx = dx < 0 ? -dx : dx; int ady = dy < 0 ? -dy : dy; // Which is farthest? int farthest = adx < ady ? ady : adx; int factor = farthest < 2 ? 9 : farthest < 4 ? 4 : farthest < 7 ? 2 : 1; // Walk away. Tile_coord dest = npcpos + Tile_coord(dx*factor, dy*factor, 0); Tile_coord delta = Tile_coord(rand()%3, rand()%3, 0); dest = dest + delta; Monster_pathfinder_client cost(npc, dest, 4); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, dest, cost); if (pact) // Found path? { npc->set_action(pact); npc->start(200, 100 + rand()%200); // Start walking. } else // Try again in a couple secs. npc->start(250, 500 + rand()%1000); } /* * Create a 'waiter' schedule. */ Waiter_schedule::Waiter_schedule ( Actor *n ) : Schedule(n), first(1), startpos(n->get_tile()), customer(0) { } /* * Get a new customer & walk to a prep. table. */ void Waiter_schedule::get_customer ( ) { if (customers.empty()) // Got to search? { Actor_vector vec; // Look within 32 tiles; npc->find_nearby_actors(vec, c_any_shapenum, 32); for (Actor_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { // Filter them. Actor *each = (Actor *) *it; if (each->get_schedule_type() == Schedule::eat_at_inn) customers.push(each); } } if (!customers.empty()) customer = customers.pop(); npc->say(first_waiter_ask, last_waiter_ask); if (prep_tables.size()) // Walk to a 'prep' table. { Game_object *table = prep_tables[rand()%prep_tables.size()]; Tile_coord pos = Map_chunk::find_spot( table->get_tile(), 1, npc); if (pos.tx != -1 && npc->walk_path_to_tile(pos, gwin->get_std_delay(), 1000 + rand()%1000)) return; } const int dist = 8; // Bad luck? Walk randomly. int newx = startpos.tx - dist + rand()%(2*dist); int newy = startpos.ty - dist + rand()%(2*dist); npc->walk_to_tile(newx, newy, startpos.tz, 2*gwin->get_std_delay(), rand()%2000); } /* * Find tables and categorize them. */ void Waiter_schedule::find_tables ( int shapenum ) { Game_object_vector vec; npc->find_nearby(vec, shapenum, 32, 0); int floor = npc->get_lift()/5; // Make sure it's on same floor. for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { Game_object *table = *it; if (table->get_lift()/5 != floor) continue; Game_object_vector chairs; // No chairs by it? if (!table->find_nearby(chairs, 873, 3, 0) && !table->find_nearby(chairs, 292, 3, 0)) prep_tables.append(table); else eating_tables.append(table); } } /* * Find serving spot for a customer. * * Output: Plate if found, with spot set. Plate is created if needed. */ Game_object *Waiter_schedule::find_serving_spot ( Tile_coord& spot ) { Game_object_vector plates; // First look for a nearby plate. Game_object *plate = 0; int cnt = npc->find_nearby(plates, 717, 1, 0); if (!cnt) cnt = npc->find_nearby(plates, 717, 2, 0); int floor = npc->get_lift()/5; // Make sure it's on same floor. for (Game_object_vector::const_iterator it = plates.begin(); it != plates.end(); ++it) { plate = *it; if (plate->get_lift()/5 == floor) { spot = plate->get_tile(); spot.tz++; // Just above plate. return plate; } } Tile_coord cpos = customer->get_tile(); // Blame MSVC { // Go through tables. for (Game_object_vector::const_iterator it = eating_tables.begin(); it != eating_tables.end(); ++it) { Game_object *table = *it; Rectangle foot = table->get_footprint(); if (foot.distance(cpos.tx, cpos.ty) > 2) continue; // Found it. spot = cpos; // Start here. // East/West of table? if (cpos.ty >= foot.y && cpos.ty < foot.y + foot.h) spot.tx = cpos.tx <= foot.x ? foot.x : foot.x + foot.w - 1; else // North/south. spot.ty = cpos.ty <= foot.y ? foot.y : foot.y + foot.h - 1; if (foot.has_point(spot.tx, spot.ty)) { // Passes test. Shape_info& info = table->get_info(); spot.tz = table->get_lift() + info.get_3d_height(); plate = gmap->create_ireg_object(717, 0); plate->move(spot); spot.tz++; // Food goes above plate. return plate; } } } return 0; // Failed. } /* * Schedule change for 'waiter': */ void Waiter_schedule::now_what ( ) { if (rand() % 4 == 0) // Check for lamps, etc. if (try_street_maintenance()) return; // We no longer exist. if (first) // First time? { first = 0; // Find tables. find_tables(971); find_tables(633); find_tables(847); find_tables(1003); find_tables(1018); find_tables(890); find_tables(964); find_tables(333); } int dist = customer ? npc->distance(customer) : 5000; if (dist > 32) // Need a new customer? { get_customer(); // Find one, and walk to a prep. table. return; } if (dist < 3) // Close enough to customer? { Game_object_vector foods; if (customer->find_nearby(foods, 377, 2, 0) > 0) { if (rand()%4) npc->say(first_waiter_banter, last_waiter_banter); } else // Needs food. { Game_object *food = npc->get_readied(Actor::lhand); Tile_coord spot; if (food && food->get_shapenum() == 377 && find_serving_spot(spot)) { npc->change_frame(npc->get_dir_framenum( npc->get_direction(customer), Actor::standing)); npc->remove(food); food->set_invalid(); food->move(spot); if (rand()%3) npc->say(first_waiter_serve, last_waiter_serve); } } customer = 0; // Done with this one. npc->start(250, rand()%3000); return; } // Walk to customer with food. if (!npc->get_readied(Actor::lhand)) { // Acquire some food. int nfoods = ShapeID(377, 0).get_num_frames(); int frame = rand()%nfoods; Game_object *food = new Ireg_game_object(377, frame, 0, 0, 0); npc->add_readied(food, Actor::lhand); } Tile_coord dest = Map_chunk::find_spot(customer->get_tile(), 3, npc); if (dest.tx != -1 && npc->walk_path_to_tile(dest, gwin->get_std_delay(), rand()%1000)) return; // Walking there. npc->start(200, 2000 + rand()%4000); // Failed so try again later. } /* * Waiter schedule is done. */ void Waiter_schedule::ending ( int new_type // New schedule. ) { // Remove what he/she is carrying. Game_object *obj = npc->get_readied(Actor::lhand); if (obj) obj->remove_this(); obj = npc->get_readied(Actor::rhand); if (obj) obj->remove_this(); } /* * Sew/weave schedule. */ Sew_schedule::Sew_schedule ( Actor *n ) : Schedule(n), state(get_wool), bale(0), spinwheel(0), chair(0), spindle(0), loom(0), cloth(0), work_table(0), wares_table(0), sew_clothes_cnt(0) { } /* * Sew/weave. */ void Sew_schedule::now_what ( ) { Tile_coord npcpos = npc->get_tile(); // Often want to get within 1 tile. Actor_pathfinder_client cost(npc, 1); switch (state) { case get_wool: { if (spindle) // Clean up any remainders. spindle->remove_this(); if (cloth) cloth->remove_this(); cloth = spindle = 0; npc->remove_quantity(2, 654, c_any_qual, c_any_framenum); npc->remove_quantity(2, 851, c_any_qual, c_any_framenum); bale = npc->find_closest(653); if (!bale) // Just skip this step. { state = sit_at_wheel; break; } Actor_action *pact = Path_walking_actor_action::create_path( npcpos, bale->get_tile(), cost); if (pact) npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(bale, 250), new Pickup_actor_action(bale, bale->get_tile(), 250))); state = sit_at_wheel; break; } case sit_at_wheel: chair = npc->find_closest(873); if (!chair || !Sit_schedule::set_action(npc, chair, 200)) { // uh-oh... try again in a few seconds npc->start(250, 2500); return; } state = spin_wool; break; case spin_wool: // Cycle spinning wheel 8 times. spinwheel = npc->find_closest(651); if (!spinwheel) { // uh-oh... try again in a few seconds? npc->start(250, 2500); return; } npc->set_action(new Object_animate_actor_action(spinwheel, 8, 200)); state = get_thread; break; case get_thread: { Tile_coord t = Map_chunk::find_spot( spinwheel->get_tile(), 1, 654, 0); if (t.tx != -1) // Space to create thread? { spindle = new Ireg_game_object(654, 0, 0, 0); spindle->move(t); gwin->add_dirty(spindle); npc->set_action( new Pickup_actor_action(spindle, 250)); } state = weave_cloth; break; } case weave_cloth: { if (spindle) // Should be held by NPC. spindle->remove_this(); spindle = 0; loom = npc->find_closest(261); if (!loom) // No loom found? { state = get_wool; break; } Tile_coord lpos = loom->get_tile() + Tile_coord(-1, 0, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, lpos, cost); if (pact) npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action(loom, 250), new Object_animate_actor_action(loom, 4, 200))); state = get_cloth; break; } case get_cloth: { Tile_coord t = Map_chunk::find_spot(loom->get_tile(), 1, 851, 0); if (t.tx != -1) // Space to create it? { cloth = new Ireg_game_object(851, rand()%2, 0, 0); cloth->move(t); gwin->add_dirty(cloth); npc->set_action( new Pickup_actor_action(cloth, 250)); } state = to_work_table; break; } case to_work_table: { work_table = npc->find_closest(971); if (!work_table || !cloth) { state = get_wool; break; } Tile_coord tpos = work_table->get_tile() + Tile_coord(1, -2, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); // Find where to put cloth. Rectangle foot = work_table->get_footprint(); Shape_info& info = work_table->get_info(); Tile_coord cpos(foot.x + foot.w/2, foot.y + foot.h/2, work_table->get_lift() + info.get_3d_height()); if (pact) npc->set_action(new Sequence_actor_action(pact, new Face_pos_actor_action( work_table, 250), new Pickup_actor_action(cloth, cpos, 250))); state = set_to_sew; break; } case set_to_sew: { Game_object *shears = npc->get_readied(Actor::lhand); if (shears && shears->get_shapenum() != 698) { // Something's not right. shears->remove_this(); shears = 0; } if (!shears) { // Shears on table? Game_object_vector vec; if (npc->find_nearby(vec, 698, 3, 0)) { shears = vec[0]; gwin->add_dirty(shears); shears->remove_this(1); } else shears = new Ireg_game_object(698, 0, 0, 0); npc->add_readied(shears, Actor::lhand); } state = sew_clothes; sew_clothes_cnt = 0; break; } case sew_clothes: { int dir = npc->get_direction(cloth); signed char frames[5]; int nframes = npc->get_attack_frames(698, false, dir, frames); npc->set_action(new Frames_actor_action(frames, nframes)); sew_clothes_cnt++; if (sew_clothes_cnt > 1 && sew_clothes_cnt < 5) { int num_cloth_frames = ShapeID(851, 0).get_num_frames(); cloth->change_frame(rand()%num_cloth_frames); } else if (sew_clothes_cnt == 5) { gwin->add_dirty(cloth); Tile_coord pos = cloth->get_tile(); cloth->remove_this(1); // Top or pants. int shnum = GAME_SI ? 403 : (rand()%2 ? 738 : 249); cloth->set_shape(shnum); int nframes = ShapeID(shnum, 0).get_num_frames(); cloth->set_frame(rand()%nframes); cloth->move(pos); state = get_clothes; } break; } case get_clothes: { Game_object *shears = npc->get_readied(Actor::lhand); if (shears) { Tile_coord pos = cloth->get_tile(); npc->set_action(new Sequence_actor_action( new Pickup_actor_action(cloth, 250), new Pickup_actor_action(shears, pos, 250))); } else { // ++++ maybe create shears? anyway, leaving this till after // possible/probable schedule system rewrite npc->set_action(new Pickup_actor_action(cloth, 250)); } state = display_clothes; break; } case display_clothes: { state = done; wares_table = npc->find_closest(890); if (!wares_table) { cloth->remove_this(); cloth = 0; break; } Tile_coord tpos = wares_table->get_tile() + Tile_coord(1, -2, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); // Find where to put cloth. Rectangle foot = wares_table->get_footprint(); Shape_info& info = wares_table->get_info(); Tile_coord cpos(foot.x + rand()%foot.w, foot.y + rand()%foot.h, wares_table->get_lift() + info.get_3d_height()); if (pact) npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(cloth, cpos, 250))); cloth = 0; // Leave it be. break; } case done: // Just put down clothing. { state = get_wool; Game_object_vector vec; // Don't create too many. int cnt = 0; if (GAME_SI) cnt += npc->find_nearby(vec, 403, 4, 0); else // BG shapes. { cnt += npc->find_nearby(vec, 738, 4, 0); cnt += npc->find_nearby(vec, 249, 4, 0); } if (cnt > 5) { Game_object *obj = vec[rand()%cnt]; gwin->add_dirty(obj); obj->remove_this(); } break; } default: // Back to start. state = get_wool; break; } npc->start(250, 100); // Back in queue. } /* * Sewing schedule is done. */ void Sew_schedule::ending ( int new_type // New schedule. ) { // Remove shears. Game_object *obj = npc->get_readied(Actor::lhand); if (obj) obj->remove_this(); if (cloth) // Don't leave cloth lying around. { if (!cloth->get_owner()) gwin->add_dirty(cloth); cloth->remove_this(); cloth = 0; } } /* * Bake bread/pastries * * TODO: fix for SI tables... (specifically in Moonglow) */ Bake_schedule::Bake_schedule(Actor *n) : Schedule(n), state(to_flour), oven(0), worktable(0), displaytable(0), flourbag(0), dough(0), dough_in_oven(0), baked_count(0) { } void Bake_schedule::now_what() { Tile_coord npcpos = npc->get_tile(); Actor_pathfinder_client cost(npc, 1); int delay = 100; switch (state) { case to_flour: { Game_object_vector items; npc->find_nearby(items, npcpos, 863, -1, 0, c_any_qual, 0); npc->find_nearby(items, npcpos, 863, -1, 0, c_any_qual, 13); npc->find_nearby(items, npcpos, 863, -1, 0, c_any_qual, 14); if (items.empty()) { state = to_table; break; } int nr = rand()%items.size(); flourbag = items[nr]; Tile_coord tpos = flourbag->get_tile(); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); if (pact) { npc->set_action(pact); } else { // just ignore it state = to_table; break; } state = get_flour; break; } case get_flour: { if (!flourbag) { // what are we doing here then? back to start state = to_flour; break; } int dir = npc->get_direction(flourbag); npc->change_frame( npc->get_dir_framenum(dir,Actor::bow_frame)); if (flourbag->get_framenum() != 0) flourbag->change_frame(0); delay = 750; state = to_table; break; } case to_table: { Game_object *table1 = npc->find_closest(1003); Game_object *table2 = npc->find_closest(1018); if (!table1) worktable = table2; else if (!table2) worktable = table1; else if (table1->distance(npc) < table2->distance(npc)) worktable = table1; else worktable = table2; if (!worktable) worktable = npc->find_closest(1018); if (!worktable) { // problem... try again in a few seconds delay = 2500; state = to_flour; break; } // Find where to put dough. Rectangle foot = worktable->get_footprint(); Shape_info& info = worktable->get_info(); Tile_coord cpos(foot.x + rand()%foot.w, foot.y + rand()%foot.h, worktable->get_lift() + info.get_3d_height()); Tile_coord tablepos = cpos; cpos.tz = 0; Actor_action *pact = Path_walking_actor_action::create_path( npcpos, cpos, cost); if (pact) { if (dough) { dough->remove_this(); dough = 0; } if (Game::get_game_type() == SERPENT_ISLE) dough = new Ireg_game_object(863, 16, 0, 0); else dough = new Ireg_game_object(658, 0, 0, 0); npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(dough,tablepos,250))); } else { // not good... try again delay = 2500; state = to_flour; break; } state = make_dough; break; } case make_dough: { if (!dough) { // better try again... delay = 2500; state = to_table; break; } int dir = npc->get_direction(dough); signed char fr[2]; fr[0] = npc->get_dir_framenum(dir, 3); fr[1] = npc->get_dir_framenum(dir, 0); npc->set_action(new Sequence_actor_action( new Frames_actor_action(fr, 2, 500), ((Game::get_game_type() == SERPENT_ISLE) ? new Frames_actor_action((signed char *)"\x11",1,250,dough) : new Frames_actor_action((signed char *)"\x01",1,250,dough)), new Frames_actor_action(fr, 2, 500), ((Game::get_game_type() == SERPENT_ISLE) ? new Frames_actor_action((signed char *)"\x12",1,250,dough) : new Frames_actor_action((signed char *)"\x02",1,250,dough)) )); state = remove_from_oven; break; } case remove_from_oven: { if (!dough_in_oven) { // nothing in oven yet state = get_dough; break; } oven = npc->find_closest(831); if (!oven) { // this really shouldn't happen... dough_in_oven->remove_this(); dough_in_oven = 0; delay = 2500; state = to_table; break; } gwin->add_dirty(dough_in_oven); dough_in_oven->set_shape(377); dough_in_oven->set_frame(rand()%7); gwin->add_dirty(dough_in_oven); Tile_coord tpos = oven->get_tile() + Tile_coord(1, 1, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); if (pact) { npc->set_action(new Sequence_actor_action( pact, new Pickup_actor_action(dough_in_oven, 250))); } else { // just pick it up npc->set_action( new Pickup_actor_action(dough_in_oven, 250)); } state = display_wares; break; } case display_wares: { if (!dough_in_oven) { // try again delay = 2500; state = to_flour; break; } displaytable = npc->find_closest(633); if (!displaytable) { // uh-oh... dough_in_oven->remove_this(); dough_in_oven = 0; delay = 2500; state = to_flour; break; } baked_count++; Tile_coord tpos = displaytable->get_tile(); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); // Find where to put cloth. Rectangle foot = displaytable->get_footprint(); Shape_info& info = displaytable->get_info(); Tile_coord cpos(foot.x + rand()%foot.w, foot.y + rand()%foot.h, displaytable->get_lift() + info.get_3d_height()); if (pact) { if (baked_count <= 5) { npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(dough_in_oven, cpos, 250))); } else { npc->set_action(pact); dough_in_oven->remove_this(); } dough_in_oven = 0; } else { // just make it vanish dough_in_oven->remove_this(); dough_in_oven = 0; } state = get_dough; break; } case get_dough: { if (!dough) { // try again delay = 2500; state = to_flour; break; } oven = npc->find_closest(831); if (!oven) { // wait a while delay = 2500; state = to_flour; break; } Tile_coord tpos = dough->get_tile(); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); if (pact) { npc->set_action(new Sequence_actor_action( pact, new Pickup_actor_action(dough, 250))); } else { // just pick it up npc->set_action(new Pickup_actor_action(dough, 250)); } state = put_in_oven; break; } case put_in_oven: { if (!dough) { // try again delay = 2500; state = to_flour; break; } oven = npc->find_closest(831); if (!oven) { // oops... retry dough->remove_this(); dough = 0; delay = 2500; state = to_table; break; } Tile_coord tpos = oven->get_tile() + Tile_coord(1, 1, 0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); Rectangle foot = oven->get_footprint(); Shape_info& info = oven->get_info(); Tile_coord cpos(foot.x + 1, foot.y, oven->get_lift() + info.get_3d_height()); if (pact) { npc->set_action(new Sequence_actor_action( pact, new Pickup_actor_action(dough, cpos, 250))); dough_in_oven = dough; dough = 0; } else { dough->remove_this(); dough = 0; } state = to_flour; break; } } npc->start(250, delay); // Back in queue. } void Bake_schedule::ending(int new_type) { if (dough) { dough->remove_this(); dough = 0; } if (dough_in_oven) { dough_in_oven->remove_this(); dough_in_oven = 0; } } /* * Notify that an object is no longer present. */ void Bake_schedule::notify_object_gone(Game_object *obj) { if (obj == dough) // Someone stole the dough! dough = 0; if (obj == dough_in_oven) dough_in_oven = 0; } /* * Blacksmith. * * Note: the original kept the tongs & hammer, and put them on a nearby table */ Forge_schedule::Forge_schedule(Actor *n) : Schedule(n), state(put_sword_on_firepit), tongs(0), hammer(0), blank(0), firepit(0), anvil(0), trough(0), bellows(0) { } void Forge_schedule::now_what ( ) { Tile_coord npcpos = npc->get_tile(); // Often want to get within 1 tile. Actor_pathfinder_client cost(npc, 1); switch (state) { case put_sword_on_firepit: { if (!blank) { blank = npc->find_closest(668); //TODO: go and get it... } if (!blank) blank = new Ireg_game_object(668, 0, 0, 0); firepit = npc->find_closest(739); if (!firepit) { // uh-oh... try again in a few seconds npc->start(250, 2500); return; } Tile_coord tpos = firepit->get_tile(); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); Rectangle foot = firepit->get_footprint(); Shape_info& info = firepit->get_info(); Tile_coord bpos(foot.x + foot.w/2 + 1, foot.y + foot.h/2, firepit->get_lift() + info.get_3d_height()); if (pact) { npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(blank, bpos, 250))); } else { npc->set_action( new Pickup_actor_action(blank, bpos, 250)); } state = use_bellows; break; } case use_bellows: { bellows = npc->find_closest(431); firepit = npc->find_closest(739); if (!bellows || !firepit || !blank) { // uh-oh... try again in a few second npc->start(250, 2500); state = put_sword_on_firepit; return; } Tile_coord tpos = bellows->get_tile() + Tile_coord(3,0,0); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); Actor_action **a = new Actor_action*[35]; a[0] = pact; a[1] = new Face_pos_actor_action(bellows, 250); a[2] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[3] = new Object_animate_actor_action(bellows, 3, 1, 300); a[4] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[5] = new Frames_actor_action((signed char *)"\x01", 1, 0, firepit); a[6] = new Frames_actor_action((signed char *)"\x01", 1, 0, blank); a[7] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[8] = new Object_animate_actor_action(bellows, 3, 1, 300); a[9] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[10] = new Frames_actor_action((signed char *)"\x02", 1, 0, blank); a[11] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[12] = new Object_animate_actor_action(bellows, 3, 1, 300); a[13] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[14] = new Frames_actor_action((signed char *)"\x02", 1, 0, firepit); a[15] = new Frames_actor_action((signed char *)"\x03", 1, 0, blank); a[16] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[17] = new Object_animate_actor_action(bellows, 3, 1, 300); a[18] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[19] = new Frames_actor_action((signed char *)"\x03", 1, 0, firepit); a[20] = new Frames_actor_action((signed char *)"\x04", 1, 0, blank); a[21] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[22] = new Object_animate_actor_action(bellows, 3, 1, 300); a[23] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[24] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[25] = new Object_animate_actor_action(bellows, 3, 1, 300); a[26] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[27] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[28] = new Object_animate_actor_action(bellows, 3, 1, 300); a[29] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[30] = new Frames_actor_action((signed char *)"\x2b", 1, 0); a[31] = new Object_animate_actor_action(bellows, 3, 1, 300); a[32] = new Frames_actor_action((signed char *)"\x20", 1, 0); a[33] = new Frames_actor_action((signed char *)"\x00", 1, 0, bellows); a[34] = 0; npc->set_action(new Sequence_actor_action(a)); state = get_tongs; break; } case get_tongs: { #if 0 if (!tongs) { tongs = npc->find_closest(994); //TODO: go and get it... } #endif if (!tongs) tongs = new Ireg_game_object(994, 0, 0, 0); npc->add_dirty(); npc->add_readied(tongs, Actor::rhand); npc->add_dirty(); state = sword_on_anvil; break; } case sword_on_anvil: { anvil = npc->find_closest(991); firepit = npc->find_closest(739); if (!anvil || !firepit || !blank) { // uh-oh... try again in a few second npc->start(250, 2500); state = put_sword_on_firepit; return; } Tile_coord tpos = firepit->get_tile(); Actor_action *pact = Path_walking_actor_action::create_path( npcpos, tpos, cost); Tile_coord tpos2 = anvil->get_tile() + Tile_coord(0,1,0); Actor_action *pact2 = Path_walking_actor_action::create_path( tpos, tpos2, cost); Rectangle foot = anvil->get_footprint(); Shape_info& info = anvil->get_info(); Tile_coord bpos(foot.x + 2, foot.y, anvil->get_lift() + info.get_3d_height()); if (pact && pact2) { npc->set_action(new Sequence_actor_action(pact, new Pickup_actor_action(blank, 250), pact2, new Pickup_actor_action(blank, bpos, 250))); } else { npc->set_action(new Sequence_actor_action( new Pickup_actor_action(blank, 250), new Pickup_actor_action(blank, bpos, 250))); } state = get_hammer; break; } case get_hammer: { #if 0 if (!hammer) { hammer = npc->find_closest(623); //TODO: go and get it... } #endif if (!hammer) hammer = new Ireg_game_object(623, 0, 0, 0); npc->add_dirty(); if (tongs) { tongs->remove_this(); tongs = 0; } npc->add_readied(hammer, Actor::rhand); npc->add_dirty(); state = use_hammer; break; } case use_hammer: { anvil = npc->find_closest(991); firepit = npc->find_closest(739); if (!anvil || !firepit || !blank) { // uh-oh... try again in a few seconds npc->start(250, 2500); state = put_sword_on_firepit; return; } signed char frames[12]; int cnt = npc->get_attack_frames(623, false, 0, frames); npc->set_action(new Frames_actor_action(frames, cnt)); Actor_action **a = new Actor_action*[10]; a[0] = new Frames_actor_action(frames, cnt); a[1] = new Frames_actor_action((signed char *)"\x03", 1, 0, blank); a[2] = new Frames_actor_action((signed char *)"\x02", 1, 0, firepit); a[3] = new Frames_actor_action(frames, cnt); a[4] = new Frames_actor_action((signed char *)"\x02", 1, 0, blank); a[5] = new Frames_actor_action((signed char *)"\x01", 1, 0, firepit); a[6] = new Frames_actor_action(frames, cnt); a[7] = new Frames_actor_action((signed char *)"\x01", 1, 0, blank); a[8] = new Frames_actor_action((signed char *)"\x00", 1, 0, firepit); a[9] = 0; npc->set_action(new Sequence_actor_action(a)); state = walk_to_trough; break; } case walk_to_trough: { npc->add_dirty(); if (hammer) { hammer->remove_this(); hammer = 0; } npc->add_dirty(); trough = npc->find_closest(719); if (!trough) { // uh-oh... try again in a few seconds npc->start(250, 2500); state = put_sword_on_firepit; return; } if (trough->get_framenum() == 0) { Tile_coord tpos = trough->get_tile() + Tile_coord(0,2,0); Actor_action *pact = Path_walking_actor_action:: create_path(npcpos, tpos, cost); npc->set_action(pact); state = fill_trough; break; } state = get_tongs2; break; } case fill_trough: { trough = npc->find_closest(719); if (!trough) { // uh-oh... try again in a few seconds npc->start(250, 2500); state = put_sword_on_firepit; return; } int dir = npc->get_direction(trough); trough->change_frame(3); npc->change_frame( npc->get_dir_framenum(dir, Actor::bow_frame)); state = get_tongs2; break; } case get_tongs2: { #if 0 if (!tongs) { tongs = npc->find_closest(994); //TODO: go and get it... } #endif if (!tongs) tongs = new Ireg_game_object(994, 0, 0, 0); npc->add_dirty(); npc->add_readied(tongs, Actor::rhand); npc->add_dirty(); state = use_trough; break; } case use_trough: { trough = npc->find_closest(719); anvil = npc->find_closest(991); if (!trough || !anvil || !blank) { // uh-oh... try again in a few seconds npc->start(250, 2500); state = put_sword_on_firepit; return; } Tile_coord tpos = anvil->get_tile() + Tile_coord(0,1,0); Actor_action *pact = Path_walking_actor_action:: create_path(npcpos, tpos, cost); Tile_coord tpos2 = trough->get_tile() + Tile_coord(0,2,0); Actor_action *pact2 = Path_walking_actor_action:: create_path(tpos, tpos2, cost); if (pact && pact2) { signed char troughframe = trough->get_framenum() - 1; if (troughframe < 0) troughframe = 0; int dir = npc->get_direction(trough); signed char npcframe = npc->get_dir_framenum(dir, Actor::bow_frame); Actor_action **a = new Actor_action*[7]; a[0] = pact; a[1] = new Pickup_actor_action(blank, 250); a[2] = pact2; a[3] = new Frames_actor_action(&npcframe, 1, 250); a[4] = new Frames_actor_action(&troughframe, 1, 0, trough); a[5] = new Frames_actor_action((signed char *)"\x00", 1, 0, blank); a[6] = 0; npc->set_action(new Sequence_actor_action(a)); } else { // no path found, just pick up sword blank npc->set_action(new Sequence_actor_action( new Pickup_actor_action(blank, 250), new Frames_actor_action((signed char *)"\0", 1, 0, blank))); } state = done; break; } case done: { npc->add_dirty(); if (tongs) { tongs->remove_this(); tongs = 0; } npc->add_dirty(); state = put_sword_on_firepit; } } npc->start(250, 100); // Back in queue. } /* * Forge schedule is done. */ void Forge_schedule::ending ( int new_type // New schedule. ) { // Remove any tools. if (tongs) { tongs->remove_this(); tongs = 0; } if (hammer) { hammer->remove_this(); hammer = 0; } firepit = npc->find_closest(739); bellows = npc->find_closest(431); if (firepit && firepit->get_framenum() != 0) firepit->change_frame(0); if (bellows && bellows->get_framenum() != 0) bellows->change_frame(0); if (blank && blank->get_framenum() != 0) blank->change_frame(0); } /* * Modify goal to walk off the screen. */ void Walk_to_schedule::walk_off_screen ( Rectangle& screen, // In tiles, area slightly larger than // actual screen. Tile_coord& goal // Modified for path offscreen. ) { // Destination. if (goal.tx >= screen.x + screen.w) { goal.tx = screen.x + screen.w - 1; goal.ty = -1; } else if (goal.tx < screen.x) { goal.tx = screen.x; goal.ty = -1; } else if (goal.ty >= screen.y + screen.h) { goal.ty = screen.y + screen.h - 1; goal.tx = -1; } else if (goal.ty < screen.y) { goal.ty = screen.y; goal.tx = -1; } } /* * Create schedule for walking to the next schedule's destination. */ Walk_to_schedule::Walk_to_schedule ( Actor *n, Tile_coord d, // Destination. int new_sched, // Schedule when we get there. int delay // Msecs, or -1 for random delay. ) : Schedule(n), dest(d), new_schedule(new_sched), retries(0), legs(0) { // Delay 0-20 secs. first_delay = delay >= 0 ? delay : 2*(rand()%10000); } /* * Schedule change for walking to another schedule destination. */ void Walk_to_schedule::now_what ( ) { if (npc->get_tile().distance(dest) <= 3) { // Close enough! npc->set_schedule_type(new_schedule); return; } if (legs >= 40 || retries >= 2) // Trying too hard? (Following // Patterson takes about 30.) { // Going to jump there. npc->move(dest.tx, dest.ty, dest.tz); npc->set_schedule_type(new_schedule); return; } // Get screen rect. in tiles. Rectangle screen = gwin->get_win_tile_rect(); screen.enlarge(6); // Enlarge in all dirs. // Might do part of it first. Tile_coord from = npc->get_tile(), to = dest; // Destination off the screen? if (!screen.has_point(to.tx, to.ty)) { if (!screen.has_point(from.tx, from.ty)) { // Force teleport on next tick. retries = 100; npc->start(200, 100); return; } // Don't walk off screen if close, or // if lots of legs, indicating that // Avatar is following this NPC. if (from.distance(to) > 80 || legs < 10) // Modify 'dest'. to walk off. walk_off_screen(screen, to); } else if (!screen.has_point(from.tx, from.ty)) // Modify src. to walk from off-screen. walk_off_screen(screen, from); blocked = Tile_coord(-1, -1, -1); cout << "Finding path to schedule for " << npc->get_name() << endl; // Create path to dest., delaying // 0 to 1 seconds. if (!npc->walk_path_to_tile(from, to, gwin->get_std_delay(), first_delay + rand()%1000)) { // Wait 1 sec., then try again. #ifdef DEBUG cout << "Failed to find path for " << npc->get_name() << endl; #endif npc->walk_to_tile(dest, gwin->get_std_delay(), 1000); retries++; // Failed. Try again next tick. } else // Okay. He's walking there. { legs++; retries = 0; } first_delay = 0; } /* * Don't go dormant when walking to a schedule. */ void Walk_to_schedule::im_dormant ( ) { Walk_to_schedule::now_what(); // Get there by any means. } /* * Get actual schedule (for Usecode intrinsic). */ int Walk_to_schedule::get_actual_type ( Actor * /* npc */ ) { return new_schedule; } /* * Set a schedule. */ void Schedule_change::set ( unsigned char *entry // 4 bytes read from schedule.dat. ) { time = entry[0]&7; type = entry[0]>>3; x = entry[1]; y = entry[2]; superchunk = entry[3]; } /* * Get a schedule. */ void Schedule_change::get ( unsigned char *entry // 4 bytes to write to schedule.dat. ) { entry[0] = time&7; entry[0] |= (type&31) << 3; entry[1] = x; entry[2] = y; entry[3] = superchunk; } /* * Set a schedule. */ void Schedule_change::set ( int ax, int ay, unsigned char stype, unsigned char stime ) { time = stime; type = stype; x = static_cast(ax%c_tiles_per_schunk); y = static_cast(ay%c_tiles_per_schunk); superchunk = static_cast((ay/c_tiles_per_schunk)*12 + (ax/c_tiles_per_schunk)); } /* * Get position. */ Tile_coord Schedule_change::get_pos() const { int cx = 16*(superchunk%12) + x/16, cy = 16*(superchunk/12) + y/16, tx = x%16, ty = y%16; return Tile_coord(cx*c_tiles_per_chunk + tx, cy*c_tiles_per_chunk + ty, 0); } exult-1.2/exultmenu.h0000644000175000001440000000227007724430450010377 /* * Copyright (C) 2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EXULTMENU_H #define EXULTMENU_H #include "palette.h" #include "game.h" class Mouse; class Image_buffer8; class Game_window; class ExultMenu { private: Game_window *gwin; Image_buffer8 *ibuf; Vga_file exult_flx; // Palette pal; int topx, topy, centerx, centery, menuy; void calc_win(); Mouse *menu_mouse; public: ExultMenu(Game_window *gw); ~ExultMenu(); Exult_Game run(); void setup(); }; #endif //EXULTMENU_H exult-1.2/args.cc0000755000175000001440000000623410054030527007441 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include #endif #include "args.h" #ifndef UNDER_CE using std::cerr; using std::endl; using std::string; using std::strtol; using std::strtoul; #endif void Args::declare(const char *s,bool *b,bool defval) { string ss; ss=s; Opts o; o.option=ss; o.bval=b; o.dbval=defval; o.valuetype=Opts::type_bool; options.push_back(o); } void Args::declare(const char *s,string *b,const char *defval) { string ss; ss=s; Opts o; o.option=ss; o.sval=b; o.dsval=defval?defval:""; *o.sval=defval?defval:""; o.valuetype=Opts::type_string; options.push_back(o); } void Args::declare(const char *s,int *b,int defval) { string ss; ss=s; Opts o; o.option=ss; o.ival=b; o.dival=defval; *o.ival=defval; o.valuetype=Opts::type_int; options.push_back(o); } void Args::declare(const char *s,uint32 *b,uint32 defval) { string ss; ss=s; Opts o; o.option=ss; o.uval=b; o.duval=defval; *o.uval=defval; o.valuetype=Opts::type_unsigned; options.push_back(o); } void Args::process(int argc,char **argv) { for(int i=1;i=argc) { cerr << "Data not specified for argument '" << options[j].option <<"'. Using default." << endl; break; } *(options[j].sval)=argv[i]; } break; } case Opts::type_int: { // char buf[64]; if(options[j].option==argv[i]) { // We want the _next_ argument if(++i>=argc) { cerr << "Data not specified for argument '" << options[j].option <<"'. Using default." << endl; break; } *(options[j].ival)=strtol(argv[i],0,10); } break; } case Opts::type_unsigned: { // char buf[64]; if(options[j].option==argv[i]) { // We want the _next_ argument if(++i>=argc) { cerr << "Data not specified for argument '" << options[j].option <<"'. Using default." << endl; break; } *(options[j].uval)=strtoul(argv[i],0,10); } break; } } } } } exult-1.2/bggame.cc0000644000175000001440000012663110054030527007730 /* * Copyright (C) 2000-2004 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "SDL_events.h" #include #include "files/U7file.h" #include "files/utils.h" #include "flic/playfli.h" #include "gamewin.h" #include "Audio.h" #include "bggame.h" #include "sigame.h" #include "palette.h" #include "databuf.h" #include "font.h" #include "txtscroll.h" #include "data/exult_bg_flx.h" #include "exult.h" #include "Configuration.h" #include "shapeid.h" #ifndef ALPHA_LINUX_CXX # include # include #endif #ifndef UNDER_CE using std::abs; using std::rand; using std::strchr; using std::strlen; using std::toupper; #endif enum { ultima_text_shp = 0x0D, butterfly_shp = 0x0E, lord_british_shp = 0x11, trees_shp = 0x12, guardian_mouth_shp = 0x1E, guardian_forehead_shp = 0x1F, guardian_eyes_shp = 0x20 }; enum { bird_song_midi = 0, home_song_midi = 1, guardian_midi = 2, menu_midi = 3, credits_midi = 4, quotes_midi = 5 }; BG_Game::BG_Game() : shapes(ENDSHAPE_FLX) { add_shape("gumps/check",2); add_shape("gumps/fileio",3); add_shape("gumps/fntext",4); add_shape("gumps/loadbtn",5); add_shape("gumps/savebtn",6); add_shape("gumps/halo",7); add_shape("gumps/disk",24); add_shape("gumps/heart",25); add_shape("gumps/statatts",28); add_shape("gumps/musicbtn",29); add_shape("gumps/speechbtn",30); add_shape("gumps/soundbtn",31); add_shape("gumps/spellbook",43); add_shape("gumps/statsdisplay",47); add_shape("gumps/combat",46); add_shape("gumps/quitbtn",56); add_shape("gumps/yesnobox",69); add_shape("gumps/yesbtn",70); add_shape("gumps/nobtn",71); add_shape("gumps/book",32); add_shape("gumps/scroll",55); add_shape("gumps/combatmode",12); add_shape("gumps/slider",14); add_shape("gumps/slider_diamond",15); add_shape("gumps/slider_right",16); add_shape("gumps/slider_left",17); add_shape("gumps/box", 0); add_shape("gumps/crate", 1); add_shape("gumps/barrel", 8); add_shape("gumps/bag", 9); add_shape("gumps/backpack", 10); add_shape("gumps/basket", 11); add_shape("gumps/chest", 22); add_shape("gumps/shipshold", 26); add_shape("gumps/drawer", 27); add_shape("gumps/woodsign", 49); add_shape("gumps/tombstone", 50); add_shape("gumps/goldsign", 51); add_shape("gumps/body", 53); add_shape("sprites/map", 22); add_shape("sprites/cheatmap", 12); add_resource("files/shapes/count", 0, 9); add_resource("files/shapes/0", "/shapes.vga", 0); add_resource("files/shapes/1", "/faces.vga", 0); add_resource("files/shapes/2", "/gumps.vga", 0); add_resource("files/shapes/3", "/sprites.vga", 0); add_resource("files/shapes/4", MAINSHP_FLX, 0); add_resource("files/shapes/5", "/endshape.flx", 0); add_resource("files/shapes/6", "/fonts.vga", 0); add_resource("files/shapes/7", "/exult.flx", 0); add_resource("files/shapes/8", "/exult_bg.flx", 0); add_resource("files/gameflx", "/exult_bg.flx", 0); add_resource("config/defaultkeys", "/exult_bg.flx", 13); add_resource("palettes/count", 0, 18); add_resource("palettes/0", PALETTES_FLX, 0); add_resource("palettes/1", PALETTES_FLX, 1); add_resource("palettes/2", PALETTES_FLX, 2); add_resource("palettes/3", PALETTES_FLX, 3); add_resource("palettes/4", PALETTES_FLX, 4); add_resource("palettes/5", PALETTES_FLX, 5); add_resource("palettes/6", PALETTES_FLX, 6); add_resource("palettes/7", PALETTES_FLX, 7); add_resource("palettes/8", PALETTES_FLX, 8); add_resource("palettes/9", PALETTES_FLX, 10); add_resource("palettes/10", PALETTES_FLX, 11); add_resource("palettes/11", PALETTES_FLX, 12); add_resource("palettes/12", "/intropal.dat", 0); add_resource("palettes/13", "/intropal.dat", 1); add_resource("palettes/14", "/intropal.dat", 2); add_resource("palettes/15", "/intropal.dat", 3); add_resource("palettes/16", "/intropal.dat", 4); add_resource("palettes/17", "/intropal.dat", 5); add_resource("xforms/count", 0, 20); add_resource("xforms/0", "/xform.tbl", 0); add_resource("xforms/1", "/xform.tbl", 1); add_resource("xforms/2", "/xform.tbl", 2); add_resource("xforms/3", "/xform.tbl", 3); add_resource("xforms/4", "/xform.tbl", 4); add_resource("xforms/5", "/xform.tbl", 5); add_resource("xforms/6", "/xform.tbl", 6); add_resource("xforms/7", "/xform.tbl", 7); add_resource("xforms/8", "/xform.tbl", 8); add_resource("xforms/9", "/xform.tbl", 9); add_resource("xforms/10", "/xform.tbl", 10); add_resource("xforms/11", "/xform.tbl", 11); add_resource("xforms/12", "/xform.tbl", 12); add_resource("xforms/13", "/xform.tbl", 13); add_resource("xforms/14", "/xform.tbl", 14); add_resource("xforms/15", "/xform.tbl", 15); add_resource("xforms/16", "/xform.tbl", 16); add_resource("xforms/17", "/xform.tbl", 17); add_resource("xforms/18", "/xform.tbl", 18); add_resource("xforms/19", "/xform.tbl", 19); fontManager.add_font("MENU_FONT", MAINSHP_FLX, 9, 1); fontManager.add_font("END2_FONT", ENDGAME, 4, -1); fontManager.add_font("END3_FONT", ENDGAME, 5, -2); fontManager.add_font("NORMAL_FONT", FONTS_VGA, 0, -1); } BG_Game::~BG_Game() { } class UserSkipException : public UserBreakException { }; #define WAITDELAY(x) switch(wait_delay(x)) { \ case 1: throw UserBreakException(); break; \ case 2: throw UserSkipException(); break; \ } #define WAITDELAYCYCLE(x) switch (wait_delay((x), 16, 78)) { \ case 1: throw UserBreakException(); break; \ case 2: throw UserSkipException(); break; \ } #define WAITDELAYCYCLE2(x) switch (wait_delay((x), 250, 5)) { \ case 1: throw UserBreakException(); break; \ case 2: throw UserSkipException(); break; \ } #define WAITDELAYCYCLE3(x) switch (wait_delay((x), 240, 15)) { \ case 1: throw UserBreakException(); break; \ case 2: throw UserSkipException(); break; \ } void BG_Game::play_intro() { gwin->clear_screen(true); Audio::get_ptr()->stop_music(); // TODO: check/fix other resolutions // these backups store the area under the guardian shapes being drawn // the cbackups are 'clean' backups, ie. just background // the others may have other shapes on them, if those are static Image_buffer *backup, *backup2, *backup3; Image_buffer *cbackup, *cbackup2, *cbackup3; backup = backup2 = backup3 = 0; cbackup = cbackup2 = cbackup3 = 0; try { /******************************************************************** Lord British Presents ********************************************************************/ scene_lord_british(); /******************************************************************** Ultima VII logo w/Trees ********************************************************************/ scene_butterfly(); /******************************************************************** Enter guardian TODO: reduce sudden facial movements in speech ********************************************************************/ scene_guardian(); // TODO: transition (zoom out to PC) scene missing /******************************************************************** PC screen ********************************************************************/ scene_desk(); /******************************************************************** The Moongate ********************************************************************/ scene_moongate(); } catch(const UserBreakException &x) { // Waste disposal FORGET_OBJECT(backup); FORGET_OBJECT(backup2); FORGET_OBJECT(backup3); FORGET_OBJECT(cbackup); FORGET_OBJECT(cbackup2); FORGET_OBJECT(cbackup3); } // Fade out the palette... pal->fade_out(c_fade_out_time); // ... and clean the screen. gwin->clear_screen(true); // Stop all audio output Audio::get_ptr()->cancel_streams(); } void BG_Game::scene_lord_british() { Font *font = fontManager.get_font("END2_FONT"); const char *txt_msg[] = { "with help from", "The Exult Team"}; // Lord British presents... (sh. 0x11) pal->load("/intropal.dat",3); sman->paint_shape(topx,topy,shapes.get_shape(lord_british_shp,0)); // insert our own intro text font->center_text(ibuf, centerx, centery+50, txt_msg[0]); font->center_text(ibuf, centerx, centery+65, txt_msg[1]); pal->fade_in(c_fade_in_time); if(1 == wait_delay(2000)) throw UserBreakException(); pal->fade_out(c_fade_out_time); gwin->clear_screen(true); } #define BUTTERFLY_FRAME_DURATION 16 #define BUTTERFLY_SUB_FRAMES 3 #define BUTTERFLY(x,y,frame,delay) do { \ win->get(backup, topx + (x) - butterfly->get_xleft(), \ topy + (y) - butterfly->get_yabove()); \ sman->paint_shape(topx + x, topy + y, shapes.get_shape(butterfly_shp, frame)); \ win->show(); \ WAITDELAY(delay); \ win->put(backup, topx + (x) - butterfly->get_xleft(), \ topy + (y) - butterfly->get_yabove()); \ } while(0) #define BUTTERFLY_FLAP() do { \ if ((rand() % 5)<4) { \ if (frame == 3) \ dir = -1; \ else if (frame == 0) \ dir = +1; \ frame += dir; \ } } while(0) static int butterfly_x[] = { 6,18,30,41,52,62,70,78,86,95, 104,113,122,132,139,146,151,155,157,158, 157,155,151,146,139,132,124,116,108,102, 96,93,93,93,95,99,109,111,118,125, 132,140,148,157,164,171,178,184,190,196, 203,211,219,228,237,246,254,259,262,264, 265,265,263,260,256,251,245,239,232,226, 219,212,208,206,206,209,212,216,220,224, 227,234,231,232,233,233,233,233,234,236, 239,243,247,250,258,265 }; static int butterfly_y[] = { 155,153,151,150,149,148,148,148,148,149, 150,150,150,149,147,142,137,131,125,118, 110,103,98,94,92,91,91,91,92,95, 99,104,110,117,123,127,131,134,135,135, 135,135,135,134,132,129,127,123,119,115, 112,109,104,102,101,102,109,109,114,119, 125,131,138,144,149,152,156,158,159,159, 158,155,150,144,137,130,124,118,112,105, 99,93,86,80,73,66,59,53,47,42, 38,35,32,29,26,25 }; static const int butterfly_num_coords = sizeof(butterfly_x)/sizeof(int); static int butterfly_end_frames[] = { 3, 4, 3, 4, 3, 2, 1, 0 }; static int butterfly_end_delay[] = { 167, 416, 250, 416, 416, 416, 416, 333 }; void BG_Game::scene_butterfly() { Font *font = fontManager.get_font("END2_FONT"); Image_buffer *backup = 0; Shape_frame *butterfly = 0; const char *txt_msg = "Driven by Exult"; int i, j, frame, dir; try { pal->load("/intropal.dat",4); // Load the butterfly shape butterfly = shapes.get_shape(butterfly_shp,0); backup = win->create_buffer(butterfly->get_width(), butterfly->get_height()); // Start playing the birdsongs while still faded out play_midi(bird_song_midi); // trees with "Ultima VII" on top of 'em sman->paint_shape(topx,topy,shapes.get_shape(trees_shp,0)); sman->paint_shape(topx+160,topy+50,shapes.get_shape(ultima_text_shp,0)); // again display our own text font->center_text(ibuf, centerx, centery+50, txt_msg); // Keep it dark for some more time, playing the music WAITDELAY(3500); // Finally fade in pal->fade_in(c_fade_in_time); WAITDELAY(12500); // clear 'Exult' text sman->paint_shape(topx,topy,shapes.get_shape(trees_shp,0)); sman->paint_shape(topx+160,topy+50,shapes.get_shape(ultima_text_shp,0)); win->show(); // // Move the butterfly along its path // frame = 0; Sint32 delay = BUTTERFLY_FRAME_DURATION; Sint32 ticks = SDL_GetTicks(); for(i=0; i < butterfly_num_coords-1; ++i) { for(j=0; j < BUTTERFLY_SUB_FRAMES; ++j) { ticks = SDL_GetTicks(); int x = butterfly_x[i] + j*(butterfly_x[i+1] - butterfly_x[i])/BUTTERFLY_SUB_FRAMES; int y = butterfly_y[i] + j*(butterfly_y[i+1] - butterfly_y[i])/BUTTERFLY_SUB_FRAMES; BUTTERFLY(x, y, frame, delay); // Flap the wings; but not always, so that the butterfly "glides" from time to time BUTTERFLY_FLAP(); // Calculate the difference between the time we wanted to spent and the time // we actually spent; then adjust 'delay' accordingly ticks = SDL_GetTicks() - ticks; delay = (delay + (2*BUTTERFLY_FRAME_DURATION - ticks)) / 2; // ... but maybe we also have to skip frames.. if( delay < 0 ) { // Calculate how many frames we should skip int frames_to_skip = (-delay) / BUTTERFLY_FRAME_DURATION + 1; int new_index = i*BUTTERFLY_SUB_FRAMES + j + frames_to_skip; i = new_index / BUTTERFLY_SUB_FRAMES; j = new_index % BUTTERFLY_SUB_FRAMES; // Did we skip over the end? if ( i >= butterfly_num_coords-1 ) break; while(frames_to_skip--) BUTTERFLY_FLAP(); delay = 0; } } } // Finally, let it flutter a bit on the end spot for(i=0; i<8; i++) { BUTTERFLY(butterfly_x[butterfly_num_coords-1], butterfly_y[butterfly_num_coords-1], butterfly_end_frames[i], butterfly_end_delay[i]); } WAITDELAY(2000); // Wait till the music finished playing while(Audio::get_ptr()->is_track_playing(bird_song_midi)) WAITDELAY(20); } catch(const UserSkipException &x) { } } #define FLASH_SHAPE(x,y,shape,frame, delay) do { \ sman->paint_shape(x,y,shapes.get_shape(shape,frame)); \ win->show(); \ WAITDELAYCYCLE(delay); \ win->put(backup,(x)-s->get_xleft(),(y)-s->get_yabove()); \ } while(0) #define EYES_DIST 12 #define FORHEAD_DIST 49 void BG_Game::scene_guardian() { Image_buffer *backup = 0, *backup2 = 0, *backup3 = 0; Image_buffer *cbackup = 0, *cbackup2 = 0, *cbackup3 = 0; Image_buffer *plasma; char *txt = 0; try { char *txt_ptr, *txt_end, *next_txt; Shape_frame *s, *s2, *s3; Uint32 ticks; int i; // Start background music play_midi(guardian_midi); // create buffer containing a blue 'plasma' screen plasma = win->create_buffer(gwin->get_width(), gwin->get_height()); gwin->plasma(gwin->get_width(), gwin->get_height(), 0, 0, 16, 16+76); win->get(plasma, 0, 0); pal->load("/intropal.dat",2); pal->set_color(1,0,0,0); //UGLY hack... set font background to black pal->apply(); //play static SFX Audio::get_ptr()->play_sound_effect(115, MIX_MAX_VOLUME, 0, 0); //TODO: timing? win->show(); WAITDELAYCYCLE(100); // // Show some "static" alternating with the blue plasma // ticks = SDL_GetTicks(); while(1) { win->get_ibuf()->fill_static(0, 7, 15); win->show(); WAITDELAY(0); if (SDL_GetTicks() > ticks + 400) break; } win->put(plasma,0,0); win->show(); WAITDELAYCYCLE(100); ticks = SDL_GetTicks(); while(1) { win->get_ibuf()->fill_static(0, 7, 15); win->show(); WAITDELAY(0); if (SDL_GetTicks() > ticks + 200) break; } win->put(plasma,0,0); win->show(); WAITDELAYCYCLE(200); ticks = SDL_GetTicks(); while(1) { win->get_ibuf()->fill_static(0, 7, 15); win->show(); WAITDELAY(0); if (SDL_GetTicks() > ticks + 100) break; } win->put(plasma,0,0); win->show(); FORGET_OBJECT(plasma); // // First 'popup' (sh. 0x21) // s = shapes.get_shape(0x21, 0); backup = win->create_buffer(s->get_width(), s->get_height()); win->get(backup, centerx-53-s->get_xleft(), centery-68-s->get_yabove()); for(i=8; i>=-8; i--) { FLASH_SHAPE(centerx-53, centery-68, 0x21, 1+abs(i),70); } FORGET_OBJECT(backup); WAITDELAYCYCLE(800); // // Second 'popup' (sh. 0x22) // s = shapes.get_shape(0x22, 0); backup = win->create_buffer(s->get_width(), s->get_height()); win->get(backup, centerx - s->get_xleft(), centery-45 - s->get_yabove()); for(i=9; i>=-9; i--) { FLASH_SHAPE(centerx, centery-45, 0x22, 9-abs(i),70); } FORGET_OBJECT(backup); WAITDELAYCYCLE(800); // // Successful 'popup' (sh. 0x23) // s = shapes.get_shape(0x23, 0); backup = win->create_buffer(s->get_width(), s->get_height()); cbackup = win->create_buffer(s->get_width(), s->get_height()); win->get(cbackup, centerx - s->get_xleft(), centery - s->get_yabove()); sman->paint_shape(centerx,centery,s); // frame 0 is static background win->get(backup, centerx- s->get_xleft(), centery- s->get_yabove()); for(i=1; i<16; i++) { FLASH_SHAPE(centerx, centery, 0x23, i,70); } win->put(cbackup, centerx - s->get_xleft(), centery - s->get_yabove()); FORGET_OBJECT(backup); FORGET_OBJECT(cbackup); // // Actual appearance // // mouth s = shapes.get_shape(guardian_mouth_shp,0); backup = win->create_buffer(s->get_width(), s->get_height()); cbackup = win->create_buffer(s->get_width(), s->get_height()); win->get(cbackup, centerx - s->get_xleft(), centery - s->get_yabove()); sman->paint_shape(centerx,centery,s); // frame 0 is background win->get(backup, centerx - s->get_xleft(), centery - s->get_yabove()); // eyes s2 = shapes.get_shape(guardian_eyes_shp,0); backup2 = win->create_buffer(s2->get_width(), s2->get_height()); cbackup2 = win->create_buffer(s2->get_width(), s2->get_height()); win->get(cbackup2, centerx - s2->get_xleft(), centery-EYES_DIST - s2->get_yabove()); sman->paint_shape(centerx,centery-EYES_DIST,s2); // frame 0 is background win->get(backup2, centerx - s2->get_xleft(), centery-EYES_DIST - s2->get_yabove()); // forehead s3 = shapes.get_shape(guardian_forehead_shp,0); cbackup3 = win->create_buffer(s3->get_width(), s3->get_height()); win->get(cbackup3, centerx - s3->get_xleft(), centery-FORHEAD_DIST - s3->get_yabove()); sman->paint_shape(centerx,centery-FORHEAD_DIST,s3); // forehead isn't animated // prepare Guardian speech Font *font = fontManager.get_font("END3_FONT"); U7object textobj(MAINSHP_FLX, 0x0D); size_t txt_len; next_txt = txt_ptr = txt = textobj.retrieve(txt_len); if (Audio::get_ptr()->is_speech_enabled()) Audio::get_ptr()->playfile(INTROSND,false); int txt_height = font->get_text_height(); int txt_ypos = gwin->get_height()-txt_height-16; // backup text area backup3 = win->create_buffer(gwin->get_width(),txt_height); win->get(backup3, 0, txt_ypos); int speech_delay[] = { 29, 71, 59, 47, 47, 62, 79, 55, 90, 104, 80, 65, 55, 120 }; // start speech for(int speech_item=0; speech_item<14; speech_item++) { unsigned long ticks = SDL_GetTicks(); unsigned long end_ticks = ticks+speech_delay[speech_item]*50; i=0; do { // convoluted mess to get eye movement acceptable int eye_frame = 1 + 3*((i/12) % 4) + ((i%50>47&&(i/12)%4!=3)?i%50-47:0); sman->paint_shape(centerx,centery-EYES_DIST, shapes.get_shape(guardian_eyes_shp, eye_frame)); sman->paint_shape(centerx,centery, shapes.get_shape(guardian_mouth_shp,1 + i % 13)); if (i == 0) { txt_ptr = next_txt; txt_end = strchr(txt_ptr, '\r'); *txt_end = '\0'; next_txt = txt_end+2; } font->center_text(win->get_ib8(), centerx, txt_ypos, txt_ptr); win->show(); WAITDELAYCYCLE(50); win->put(backup3, 0, txt_ypos); win->put(backup, centerx - s->get_xleft(), centery - s->get_yabove()); win->put(backup2, centerx - s2->get_xleft(), centery-EYES_DIST - s2->get_yabove()); ticks = SDL_GetTicks(); ++i; } while (ticksput(backup3, 0, txt_ypos); win->put(cbackup, centerx - s->get_xleft(), centery - s->get_yabove()); win->put(cbackup2, centerx - s2->get_xleft(), centery-EYES_DIST - s2->get_yabove()); win->put(cbackup3, centerx - s3->get_xleft(), centery-FORHEAD_DIST - s3->get_yabove()); FORGET_ARRAY(txt); FORGET_OBJECT(backup); FORGET_OBJECT(backup2); FORGET_OBJECT(backup3); FORGET_OBJECT(cbackup); FORGET_OBJECT(cbackup2); FORGET_OBJECT(cbackup3); // G. disappears again (sp. 0x23 again) s = shapes.get_shape(0x23, 0); backup = win->create_buffer(s->get_width(), s->get_height()); cbackup = win->create_buffer(s->get_width(), s->get_height()); win->get(cbackup, centerx- s->get_xleft(), centery- s->get_yabove()); sman->paint_shape(centerx,centery,s); // frame 0 is background win->get(backup, centerx - s->get_xleft(), centery - s->get_yabove()); for(i=15; i>0; i--) { FLASH_SHAPE(centerx, centery, 0x23, i, 70); } win->put(cbackup, centerx- s->get_xleft(), centery- s->get_yabove()); FORGET_OBJECT(backup); FORGET_OBJECT(cbackup); win->show(); WAITDELAYCYCLE(1000); Audio::get_ptr()->stop_music(); // // White dot // s = shapes.get_shape(0x14, 0); backup = win->create_buffer(s->get_width()+2, s->get_height()+2); win->get(backup, centerx - 1, centery - 1); ticks = SDL_GetTicks(); for(i = 0; i < 100; i++) { int x = centerx + rand()%3 - 1; int y = centery + rand()%3 - 1; FLASH_SHAPE(x, y, 0x14, 0, 0); if (SDL_GetTicks() - ticks > 400) break; } FORGET_OBJECT(backup); } catch(const UserBreakException &x) { // Waste disposal FORGET_ARRAY(txt); FORGET_OBJECT(backup); FORGET_OBJECT(backup2); FORGET_OBJECT(backup3); FORGET_OBJECT(cbackup); FORGET_OBJECT(cbackup2); FORGET_OBJECT(cbackup3); FORGET_OBJECT(plasma); if(typeid(x) != typeid(UserSkipException)) throw x; } } void BG_Game::scene_desk() { Shape_frame *s; Image_buffer *backup = 0; int i; try { play_midi(home_song_midi); gwin->clear_screen(); pal->load("/intropal.dat",1); pal->apply(); // draw monitor (sh. 0x07, 0x08, 0x09, 0x0A: various parts of monitor) sman->paint_shape(centerx, centery, shapes.get_shape(0x07,0)); sman->paint_shape(centerx, centery, shapes.get_shape(0x09,0)); sman->paint_shape(centerx, centery, shapes.get_shape(0x08,0)); sman->paint_shape(centerx, centery, shapes.get_shape(0x0A,0)); // draw white dot in center of monitor (sh. 0x14) sman->paint_shape(centerx+12, centery-22, shapes.get_shape(0x14,0)); // draw arm hitting pc (sh. 0x0C) s = shapes.get_shape(0x0C, 0); backup = win->create_buffer(s->get_width(), s->get_height()); for (i=0; i<9; i++) { win->get(backup, centerx-96-30*abs(i%4-2) - s->get_xleft(), centery+100 - s->get_yabove()); sman->paint_shape(centerx-96-30*abs(i%4-2), centery+100, s); win->show(); win->put(backup, centerx-96-30*abs(i%4-2) - s->get_xleft(), centery+100 - s->get_yabove()); WAITDELAY(1); //just to catch events } // screen comes back up (sh. 0x1D) sman->paint_shape(centerx+12, centery-22, shapes.get_shape(0x1D,0)); win->show(); FORGET_OBJECT(backup); // "Something is obviously amiss" sman->paint_shape(centerx, centery+50, shapes.get_shape(0x15,0)); win->show(); WAITDELAY(4000); // TODO: misaligned? // scroll right (sh. 0x06: map to the right of the monitor) for(i=0;i<194;i+=4) { sman->paint_shape(centerx-i,centery, shapes.get_shape(0x07,0)); sman->paint_shape(centerx-i,centery, shapes.get_shape(0x09,0)); sman->paint_shape(centerx-i,centery, shapes.get_shape(0x08,0)); sman->paint_shape(centerx-i,centery, shapes.get_shape(0x0A,0)); sman->paint_shape(centerx-i+12, centery-22, shapes.get_shape(0x1D,0)); sman->paint_shape(topx+320-i,topy, shapes.get_shape(0x06,0)); if (i > 20 && i < 175) { // "It has been a long time..." sman->paint_shape(centerx, centery+50, shapes.get_shape(0x16,0)); } win->show(); WAITDELAY(30); } // scroll down (sh. 0x0B: mouse + orb of moons, below map) for(i=0;i<=50;i+=2) { sman->paint_shape(centerx-194, centery-i, shapes.get_shape(0x07,0)); sman->paint_shape(centerx-194, centery-i, shapes.get_shape(0x09,0)); sman->paint_shape(centerx-194, centery-i, shapes.get_shape(0x08,0)); sman->paint_shape(centerx-194, centery-i, shapes.get_shape(0x0A,0)); sman->paint_shape(centerx-194+12, centery-22-i, shapes.get_shape(0x1D,0)); sman->paint_shape(topx+319-194, topy-i, shapes.get_shape(0x06,0)); sman->paint_shape(topx+319, topy+199-i, shapes.get_shape(0x0B,0)); // "The mystical Orb beckons you" sman->paint_shape(centerx, topy, shapes.get_shape(0x17,0)); win->show(); WAITDELAYCYCLE2(50); } WAITDELAYCYCLE2(1000); sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x07,0)); sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x09,0)); sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x08,0)); sman->paint_shape(centerx-194, centery-50, shapes.get_shape(0x0A,0)); sman->paint_shape(centerx-182, centery-72, shapes.get_shape(0x1D,0)); sman->paint_shape(topx+319-194, topy-50, shapes.get_shape(0x06,0)); sman->paint_shape(topx+319, topy+149, shapes.get_shape(0x0B,0)); // "It has opened gateways to Britannia in the past" sman->paint_shape(centerx, topy, shapes.get_shape(0x18,0)); win->show(); WAITDELAYCYCLE2(3000); } catch(const UserBreakException &x) { // Waste disposal FORGET_OBJECT(backup); throw x; } } void BG_Game::scene_moongate() { // sh. 0x02, 0x03, 0x04, 0x05: various parts of moongate // sh. 0x00, 0x01: parting trees before clearing int i; gwin->clear_screen(); pal->load("/intropal.dat",5); pal->apply(); // "Behind your house is the circle of stones" sman->paint_shape(centerx, centery+50, shapes.get_shape(0x19,0)); win->show(); // TODO: fade in screen while text is onscreen WAITDELAY(3000); // TODO: misaligned? for(i=120;i>=-170;i-=6) { sman->paint_shape(centerx+1,centery+1, shapes.get_shape(0x02,0)); sman->paint_shape(centerx+1,centery+1, shapes.get_shape(0x03,0)); sman->paint_shape(centerx+1,centery+1, shapes.get_shape(0x04,0)); sman->paint_shape(centerx+1,centery+1, shapes.get_shape(0x05,0)); sman->paint_shape(centerx+i,topy, shapes.get_shape(0x00,0)); sman->paint_shape(centerx-i,topy, shapes.get_shape(0x01,0)); // "Why is a moongate already there?" sman->paint_shape(centerx,centery+50,shapes.get_shape(0x1A,0)); win->show(); WAITDELAYCYCLE3(50); } sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x02,0)); sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x03,0)); sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x04,0)); sman->paint_shape(centerx+1, centery+1, shapes.get_shape(0x05,0)); // "You have but one path to the answer" sman->paint_shape(centerx, centery+50, shapes.get_shape(0x1C,0)); win->show(); // TODO: zoom (run) into moongate WAITDELAYCYCLE3(3000); // Wait till the music finished playing while(Audio::get_ptr()->is_track_playing(home_song_midi)) WAITDELAYCYCLE3(50); } void BG_Game::top_menu() { play_midi(menu_midi, true); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); pal->load("/intropal.dat",0); pal->fade_in(60); } void BG_Game::show_journey_failed() { pal->fade_out(50); sman->paint_shape(topx,topy,menushapes.get_shape(0x2,0)); journey_failed_text(); } void BG_Game::end_game(bool success) { int i, j, next = 0; int starty; int centerx = gwin->get_width() /2; int topy = (gwin->get_height()-200)/2; Font *font = fontManager.get_font("MENU_FONT"); if(!success) { TextScroller text(MAINSHP_FLX, 0x15, font,0); gwin->clear_screen(); pal->load("/intropal.dat",0); for(uint32 i=0; ifade_in(c_fade_in_time); wait_delay(10000); pal->fade_out(c_fade_out_time); gwin->clear_screen(); font->center_text(ibuf, centerx, centery-10, "The end of Ultima VII"); pal->fade_in(c_fade_in_time); wait_delay(4000); pal->fade_out(c_fade_out_time); gwin->clear_screen(); font->center_text(ibuf, centerx, centery-10, "The end of Britannia as you know it!"); pal->fade_in(c_fade_in_time); wait_delay(4000); pal->fade_out(c_fade_out_time); gwin->clear_screen(true); return; } // Audio buffer size_t size; uint8 *buffer; // Fli Buffers size_t flisize; char *fli_b[3]; // Clear screen gwin->clear_screen(true); U7object flic1(ENDGAME, 0); U7object flic2(ENDGAME, 1); U7object flic3(ENDGAME, 2); U7object speech1(ENDGAME, 7); U7object speech2(ENDGAME, 8); U7object speech3(ENDGAME, 9); /* There seems to be something wrong with the shapes. Needs investigating U7object shapes(ENDGAME, 10); shapes.retrieve("endgame.shp"); Shape_file sf("endgame.shp"); int x = get_width()/2-160; int y = get_height()/2-100; cout << "Shape in Endgame.dat has " << sf.get_num_frames() << endl; */ fli_b[0] = flic1.retrieve(flisize); playfli fli1(fli_b[0]+8, flisize-8); fli_b[1] = flic2.retrieve(flisize); playfli fli2(fli_b[1]+8, flisize-8); fli_b[2] = flic3.retrieve(flisize); playfli fli3(fli_b[2]+8, flisize-8); buffer = (uint8 *) speech1.retrieve(size); fli1.play(win, 0, 0, 0); // Start endgame music. Audio *audio = Audio::get_ptr(); int music_offset = 0; if (audio) { MyMidiPlayer *midi = audio->get_midi(); if (midi) { midi->load_patches(true); if (midi->is_fm_synth()) music_offset = 2; } audio->start_music(ENDSCORE_XMI,1+music_offset,false); } // A little hack bool do_break = false; do { for (i = 0; i < 240; i++) { next = fli1.play(win, 0, 1, next); if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; for (i = 1; i < 150; i++) { next = fli1.play(win, i, i+1, next); if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; if (audio) audio->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); Font *endfont2 = fontManager.get_font("END2_FONT"); Font *endfont3 = fontManager.get_font("END3_FONT"); Font *normal = fontManager.get_font("NORMAL_FONT"); const char *message = "No. You cannot do that! You must not!"; int height = topy+200 - endfont2->get_text_height()*2; int width = (gwin->get_width() - endfont2->get_text_width(message)) / 2; for (i = 150; i < 204; i++) { next = fli1.play(win, i, i, next); endfont2->draw_text(ibuf, width, height, message); win->show(); if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; // Set new music if (audio) audio->start_music(ENDSCORE_XMI,2+music_offset,false); // Set speech buffer = (uint8 *) speech2.retrieve(size); if (audio) audio->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); message = "Damn you Avatar! Damn you!"; width = (gwin->get_width() - endfont2->get_text_width(message)) / 2; for (i = 0; i < 100; i++) { next = fli2.play(win, i, i, next); endfont2->draw_text(ibuf, width, height, message); win->show(); if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; Palette *pal = fli2.get_palette(); next = SDL_GetTicks(); for (i = 1000 + next; next < i; next += 10) { // Speed related frame skipping detection int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next; while (SDL_GetTicks() < next) ; if (!skip_frame) { pal->set_brightness ((i - next) / 10); pal->apply(); } if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; pal->set_brightness(80); // Set readable brightness // Text message 1 // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); // Paint text message = "The Black Gate is destroyed."; width = (gwin->get_width() - normal->get_text_width(message)) / 2; height = (gwin->get_height() - normal->get_text_height()) / 2; normal->draw_text (ibuf, width, height, message); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for 3 seconds for (i = 0; i < 30; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); // Now the second text message // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); // Paint text message = "The Guardian has been stopped."; width = (gwin->get_width() - normal->get_text_width(message)) / 2; normal->draw_text (ibuf, width, height, message); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for approx 3 seonds for (i = 0; i < 30; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); next = fli3.play(win, 0, 0, next); pal = fli3.get_palette(); next = SDL_GetTicks(); for (i = 1000 + next; next < i; next += 10) { // Speed related frame skipping detection int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next; while (SDL_GetTicks() < next) ; if (!skip_frame) { pal->set_brightness (100 - (i-next) / 10); pal->apply(); } if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; buffer = (uint8 *) speech3.retrieve(size); if (audio) audio->play (buffer+8, size-8, false); FORGET_ARRAY(buffer); playfli::fliinfo finfo; fli3.info (&finfo); int m; const char *txt_screen0[] = { "Avatar! You think you have won>", "Think again! You are unable to", "leave britannia, whereas I am free", "to enter other worlds", "Perhaps your puny Earth shall be", "my NEXT target!." }; starty = (gwin->get_height() - endfont3->get_text_height()*8)/2; next = SDL_GetTicks(); for (i = next+28000; i > next; ) { for (j = 0; j < finfo.frames; j++) { next = fli3.play(win, j, j, next); for(m=0; m<6; m++) endfont3->center_text(ibuf, centerx, starty+endfont3->get_text_height()*m, txt_screen0[m]); win->show (); if (wait_delay (10)) { do_break = true; break; } } } if (do_break) break; next = SDL_GetTicks(); for (i = 1000 + next; next < i; next += 10) { // Speed related frame skipping detection int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= next; while (SDL_GetTicks() < next) ; if (!skip_frame) { pal->set_brightness ((i - next) / 10); pal->apply(); } if (wait_delay (0)) { do_break = true; break; } } if (do_break) break; // Text Screen 1 pal->set_brightness(80); // Set readable brightness // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); const char *txt_screen1[] = { "In the months following the climactic", "battle at The Black Gate, Britannia", "is set upon the long road to recovery", "from its various plights.", " ", "Upon your return to Britain,", "Lord British decreed that", "The Fellowship be outlawed", "and all of the branches were", "soon destroyed." }; starty = (gwin->get_height() - normal->get_text_height()*10)/2; for(i=0; i<10; i++) normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen1[i])/2, starty+normal->get_text_height()*i, txt_screen1[i]); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for 20 seonds (only 10 at the moment) for (i = 0; i < 100; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); if (wait_delay (10)) { do_break = true; break; } if (do_break) break; // Text Screen 2 // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); const char *txt_screen2[] = { "The frustration you feel at having been", "stranded in Britannia is somewhat", "alleviated by the satisfaction that you", "solved the gruesome murders committed", "by The Fellowship and even avenged the", "death of Spark's father." }; starty = (gwin->get_height() - normal->get_text_height()*6)/2; for(i=0; i<6; i++) normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen2[i])/2, starty+normal->get_text_height()*i, txt_screen2[i]); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for 20 seonds (only 8 at the moment) for (i = 0; i < 80; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); if (wait_delay (10)) break; // Text Screen 3 // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); const char *txt_screen3[] = { "And although you are, at the moment,", "helpless to do anything about", "The Guardian's final threat,", "another thought nags at you...", "what became of Batlin, the fiend", "who got away?" }; starty = (gwin->get_height() - normal->get_text_height()*6)/2; for(i=0; i<6; i++) normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen3[i])/2, starty+normal->get_text_height()*i, txt_screen3[i]); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for 20 seonds (only 8 at the moment) for (i = 0; i < 80; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); if (wait_delay (10)) break; // Text Screen 4 // Paint backgound black win->fill8(0,gwin->get_width(),gwin->get_height(),0,0); const char *txt_screen4[] = { "That is another story...", "one that will take you", "to a place called", "The Serpent Isle..." }; starty = (gwin->get_height() - normal->get_text_height()*4)/2; for(i=0; i<4; i++) normal->draw_text (ibuf, centerx-normal->get_text_width(txt_screen4[i])/2, starty+normal->get_text_height()*i, txt_screen4[i]); // Fade in for 1 sec (50 cycles) pal->fade (50, 1, 0); // Display text for 10 seonds (only 5 at the moment) for (i = 0; i < 50; i++) if (wait_delay (100)) { do_break = true; break; } if (do_break) break; // Fade out for 1 sec (50 cycles) pal->fade (50, 0, 0); } while (0); if (audio) { audio->stop_music(); MyMidiPlayer *midi = audio->get_midi(); if (midi) midi->load_patches(false); } gwin->clear_screen(true); FORGET_ARRAY(buffer); FORGET_ARRAY(fli_b[0]); FORGET_ARRAY(fli_b[1]); FORGET_ARRAY(fli_b[2]); } void BG_Game::show_quotes() { play_midi(quotes_midi); TextScroller quotes(MAINSHP_FLX, 0x10, fontManager.get_font("MENU_FONT"), menushapes.extract_shape(0x14) ); gwin->get_pal()->load("/intropal.dat",6); quotes.run(gwin); gwin->get_pal()->load("/intropal.dat",0); } void BG_Game::show_credits() { play_midi(credits_midi); TextScroller credits(MAINSHP_FLX, 0x0E, fontManager.get_font("MENU_FONT"), menushapes.extract_shape(0x14) ); gwin->get_pal()->load("/intropal.dat",6); if(credits.run(gwin)) { // Watched through the entire sequence? std::ofstream quotesflg; U7open(quotesflg, "/quotes.flg"); quotesflg.close(); } gwin->get_pal()->load("/intropal.dat",0); } bool BG_Game::new_game(Vga_file &shapes) { SDL_EnableUNICODE(1); int menuy = topy+110; Font *font = fontManager.get_font("MENU_FONT"); // Need to know if SI is installed bool si_installed = SI_Game::is_installed(); U7object faces_u7o("/exult_bg.flx", EXULT_BG_FLX_MR_INTRO_SHP); size_t shapesize; char *shape_buf = faces_u7o.retrieve(shapesize); BufferDataSource faces_ds(shape_buf, shapesize); Shape_file faces_shape(&faces_ds); const int max_name_len = 16; char npc_name[max_name_len+1]; char disp_name[max_name_len+2]; npc_name[0] = 0; int sex = 0; int selected = 0; int num_choices = 4; gwin->get_pal()->load("/intropal.dat",6); SDL_Event event; bool editing = true; bool redraw = true; bool ok = true; do { if (redraw) { win->fill8(0,gwin->get_width(),90,0,menuy); sman->paint_shape(topx+10,menuy+10,shapes.get_shape(0xC, selected==0?1:0)); Shape_frame *sex_shape = shapes.get_shape(0xA, selected==1?1:0); sman->paint_shape(topx+10,menuy+25,sex_shape); int sex_width = sex_shape->get_width()+10; if (sex_width > 35) sex_width += 25; else sex_width = 60; if (si_installed) { sman->paint_shape(topx+sex_width,menuy+25,shapes.get_shape(0xB,sex%2)); if (sex >= 2) { sman->paint_shape(topx+250,menuy+10,faces_shape.get_frame(7-sex)); } else sman->paint_shape(topx+250,menuy+10,shapes.get_shape(sex,0)); } else { sman->paint_shape(topx+sex_width,menuy+25,shapes.get_shape(0xB,sex)); sman->paint_shape(topx+250,menuy+10,shapes.get_shape(sex,0)); } sman->paint_shape(topx+10,topy+180,shapes.get_shape(0x8,selected==2?1:0)); sman->paint_shape(centerx+10,topy+180,shapes.get_shape(0x7,selected==3?1:0)); if(selected==0) snprintf(disp_name, max_name_len+2, "%s_", npc_name); else snprintf(disp_name, max_name_len+2, "%s", npc_name); font->draw_text(ibuf, topx+60, menuy+10, disp_name); gwin->get_pal()->apply(); redraw = false; } SDL_WaitEvent(&event); if(event.type==SDL_KEYDOWN) { redraw = true; switch(event.key.keysym.sym) { case SDLK_SPACE: if(selected==0) { int len = strlen(npc_name); if(len= 8) sex = 0; } else sex = !sex; } else if(selected==2) { editing=false; ok = true; } else if(selected==3) { editing = false; ok = false; } break; case SDLK_LEFT: if(selected==1) { if (si_installed) { sex--; if (sex < 0) sex = 7; } else sex = !sex; } break; case SDLK_RIGHT: if(selected==1) { if (si_installed) { sex++; if (sex >= 8) sex = 0; } else sex = !sex; } break; case SDLK_ESCAPE: editing = false; ok = false; break; case SDLK_TAB: case SDLK_DOWN: ++selected; if(selected==num_choices) selected = 0; break; case SDLK_UP: --selected; if(selected<0) selected = num_choices-1; break; case SDLK_RETURN: if(selected<2) ++selected; else if(selected==2) { editing=false; ok = true; } else { editing = false; ok = false; } break; case SDLK_BACKSPACE: if(selected==0) { if(strlen(npc_name)>0) npc_name[strlen(npc_name)-1] = 0; } break; default: { if (selected == 0) // on the text input field? { int len = strlen(npc_name); char chr = 0; if ((event.key.keysym.unicode & 0xFF80) == 0) chr = event.key.keysym.unicode & 0x7F; if (chr >= ' ' && len < max_name_len) { npc_name[len] = chr; npc_name[len+1] = 0; } } else { redraw = false; } } break; } } } while(editing); FORGET_ARRAY(shape_buf); if(ok) { #ifdef DEBUG std::cout << "Skin is: " << (3-(sex/2)) << " Sex is: " << (sex%2) << std::endl; #endif set_avskin(3-(sex/2)); set_avname (npc_name); set_avsex (sex%2); gwin->get_pal()->fade_out(c_fade_out_time); gwin->clear_screen(true); ok =gwin->init_gamedat(true); } win->fill8(0,gwin->get_width(),90,0,menuy); SDL_EnableUNICODE(0); return ok; } bool BG_Game::is_installed() { std::string buf("/endgame.dat"); bool foundbg = U7exists(buf); bool foundbgflx = U7exists("/exult_bg.flx"); if (foundbg) std::cout << "Black Gate : found" << std::endl; else std::cout << "Black Gate : not found (" << get_system_path(buf) << ")" << std::endl; if (foundbgflx) std::cout << "exult_bg.flx : found" << std::endl; else std::cout << "exult_bg.flx : not found (" << get_system_path("/exult_bg.flx") << ")" << std::endl; return (foundbg && foundbgflx); } exult-1.2/effects.h0000644000175000001440000002435607724430447010007 /* * effects.h - Special effects. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef EFFECTS_H #define EFFECTS_H 1 #include #include "tqueue.h" #include "tiles.h" #include "singles.h" class Xform_palette; class PathFinder; class Game_object; class Game_window; class Image_window8; class Shape_frame; class Actor; class Special_effect; class Text_effect; /* * Manage special effects. */ class Effects_manager { Game_window *gwin; // Handy pointer. Special_effect *effects; // Sprite effects, projectiles, etc. Text_effect *texts; // Text snippets. public: Effects_manager(Game_window *g) : gwin(g), effects(0), texts(0) { } ~Effects_manager(); // Add text item. void add_text(const char *msg, Game_object *item); void add_text(const char *msg, int x, int y); void center_text(const char *msg); void add_effect(Special_effect *effect); void add_text_effect(Text_effect *txt); void remove_text_effect(Game_object *item); // Remove text item & delete it. void remove_effect(Special_effect *effect); void remove_text_effect(Text_effect *txt); void remove_all_effects(bool repaint=false); void remove_text_effects(); // Remove just the weather. void remove_weather_effects(int dist = 0); int get_weather(); // Get # of last weather added. void paint(); // Draw all sprites/proj./weather. void paint_text(); // Draw text. }; /* * Base class for special-effects: */ class Special_effect : public Time_sensitive, public Game_singletons { Special_effect *next, *prev; // All of them are chained together. public: friend class Effects_manager; Special_effect() : next(0), prev(0) { } virtual ~Special_effect() { } // Render. virtual void paint(); virtual int is_weather() // Need to distinguish weather. { return 0; } }; /* * An animation from 'sprites.vga': */ class Sprites_effect : public Special_effect { protected: ShapeID sprite; //int sprite_num; // Which one. //int frame_num; // Current frame. int frames; // # frames. Game_object *item; // Follows this around if not null. Tile_coord pos; // Position within world. int xoff, yoff; // Offset from position in pixels. int deltax, deltay; // Add to xoff, yoff on each frame. void add_dirty(int frnum); public: Sprites_effect(int num, Tile_coord p, int dx = 0, int dy = 0, int delay = 0); Sprites_effect(int num, Game_object *it, int xf, int yf, int dx, int dy); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); // Render. virtual void paint(); }; /* * An explosion. */ class Explosion_effect : public Sprites_effect { Game_object *explode; // What's exploding, or 0. int weapon; // Weapon to use for attack values. public: Explosion_effect(Tile_coord p, Game_object *exp, int delay = 0, int weap = -1); virtual void handle_event(unsigned long time, long udata); }; /* * A moving animation, followed by an 'attack' at the end, to * implement Usecode intrinsic 0x41: */ class Projectile_effect : public Special_effect { Actor *attacker; // Source of attack/spell. Game_object *target; // Target of path. int projectile_shape; // Shape # of projectile/spell. ShapeID sprite; // Sprite shape to display. int weapon; // Shape # of firing weapon, or 0. int frames; // # frames. PathFinder *path; // Determines path. Tile_coord pos; // Current position. bool return_path; // Returning a boomerang. bool no_blocking; // Don't get blocked by things. // Add dirty rectangle. void add_dirty(); void init(Tile_coord s, Tile_coord t); public: Projectile_effect(Actor *att, Game_object *to, int shnum, int weap = 0); // For missile traps: Projectile_effect(Tile_coord s, Tile_coord d, int shnum, int weap); Projectile_effect(Tile_coord s, Game_object *to, int shnum, int weap, bool retpath = false); ~Projectile_effect(); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); // Render. virtual void paint(); }; /* * 'Death Vortex', from the spell. (Maybe this could be a * Sprites_effect.) */ class Death_vortex : public Special_effect { ShapeID vortex; Actor *target; // We'll follow this around if not 0. Tile_coord pos; // Current position. int frames; // # frames. uint32 stop_time; // Time in 1/1000 secs. to stop. uint32 next_damage_time; // When to check for NPC's beneath us. int add_dirty(); public: Death_vortex(Game_object *trg, Tile_coord tp); // For Time_sensitive: virtual void handle_event(unsigned long time, long udata); // Render. virtual void paint(); }; /* * A text object is a message that stays on the screen for just a couple * of seconds. These are all kept in a single list, and managed by * Game_window. */ class Text_effect : public Time_sensitive, public Game_singletons { Text_effect *next, *prev; // All of them are chained together. std::string msg; // What to print. Game_object *item; // Item text is on. May be null. Tile_coord pos; // Position to display it at. short width, height; // Dimensions of rectangle. int num_ticks; // # ticks passed. void add_dirty(); void init(); public: friend class Effects_manager; Text_effect(const std::string &m, Game_object *it); Text_effect(const std::string &m, int t_x, int t_y); // At timeout, remove from screen. virtual void handle_event(unsigned long curtime, long udata); // Render. virtual void paint(); // Check for matching item. int is_text(Game_object *it) { return it == item; } }; /* * Weather. */ class Weather_effect : public Special_effect { protected: uint32 stop_time; // Time in 1/1000 secs. to stop. int num; // Weather ID (0-6), or -1. Tile_coord eggloc; // Location of egg that started this. public: Weather_effect(int duration, int delay, int n, Game_object *egg = 0); virtual ~Weather_effect() { } // Avatar out of range? int out_of_range(Tile_coord& avpos, int dist); virtual int is_weather() { return 1; } int get_num() { return num; } }; /* * A raindrop: */ class Raindrop { unsigned char oldpix; // Pixel originally on screen. unsigned char yperx; // Move this many y-pixels for each x. long ax, ay; // Coords. where drawn in abs. pixels. public: Raindrop() : oldpix(0xff), yperx(1), ax(-1), ay(-1) { } void paint(Image_window8 *iwin, int scrolltx, int scrollty, Xform_palette& xform); // Move to next position. void next(Image_window8 *iwin, int scrolltx, int scrollty, Xform_palette& xform, int w, int h); void next_random(Image_window8 *iwin, int scrolltx, int scrollty, Xform_palette& xform, int w, int h); }; /* * Raining. */ class Rain_effect : public Weather_effect { protected: #define MAXDROPS 200 Raindrop drops[MAXDROPS]; // Drops moving down the screen. int num_drops; // # to actually use. public: Rain_effect(int duration, int delay = 0, int ndrops = MAXDROPS, int n = -1, Game_object *egg = 0) : Weather_effect(duration, delay, n, egg), num_drops(ndrops) { } // Execute when due. virtual void handle_event(unsigned long curtime, long udata); // Render. virtual void paint(); }; /* * Lightning. */ class Lightning_effect : public Weather_effect { static int active; // Just want one at a time. bool flashing; // Lightning palette is set. friend class Storm_effect; public: Lightning_effect(int duration, int delay = 0) : Weather_effect(duration, delay, -1), flashing(false) { } ~Lightning_effect(); // Execute when due. virtual void handle_event(unsigned long curtime, long udata); }; /* * Storm. */ class Storm_effect : public Weather_effect { int start; // 1 to start storm. public: Storm_effect(int duration, int delay = 0, Game_object *egg = 0); // Execute when due. virtual void handle_event(unsigned long curtime, long udata); virtual ~Storm_effect(); }; /* * Ambrosia's 'twinkling rain'. */ class Sparkle_effect : public Rain_effect { public: Sparkle_effect(int duration, int delay = 0, Game_object *egg = 0) // Weather #3. : Rain_effect(duration, delay, 50, 3, egg) { } // Execute when due. virtual void handle_event(unsigned long curtime, long udata); }; /* * A single cloud (sprite shape 2): */ class Cloud { ShapeID cloud; long wx, wy; // Position within world. short deltax, deltay; // How to move. int count; // Counts down to 0. int max_count; uint32 start_time; // When to start. static int randcnt; // For generating random times. void set_start_pos(Shape_frame *shape, int w, int h, int& x, int& y); public: Cloud(short dx, short dy); // Move to next position & paint. void next(Game_window *gwin, unsigned long curtime, int w, int h); void paint(); }; /* * Clouds. */ class Clouds_effect : public Weather_effect { int num_clouds; Cloud **clouds; // ->clouds. public: Clouds_effect(int duration, int delay = 0, Game_object *egg = 0); // Execute when due. virtual void handle_event(unsigned long curtime, long udata); // Render. virtual void paint(); virtual ~Clouds_effect() { delete [] clouds; } }; /* * Earthquakes. +++++Might make this a Weather_effect. */ class Earthquake : public Time_sensitive { int len; // From Usecode intrinsic. int i; // Current index. public: Earthquake(int l) : len(l), i(0) { } // Execute when due. virtual void handle_event(unsigned long curtime, long udata); }; /* * A fire field that dies out after a few seconds. */ class Fire_field_effect : public Special_effect { Game_object *field; // What we create. public: Fire_field_effect(Tile_coord t); virtual void handle_event(unsigned long curtime, long udata); }; #endif exult-1.2/combat_opts.h0000644000175000001440000000253007724430447010670 /* * Combat_opts.h - Combat options. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef COMBAT_OPTS_H #define COMBAT_OPTS_H 1 /* * Combat options: */ class Combat : public Game_singletons { static bool paused; // For suspending. public: static int difficulty; // 0=normal, >0 harder, <0 easier. enum Mode { original = 0, // All automatic, keypause = 1 // Kbd (space) suspends/resumes. }; static Mode mode; static bool show_hits; // Display #'s. // In game: static void toggle_pause(); // Pause/resume. static void resume(); // Always resume. static bool is_paused() { return paused; } }; #endif exult-1.2/effects.cc0000644000175000001440000010433310054030530010112 /* * effects.h - Special effects. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include "gamewin.h" #include "gamemap.h" #include "gameclk.h" #include "actors.h" #include "effects.h" #include "Zombie.h" #include "dir.h" #include "chunks.h" #include "Audio.h" #include "Gump_manager.h" #include "game.h" #include "Gump.h" #include "egg.h" #include "SDL_timer.h" #ifndef UNDER_CE using std::cout; using std::endl; using std::rand; using std::string; using std::strlen; #endif int Cloud::randcnt = 0; int Lightning_effect::active = 0; /* * Clean up. */ Effects_manager::~Effects_manager() { remove_all_effects(false); } /* * Add text over a given item. */ void Effects_manager::add_text ( const char *msg, Game_object *item // Item text ID's, or null. ) { if (!msg) // Happens with edited games. return; // Don't duplicate for item. for (Text_effect *each = texts; each; each = each->next) if (each->is_text(item)) return; // Already have text on this. Text_effect *txt = new Text_effect(msg, item); // txt->paint(this); // Draw it. // painted = 1; add_text_effect(txt); } /* * Add a text object at a given spot. */ void Effects_manager::add_text ( const char *msg, int x, int y // Pixel coord. on screen. ) { Text_effect *txt = new Text_effect(msg, gwin->get_scrolltx() + x/c_tilesize, gwin->get_scrollty() + y/c_tilesize); add_text_effect(txt); } /* * Add a text object in the center of the screen */ void Effects_manager::center_text ( const char *msg ) { remove_text_effects(); Shape_manager *sman = Shape_manager::get_instance(); add_text(msg, (gwin->get_width()-sman->get_text_width(0,msg))/2, gwin->get_height()/2); } /* * Add an effect at the start of the chain. */ void Effects_manager::add_effect ( Special_effect *effect ) { effect->next = effects; // Insert into chain. effect->prev = 0; if (effect->next) effect->next->prev = effect; effects = effect; } /* * Add a text effect at the start of the chain. */ void Effects_manager::add_text_effect ( Text_effect *effect ) { effect->next = texts; // Insert into chain. effect->prev = 0; if (effect->next) effect->next->prev = effect; texts = effect; } /* * Remove a given object's text effect. */ void Effects_manager::remove_text_effect ( Game_object *item // Item text was added for. ) { for (Text_effect *each = texts; each; each = each->next) if (each->is_text(item)) { // Found it. remove_text_effect(each); gwin->paint(); return; } } /* * Remove a sprite from the chain and delete it. */ void Effects_manager::remove_effect ( Special_effect *effect ) { if (effect->in_queue()) gwin->get_tqueue()->remove(effect); if (effect->next) effect->next->prev = effect->prev; if (effect->prev) effect->prev->next = effect->next; else // Head of chain. effects = effect->next; delete effect; } /* * Remove text from the chain and delete it. */ void Effects_manager::remove_text_effect ( Text_effect *txt ) { if (txt->in_queue()) gwin->get_tqueue()->remove(txt); if (txt->next) txt->next->prev = txt->prev; if (txt->prev) txt->prev->next = txt->next; else // Head of chain. texts = txt->next; delete txt; } /* * Remove all text items. */ void Effects_manager::remove_all_effects ( bool repaint ) { if (!effects && !texts) return; while (effects) remove_effect(effects); while (texts) remove_text_effect(texts); if (repaint) gwin->paint(); // Just paint whole screen. } /* * Remove text effects. */ void Effects_manager::remove_text_effects ( ) { while (texts) remove_text_effect(texts); gwin->set_all_dirty(); } /* * Remove weather effects. */ void Effects_manager::remove_weather_effects ( int dist // Only remove those from eggs at // least this far away. ) { Actor *main_actor = gwin->get_main_actor(); Tile_coord apos = main_actor ? main_actor->get_tile() : Tile_coord(-1, -1, -1); Special_effect *each = effects; while (each) { Special_effect *next = each->next; // See if we're far enough away. if (each->is_weather() && (!dist || ((Weather_effect *) each)->out_of_range(apos, dist))) remove_effect(each); each = next; } gwin->set_all_dirty(); } /* * Find last numbered weather effect added. */ int Effects_manager::get_weather ( ) { Special_effect *each = effects; while (each) { Special_effect *next = each->next; if (each->is_weather()) { Weather_effect *weather = (Weather_effect *) each; if (weather->get_num() >= 0) return weather->get_num(); } each = next; } return 0; } /* * Paint them all. */ void Effects_manager::paint ( ) { for (Special_effect *effect = effects; effect; effect = effect->next) effect->paint(); } /* * Paint all text. */ void Effects_manager::paint_text ( ) { for (Text_effect *txt = texts; txt; txt = txt->next) txt->paint(); } /* * Some special effects may not need painting. */ void Special_effect::paint ( ) { } /* * Create an animation from the 'sprites.vga' file. */ Sprites_effect::Sprites_effect ( int num, // Index. Tile_coord p, // Position within world. int dx, int dy, // Add to offset for each frame. int delay // Delay (msecs) before starting. ) : sprite(num, 0, SF_SPRITES_VGA), item(0), pos(p), xoff(0), yoff(0), deltax(dx), deltay(dy) { Game_window *gwin = Game_window::get_instance(); frames = sprite.get_num_frames(); // Start. gwin->get_tqueue()->add(Game::get_ticks() + delay, this, 0L); } /* * Create an animation on an object. */ Sprites_effect::Sprites_effect ( int num, // Index. Game_object *it, // Item to put effect by. int xf, int yf, // Offset from actor in pixels. int dx, int dy // Add to offset on each frame. ) : sprite(num, 0, SF_SPRITES_VGA), item(it), xoff(xf), yoff(yf), deltax(dx), deltay(dy) { pos = item->get_tile(); Game_window *gwin = Game_window::get_instance(); frames = sprite.get_num_frames(); // Start immediately. gwin->get_tqueue()->add(Game::get_ticks(), this, 0L); } /* * Add a dirty rectangle for the current position and frame. */ inline void Sprites_effect::add_dirty ( int frnum ) { if (pos.tx == -1 || frnum == -1) return; // Already at destination. Shape_frame *shape = sprite.get_shape(); int lp = pos.tz/2; gwin->add_dirty(gwin->clip_to_win(gwin->get_shape_rect(shape, xoff + (pos.tx - lp - gwin->get_scrolltx())*c_tilesize, yoff + (pos.ty - lp - gwin->get_scrollty())*c_tilesize).enlarge(12))); } /* * Animation. */ void Sprites_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { int frame_num = sprite.get_framenum(); Game_window *gwin = Game_window::get_instance(); int delay = gwin->get_std_delay();// Delay between frames. Needs to // match usecode animations. if (frame_num == frames) // At end? { // Remove & delete this. eman->remove_effect(this); gwin->set_all_dirty(); return; } add_dirty(frame_num); // Clear out old. gwin->set_painted(); if (item) // Following actor? pos = item->get_tile(); xoff += deltax; // Add deltas. yoff += deltay; frame_num++; // Next frame. add_dirty(frame_num); // Want to paint new frame. sprite.set_frame(frame_num); // Add back to queue for next time. gwin->get_tqueue()->add(curtime + delay, this, udata); } /* * Render. */ void Sprites_effect::paint ( ) { if (sprite.get_framenum() >= frames) return; int lp = pos.tz/2; // Account for lift. sprite.paint_shape( xoff + (pos.tx - lp - gwin->get_scrolltx())*c_tilesize, yoff + (pos.ty - lp - gwin->get_scrollty())*c_tilesize); } /* * Start explosion. */ Explosion_effect::Explosion_effect ( Tile_coord p, Game_object *exp, int delay, // Delay before starting (msecs). int weap // Weapon to use for damage calcs., or // -1 for default(704 = poweder keg). ) : Sprites_effect(1, p, 0, 0, delay), explode(exp), weapon(weap >= 0 ? weap : 704) { if (exp && exp->get_shapenum() == 704) { // powderkeg exp->set_quality(1); // mark as detonating } } void Explosion_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { int frnum = sprite.get_framenum(); if (!frnum) // Max. volume, with stereo position. { Tile_coord apos = gwin->get_main_actor()->get_tile(); int dir = Get_direction16(apos.ty - pos.ty, pos.tx - apos.tx); Audio::get_ptr()->play_sound_effect( Audio::game_sfx(9), SDL_MIX_MAXVOLUME, dir); } if (frnum == frames/4) { // this was in ~Explosion_effect before if (explode && !explode->is_pos_invalid()) { Game_window::get_instance()->add_dirty(explode); explode->remove_this(); explode = 0; } Game_object_vector vec; // Find objects near explosion. Game_object::find_nearby(vec, pos, c_any_shapenum, 5, 0); for (Game_object_vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { (**it).attacked(0, -704, 0); } } Sprites_effect::handle_event(curtime, udata); } /* * Get direction in 1/16's starting from North. */ inline int Get_dir16 ( Tile_coord& t1, Tile_coord& t2 ) { // Treat as cartesian coords. return Get_direction16(t1.ty - t2.ty, t2.tx - t1.tx); } /* * Initialize path & add to time queue. */ void Projectile_effect::init ( Tile_coord s, // Source, Tile_coord d // Destination. ) { no_blocking = false; // We'll check the ammo & weapon. Game_window *gwin = Game_window::get_instance(); Shape_info& info = ShapeID::get_info(projectile_shape); Weapon_info *winfo = info.get_weapon_info(); if (winfo) { if (winfo->get_projectile()) // Different sprite to show? sprite.set_shape(winfo->get_projectile()); no_blocking = no_blocking || winfo->no_blocking(); } Ammo_info *ainfo = info.get_ammo_info(); if (ainfo) no_blocking = no_blocking || ainfo->no_blocking(); frames = sprite.get_num_frames(); pos = s; // Get starting position. if (attacker) // Try to set start better. { Shape_info& info = attacker->get_info(); // Try for around the heat. pos.tz += info.get_3d_height() - 1; if (d.tx < pos.tx) // Start on proper side. pos.tx -= info.get_3d_xtiles(); else pos.tx++; if (d.ty < pos.ty) pos.ty -= info.get_3d_ytiles(); else pos.ty++; } path = new Zombie(); // Create simple pathfinder. // Find path. Should never fail. path->NewPath(pos, d, 0); if (frames >= 24) // Use frames 8-23, for direction { // going clockwise from North. int dir = Get_dir16(s, d); sprite.set_frame(8 + dir); } else if (frames == 1 && sprite.get_shapenum() != 704) sprite.set_frame(0); // (Don't show powder keg!) else sprite.set_frame(-1); // We just won't show it. // Start immediately. gwin->get_tqueue()->add(Game::get_ticks(), this, 0L); } /* * Create a projectile animation. */ Projectile_effect::Projectile_effect ( Actor *att, // Source of spell/attack. Game_object *to, // End here, 'attack' it with shape. int shnum, // Projectile shape # in 'shapes.vga'. int weap // Weapon (bow, gun, etc.) shape, or 0. ) : attacker(att), target(to), projectile_shape(shnum), sprite(shnum, 0), weapon(weap), return_path(false) { init(attacker->get_tile(), to->get_tile()); } /* * Constructor used by missile eggs. */ Projectile_effect::Projectile_effect ( Tile_coord s, // Start here. Tile_coord d, // End here. int shnum, // Projectile shape int weap // Weapon (bow, gun, etc.) shape, or 0. ) : attacker(0), target(0), projectile_shape(shnum), sprite(shnum, 0), weapon(weap), return_path(false) { init(s, d); } /* * Another used by missile eggs. */ Projectile_effect::Projectile_effect ( Tile_coord s, // Start here. Game_object *to, // End here, 'attack' it with shape. int shnum, // Projectile shape int weap, // Weapon (bow, gun, etc.) shape, or 0. bool retpath // Return of a boomerang. ) : attacker(0), target(to), projectile_shape(shnum), sprite(shnum, 0), weapon(weap), return_path(retpath) { init(s, to->get_tile()); } /* * Delete. */ Projectile_effect::~Projectile_effect ( ) { delete path; } /* * Add a dirty rectangle for the current position and frame. */ inline void Projectile_effect::add_dirty ( ) { if (pos.tx == -1 || sprite.get_framenum() == -1) return; // Already at destination. Shape_frame *shape = sprite.get_shape(); // Force repaint of prev. position. int liftpix = pos.tz*c_tilesize/2; gwin->add_dirty(gwin->clip_to_win(gwin->get_shape_rect(shape, (pos.tx - gwin->get_scrolltx())*c_tilesize - liftpix, (pos.ty - gwin->get_scrollty())*c_tilesize - liftpix).enlarge(4))); } /* * See if something was hit. * * Output: ->target hit, or 0. */ inline Game_object *Find_target ( Game_window *gwin, Tile_coord pos ) { if (pos.tz%5 == 0) // On floor? pos.tz++; // Look up 1 tile. Tile_coord dest = pos; // This gets modified. if (!Map_chunk::is_blocked(pos, 1, MOVE_FLY, 0) && dest == pos) return (0); return Game_object::find_blocking(pos); } /* * Animation. */ void Projectile_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); int delay = gwin->get_std_delay()/2; add_dirty(); // Force repaint of old pos. Tile_coord epos = pos; // Save pos. if (!path->GetNextStep(pos) || // Get next spot. // If missile egg, detect target. (!target && !no_blocking && (target = Find_target(gwin, pos)) != 0)) { // Done? int delay = 0; // For explosions. switch (projectile_shape) { case 287: // Swordstrike. eman->add_effect(new Sprites_effect(23, epos)); break; case 554: // Burst arrow. eman->add_effect(new Sprites_effect(19, epos)); break; case 565: // Starburst. eman->add_effect(new Sprites_effect(18, epos)); break; case 639: // Death Vortex. eman->add_effect(new Death_vortex(target, epos)); target = 0; // Takes care of attack. break; case 82: // Delayed explosion. case 621: // " " delay = 3000; // Wait 3 secs. FALL THROUGH! case 78: // Explosion. case 702: // Cannon. case 704: // Powder keg. eman->add_effect(new Explosion_effect(epos, 0, delay)); target = 0; // Takes care of attack. break; } if (return_path) // Returned a boomerang? target->add(gmap->create_ireg_object(weapon, 0)); else { // Not teleported away ? if (target && epos.distance(target->get_tile()) < 50) target->attacked(attacker, weapon, projectile_shape); if (attacker && // Check for `boomerangs' weapon == projectile_shape && epos.distance(attacker->get_tile() ) < 50) { // not teleported away Weapon_info *winf = ShapeID::get_info(weapon).get_weapon_info(); if (winf && winf->returns()) eman->add_effect(new Projectile_effect( pos, attacker, weapon, weapon, true)); } } add_dirty(); pos.tx = -1; // Signal we're done. eman->remove_effect(this); return; } add_dirty(); // Paint new spot/frame. // Add back to queue for next time. gwin->get_tqueue()->add(curtime + delay, this, udata); } /* * Render. */ void Projectile_effect::paint ( ) { if (pos.tx == -1 || sprite.get_framenum() == -1) return; // Already at destination. int liftpix = pos.tz*c_tilesize/2; sprite.paint_shape( (pos.tx - gwin->get_scrolltx())*c_tilesize - liftpix, (pos.ty - gwin->get_scrollty())*c_tilesize - liftpix); } /* * Create a 'death vortex'. */ Death_vortex::Death_vortex ( Game_object *trg, // What to aim for. Tile_coord tp // Target pos, if trg==0. ) : vortex(8, 0, SF_SPRITES_VGA), next_damage_time(0) { pos = trg ? trg->get_tile() : tp; target = trg ? trg->as_actor() : 0; Game_window *gwin = Game_window::get_instance(); frames = vortex.get_num_frames(); // Go for 20 seconds. stop_time = Game::get_ticks() + 20*1000; // Start immediately. gwin->get_tqueue()->add(Game::get_ticks(), this, 0L); } /* * Add a dirty rectangle for the current position and frame. * * Output: Width in pixels. */ inline int Death_vortex::add_dirty ( ) { Shape_frame *shape = vortex.get_shape(); int liftpix = pos.tz*c_tilesize/2; gwin->add_dirty(gwin->clip_to_win(gwin->get_shape_rect(shape, (pos.tx - gwin->get_scrolltx())*c_tilesize - liftpix, (pos.ty - gwin->get_scrollty())*c_tilesize - liftpix).enlarge(4))); return shape->get_width(); } /* * Animation. */ void Death_vortex::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); int width = add_dirty(); // Repaint old area. if (target && !target->is_dead()) // Follow target. { Tile_coord tpos = target->get_tile(); int deltax = tpos.tx - pos.tx, deltay = tpos.ty - pos.ty; int absx = deltax >= 0 ? deltax : -deltax; int absy = deltay >= 0 ? deltay : -deltay; if (absx > 2 || absy > 2) { if (deltax) pos.tx += deltax/absx; if (deltay) pos.ty += deltay/absy; } } if (curtime > next_damage_time) // Time to cause damage. { // Do it every second. next_damage_time = curtime + 1000; Actor_vector npcs; // Find NPC's. Game_object::find_nearby(npcs, pos, -1, width/(2*c_tilesize), 8); for (Actor_vector::const_iterator it = npcs.begin(); it != npcs.end(); ++it) { Actor *npc = *it; if (!npc->is_in_party()) npc->reduce_health(40); } } vortex.set_frame((vortex.get_framenum() + 1)%frames); add_dirty(); // Paint new. if (curtime < stop_time) // Keep going? gwin->get_tqueue()->add(curtime + 100, this, udata); else { gwin->set_all_dirty(); eman->remove_effect(this); } } /* * Render. */ void Death_vortex::paint ( ) { int liftpix = pos.tz*c_tilesize/2; vortex.paint_shape( (pos.tx - gwin->get_scrolltx())*c_tilesize - liftpix, (pos.ty - gwin->get_scrollty())*c_tilesize - liftpix); } /* * Figure text position. */ static inline Tile_coord Figure_text_pos ( Game_object *item ) { Game_window *gwin = Game_window::get_instance(); Gump_manager *gumpman = gwin->get_gump_man(); Rectangle box; // See if it's in a gump. Gump *gump = gumpman->find_gump(item); if (gump) box = gump->get_shape_rect(item); else box = gwin->get_shape_rect(item->get_outermost()); return Tile_coord(gwin->get_scrolltx() + box.x/c_tilesize, gwin->get_scrollty() + box.y/c_tilesize, 0); } /* * Add dirty rectangle for current position. */ void Text_effect::add_dirty ( ) { Game_window *gwin = Game_window::get_instance(); // Repaint slightly bigger rectangle. Rectangle rect((pos.tx - gwin->get_scrolltx() - 1)*c_tilesize, (pos.ty - gwin->get_scrollty() - 1)*c_tilesize, width + 2*c_tilesize, height + 2*c_tilesize); gwin->add_dirty(gwin->clip_to_win(rect)); } /* * Initialize. */ void Text_effect::init ( ) { set_always(true); // Always execute in time queue, even // when paused. Game_window *gwin = Game_window::get_instance(); width = 8 + sman->get_text_width(0, msg.c_str()); height = 8 + sman->get_text_height(0); add_dirty(); // Force first paint. // Start immediately. gwin->get_tqueue()->add(Game::get_ticks(), this, 0L); if (msg[0] == '@') msg[0] = '"'; int len = msg.size(); if (msg[len - 1] == '@') msg[len - 1] = '"'; } /* * Create a text effect for a given object. */ Text_effect::Text_effect ( const string &m, // A copy is made. Game_object *it // Item text is on, or null. ) : msg(m), item(it), pos(Figure_text_pos(it)), num_ticks(0) { init(); } /* * Create a text object. */ Text_effect::Text_effect ( const string &m, // A copy is made. int t_x, int t_y // Abs. tile coords. ) : msg(m), item(0), pos(t_x, t_y, 0), num_ticks(0) { init(); } /* * Reposition if necessary. */ void Text_effect::handle_event ( unsigned long curtime, // Current time of day. long udata // Ignored. ) { Game_window *gwin = Game_window::get_instance(); if (++num_ticks == 10) // About 1-2 seconds. { // All done. add_dirty(); eman->remove_text_effect(this); return; } // Back into queue. gwin->get_tqueue()->add(Game::get_ticks() + gwin->get_std_delay(), this, 0L); if (!item) // Nothing to move? return; // See if moved. Tile_coord npos = Figure_text_pos(item); if (npos == pos) // No change? return; add_dirty(); // Force repaint of old area. pos = npos; // Then set to repaint new. add_dirty(); } /* * Render. */ void Text_effect::paint ( ) { const char *ptr = msg.c_str(); int len = strlen(ptr); sman->paint_text(0, ptr, len, (pos.tx - gwin->get_scrolltx())*c_tilesize, (pos.ty - gwin->get_scrollty())*c_tilesize); } /* * Init. a weather effect. */ Weather_effect::Weather_effect ( int duration, // Length in game minutes. int delay, // Delay before starting. int n, // Weather number. Game_object *egg // Egg that started it, or null. ) : num(n) { Game_window *gwin = Game_window::get_instance(); if (egg) eggloc = egg->get_tile(); else eggloc = Tile_coord(-1, -1, -1); stop_time = Game::get_ticks() + delay + 1000*((duration*60)/time_factor); // Start immediately. gwin->get_tqueue()->add(Game::get_ticks() + delay, this, 0L); } /* * Are we far enough away from this to cancel it? */ int Weather_effect::out_of_range ( Tile_coord& avpos, // Avatar's position. int dist // Distance in tiles to cancel at. ) { if (eggloc.tx == -1) // Not created by an egg? return 0; return eggloc.distance(avpos) >= dist; } /* * Paint raindrop. */ inline void Raindrop::paint ( Image_window8 *iwin, // Where to draw. int scrolltx, int scrollty, // Tile at top-left corner. Xform_palette& xform // Transform array. ) { uint32 ascrollx = scrolltx*(uint32)c_tilesize, ascrolly = scrollty*(uint32)c_tilesize; int x = ax - ascrollx, y = ay - ascrolly; if (x < 0 || y < 0 || x >= iwin->get_width() || y >= iwin->get_height()) return; if (oldpix == 255) oldpix = iwin->get_pixel8(x, y); // Get pixel. iwin->put_pixel8(xform[oldpix], x, y); } /* * Move raindrop. */ inline void Raindrop::next ( Image_window8 *iwin, // Where to draw. int scrolltx, int scrollty, // Tile at top-left corner. Xform_palette& xform, // Transform array. int w, int h // Dims. of window. ) { uint32 ascrollx = scrolltx*(uint32)c_tilesize, ascrolly = scrollty*(uint32)c_tilesize; int x = ax - ascrollx, y = ay - ascrolly; // Still on screen? Restore pix. if (x >= 0 && y >= 0 && x < w && y < h && oldpix != 255) iwin->put_pixel8(oldpix, x, y); oldpix = 255; // Time to restart? if (x < 0 || x >= w || y < 0 || y >= h) { int r = rand(); // Have a few fall faster. yperx = (r%4) ? 1 : 2; ax = ascrollx + r%(w - w/8); ay = ascrolly + r%(h - h/4); } else // Next spot. { int delta = 1 + rand()%4; ax += delta; ay += delta + yperx; } // Save old pixel & paint new. paint(iwin, scrolltx, scrollty, xform); } /* * Move raindrop. */ inline void Raindrop::next_random ( Image_window8 *iwin, // Where to draw. int scrolltx, int scrollty, // Tile at top-left corner. Xform_palette& xform, // Transform array. int w, int h // Dims. of window. ) { uint32 ascrollx = scrolltx*(uint32)c_tilesize, ascrolly = scrollty*(uint32)c_tilesize; int x = ax - ascrollx, y = ay - ascrolly; // Still on screen? Restore pix. if (x >= 0 && y >= 0 && x < w && y < h && oldpix != 255) iwin->put_pixel8(oldpix, x, y); oldpix = 255; // Pick new spot randomly. int newx = rand()%w, newy = rand()%h; ax = ascrollx + newx; ay = ascrolly + newy; // Save old pixel & paint new. paint(iwin, scrolltx, scrollty, xform); } /* * Rain. */ void Rain_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); if (!gwin->is_main_actor_inside() && !gumpman->showing_gumps(true)) { // Don't show rain inside buildings! Image_window8 *win = gwin->get_win(); int w = win->get_width(), h = win->get_height(); // Get transform table. Xform_palette& xform = sman->get_xform(8);//++++Experiment. int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty(); // Move drops. for (int i = 0; i < num_drops; i++) drops[i].next(win, scrolltx, scrollty, xform, w, h); gwin->set_painted(); } if (curtime < stop_time) // Keep going? gwin->get_tqueue()->add(curtime + 100, this, udata); else { gwin->set_all_dirty(); eman->remove_effect(this); } } /* * Paint rain. */ void Rain_effect::paint ( ) { if (gwin->is_main_actor_inside()) return; // Inside. // Get transform table. Xform_palette& xform = sman->get_xform(8);//++++Experiment. int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty(); Image_window8 *win = gwin->get_win(); for (int i = 0; i < num_drops; i++) drops[i].paint(win, scrolltx, scrollty, xform); gwin->set_painted(); } /* * End of lightning. */ Lightning_effect::~Lightning_effect ( ) { if (flashing) // Be sure palette is restored. Game_window::get_instance()->get_clock()->set_palette(); } /* * Lightning. */ void Lightning_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); int r = rand(); // Get a random #. int delay = 100; // Delay for next time. if (flashing) // Just turned white? Restore. { gclock->set_palette(); flashing = false; active = false; if (curtime >= stop_time) { // Time to stop. eman->remove_effect(this); return; } if (r%5 == 0) // Occassionally flash again. delay = (1 + r%7)*40; else // Otherwise, wait several secs. delay = (4000 + r%3000); } else if (!gwin->is_in_dungeon() && !active)// Time to flash. { // Play thunder. Audio::get_ptr()->play_sound_effect(Audio::game_sfx(62)); active = true; flashing = true; gwin->get_pal()->set(PALETTE_LIGHTNING); delay = (1 + r%2)*25; } gwin->get_tqueue()->add(curtime + delay, this, udata); } /* * Start a storm. */ Storm_effect::Storm_effect ( int duration, // In game minutes. int delay, // In msecs. Game_object *egg // Egg that caused it, or null. ) : Weather_effect(duration, delay, 2, egg), start(1) { Game_window *gwin = Game_window::get_instance(); // Start raining soon. int rain_delay = 20 + rand()%1000; eman->add_effect(new Rain_effect(duration - 1, rain_delay)); int lightning_delay = rain_delay + rand()%500; eman->add_effect(new Lightning_effect(duration - 1, lightning_delay)); } /* * Start/end of storm. */ void Storm_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); if (start) { start = 0; // Darken sky. gwin->get_clock()->set_storm(true); // Nothing more to do but end. gwin->get_tqueue()->add(stop_time, this, udata); } else // Must be time to stop. eman->remove_effect(this); } /* * Storm ended. */ Storm_effect::~Storm_effect ( ) { Game_window *gwin = Game_window::get_instance(); // Restore palette. gwin->get_clock()->set_storm(false); } /* * Sparkles (in Ambrosia). */ void Sparkle_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { Game_window *gwin = Game_window::get_instance(); if (!gwin->is_main_actor_inside()) { // Don't show rain inside buildings! Image_window8 *win = gwin->get_win(); int w = win->get_width(), h = win->get_height(); // Get transform table. Xform_palette& xform = sman->get_xform(8); int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty(); // Move drops to random spots. for (int i = 0; i < num_drops; i++) drops[i].next_random(win, scrolltx, scrollty, xform, w, h); gwin->set_painted(); } if (curtime < stop_time) // Keep going? gwin->get_tqueue()->add(curtime + 100, this, udata); else { gwin->set_all_dirty(); eman->remove_effect(this); } } /* * Create a cloud. */ const int CLOUD = 2; // Shape #. Cloud::Cloud ( short dx, short dy // Deltas for movement. ) : cloud(CLOUD, 0, SF_SPRITES_VGA), wx(0), wy(0), deltax(dx), deltay(dy), count(-1) { Game_window *gwin = Game_window::get_instance(); // Get abs. values. int adx = deltax > 0 ? deltax : -deltax; int ady = deltay > 0 ? deltay : -deltay; if (adx < ady) max_count = 2*gwin->get_height()/ady; else max_count = 2*gwin->get_width()/adx; start_time = 0; } /* * Set starting screen position according to direction. */ void Cloud::set_start_pos ( Shape_frame *shape, int w, int h, // Dims. of window. int& x, int& y // Screen pos. returned. ) { if (!deltax) // Special cases first. { x = rand()%w; y = deltay > 0 ? -shape->get_ybelow() : h + shape->get_yabove(); return; } if (!deltay) { y = rand()%h; x = deltax > 0 ? -shape->get_xright() : w + shape->get_xleft(); return; } int halfp = w + h; // 1/2 perimeter. int r = rand()%halfp; // Start on one of two sides. if (r > h) // Start on top/bottom. { x = r - h; y = deltay > 0 ? -shape->get_ybelow() : h + shape->get_yabove(); return; } y = r; // On left or right side. if (deltax > 0) // Going right? x = -shape->get_xright(); else // Going left? x = w + shape->get_xleft(); } /* * Move cloud */ inline void Cloud::next ( Game_window *gwin, // Game window. unsigned long curtime, // Current time of day. int w, int h // Dims. of window. ) { if (curtime < start_time) return; // Not yet. // Get top-left world pos. long scrollx = gwin->get_scrolltx()*c_tilesize; long scrolly = gwin->get_scrollty()*c_tilesize; Shape_frame *shape = cloud.get_shape(); gwin->add_dirty(gwin->clip_to_win(gwin->get_shape_rect( shape, wx - scrollx, wy - scrolly).enlarge(4))); if (count <= 0) // Time to restart? { // Set start time randomly. start_time = curtime + 2000*randcnt + rand()%2000; randcnt = (randcnt + 1)%4; start_time = Game::get_ticks() + 2000*randcnt + rand()%500; cout << "Cloud: start_time = " << start_time << endl; count = max_count; cloud.set_frame(rand()%cloud.get_num_frames()); int x, y; // Get screen pos. set_start_pos(shape, w, h, x, y); wx = x + scrollx; wy = y + scrolly; } else { wx += deltax; wy += deltay; count--; } gwin->add_dirty(gwin->clip_to_win(gwin->get_shape_rect( shape, wx - scrollx, wy - scrolly).enlarge(4))); } /* * Paint cloud. */ void Cloud::paint ( ) { Game_window *gwin = Game_window::get_instance(); if (count > 0) // Might not have been started. cloud.paint_shape(wx - gwin->get_scrolltx()*c_tilesize, wy - gwin->get_scrollty()*c_tilesize); } /* * Create a few clouds to float across the screen. */ Clouds_effect::Clouds_effect ( int duration, // In game minutes. int delay, // In msecs. Game_object *egg // Egg that caused it, or null. ) : Weather_effect(duration, delay, 6, egg) { num_clouds = 2 + rand()%5; // Pick #. clouds = new Cloud *[num_clouds]; // Figure wind direction. int dx = rand()%5 - 2; int dy = rand()%5 - 2; if (!dx && !dy) { dx = 1 + rand()%2; dy = 1 - rand()%3; } for (int i = 0; i < num_clouds; i++) { // Modify speed of some. int deltax = dx, deltay = dy; if (rand()%2 == 0) { deltax += deltax/2; deltay += deltay/2; } clouds[i] = new Cloud(deltax, deltay); } } /* * Cloud drift. */ void Clouds_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { const int delay = 100; Game_window *gwin = Game_window::get_instance(); if (curtime >= stop_time) { // Time to stop. eman->remove_effect(this); gwin->set_all_dirty(); return; } int w = gwin->get_width(), h = gwin->get_height(); for (int i = 0; i < num_clouds; i++) clouds[i]->next(gwin, curtime, w, h); gwin->get_tqueue()->add(curtime + delay, this, udata); } /* * Render. */ void Clouds_effect::paint ( ) { if (!gwin->is_main_actor_inside()) for (int i = 0; i < num_clouds; i++) clouds[i]->paint(); } /* * Shake the screen. */ void Earthquake::handle_event ( unsigned long curtime, // Current time of day. long udata ) { static int eqsoundonce; if(eqsoundonce != 1) { eqsoundonce = 1; // Play earthquake SFX once Audio::get_ptr()->play_sound_effect(Audio::game_sfx(60)); } Game_window *gwin = Game_window::get_instance(); Image_window *win = gwin->get_win(); int w = win->get_width(), h = win->get_height(); int sx = 0, sy = 0; int dx = rand()%9 - 4; int dy = rand()%9 - 4; if (dx > 0) w -= dx; else { w += dx; sx -= dx; dx = 0; } if (dy > 0) h -= dy; else { h += dy; sy -= dy; dy = 0; } win->copy(sx, sy, w, h, dx, dy); gwin->set_painted(); gwin->show(); // Shake back. win->copy(dx, dy, w, h, sx, sy); if (++i < len) // More to do? Put back in queue. gwin->get_tqueue()->add(curtime + 100, this, udata); else { eqsoundonce = 0; delete this; } } /* * Create a fire field that will last for about 4 seconds. */ Fire_field_effect::Fire_field_effect ( Tile_coord t // Where to create it. ) { field = gmap->create_ireg_object(895, 0); field->set_flag(Obj_flags::is_temporary); field->move(t.tx, t.ty, t.tz); gwin->get_tqueue()->add(Game::get_ticks() + 3000 + rand()%2000, this, 0L); } /* * Remove the field. */ void Fire_field_effect::handle_event ( unsigned long curtime, // Current time of day. long udata ) { int frnum = field->get_framenum(); if (frnum == 0) // All done? { field->remove_this(); eman->remove_effect(this); } else { if (frnum > 3) // Starting to wind down? { ((Animated_egg_object *) field)->stop_animation(); frnum = 3; } else frnum--; gwin->add_dirty(field); field->set_frame(frnum); gwin->get_tqueue()->add(curtime + gwin->get_std_delay(), this, udata); } } exult-1.2/alloc.cc0000644000175000001440000000403407724430447007607 /* * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #ifndef ALPHA_LINUX_CXX # include # include #endif #include #if 0 // Some people are having trouble with this #include // This allocator defines memset (we think) #else #ifndef ALPHA_LINUX_CXX # include #endif #endif unsigned long exult_mem = 0L; // Keep track of total memory allocated #ifdef WANT_ALTERNATE_ALLOCATOR #ifdef POISON_ALLOCATED_BLOCKS #undef INITIALISE_ALLOCATED_BLOCKS #define INITIALISE_ALLOCATED_BLOCKS 0xf1 #endif void *operator new (size_t) throw (std::bad_alloc); void *operator new[] (size_t) throw (std::bad_alloc); void *operator new(size_t n) throw (std::bad_alloc) { void *r; r=malloc(n); if(!r) throw std::bad_alloc(); #ifdef INITIALISE_ALLOCATED_BLOCKS memset(r,INITIALISE_ALLOCATED_BLOCKS,n); #endif exult_mem += n; return r; } void *operator new[](size_t n) throw (std::bad_alloc) { void *r=malloc(n); if(!r) throw std::bad_alloc(); #ifdef INITIALISE_ALLOCATED_BLOCKS memset(r,INITIALISE_ALLOCATED_BLOCKS,n); #endif exult_mem += n; return r; } void operator delete(void *p) throw() { if(p) free(p); // C++ doesn't throw if it's asked to delete // a null pointer } void operator delete[](void *p) throw() { if(p) free(p); } #endif exult-1.2/gamerend.h0000644000175000001440000000364107724430450010136 /* * gamerend.h - Rendering methods. * * Copyright (C) 1998-1999 Jeffrey S. Freedman * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GAMEREND_H #define GAMEREND_H 1 /* * A helper-class for rendering. */ class Game_render { unsigned long render_seq; // For marking rendered objects. int skip; // Set for each render. We skip // painting at or above this. public: Game_render() : render_seq(0), skip(31) { } void paint_terrain_only(int start_chunkx, int start_chunky, int stop_chunkx, int stop_chunky); // Render the map & objects. int paint_map(int x, int y, int w, int h); // Paint "flat" scenery in a chunk. void paint_chunk_flats(int cx, int cy, int xoff, int yoff); void paint_chunk_flat_rles(int cx, int cy, int xoff, int yoff); // // Paint blackness in a dungeon //void paint_dungeon_black(int cx, int cy, int xoff, int yoff, int index=0); // Paint objects in given chunk at // given lift. int paint_chunk_objects(int cx, int cy); // Paint an obj. after dependencies. void paint_object(Game_object *obj); // Render dungeon blackness void paint_blackness(int cx, int cy, int stop_chunkx, int stop_chunky, int index=0); }; #endif exult-1.2/singles.h0000644000175000001440000000246207724430450010020 /* * Copyright (C) 2000-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SINGLES_H #define SINGLES_H 1 /* * 'Singletons' used throughout the code. * NOTE: For now, the implementation is in shapeid.cc. */ class Game_singletons { protected: static class Game_window *gwin; static class Game_map *gmap; static class Effects_manager *eman; static class Shape_manager *sman; static class Usecode_machine *ucmachine; static class Game_clock *gclock; static class Palette *pal; static class Gump_manager *gumpman; static class Party_manager *partyman; public: static void init(Game_window *g); }; #endif exult-1.2/actions.h0000644000175000001440000002135307767762766010045 /* * actions.h - Action controllers for actors. * * Copyright (C) 2000-2001 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ACTIONS_H #define ACTIONS_H 1 #include "tiles.h" class Actor; class Game_object; class Tile_coord; class PathFinder; class Pathfinder_client; class If_else_path_actor_action; /* * This class controls the current actions of an actor: */ class Actor_action { static long seqcnt; // Sequence # to check for deletion. protected: bool get_party; // At each step (of the Avatar), have // the party follow. long seq; // 'unique' sequence #. public: Actor_action() : get_party(false) { seq = ++seqcnt; } virtual ~Actor_action() { } void set_get_party(bool tf = true) { get_party = true; } int handle_event_safely(Actor *actor, bool& deleted); // Handle time event. virtual int handle_event(Actor *actor) = 0; virtual void stop(Actor *actor) // Stop moving. { } // Set simple path to destination. virtual Actor_action *walk_to_tile(Actor *npc, Tile_coord src, Tile_coord dest, int dist = 0); // Set action to walk to dest, then // exec. another action when there. static Actor_action *create_action_sequence(Actor *actor, Tile_coord dest, Actor_action *when_there, bool from_off_screen = false); // Get destination, or ret. 0. virtual int get_dest(Tile_coord& dest) { return 0; } // Check for Astar. virtual int following_smart_path() { return 0; } virtual If_else_path_actor_action *as_usecode_path() { return 0; } }; /* * A null action just returns 0 the first time. */ class Null_action : public Actor_action { public: Null_action() { } virtual int handle_event(Actor *actor); }; /* * Follow a path. */ class Path_walking_actor_action : public Actor_action { protected: bool reached_end; // Reached end of path. PathFinder *path; // Allocated pathfinder. private: int original_dir; // From src. to dest. (0-7). int speed; // Time between frames. bool from_offscreen; // Walking from offscreen. Actor_action *subseq; // For opening doors. unsigned char blocked; // Blocked-tile retries. unsigned char max_blocked; // Try this many times. unsigned char blocked_frame; // Frame for blocked tile. Tile_coord blocked_tile; // Tile to retry. void set_subseq(Actor_action *sub) { delete subseq; subseq = sub; } public: Path_walking_actor_action(PathFinder *p = 0, int maxblk = 3); virtual ~Path_walking_actor_action(); static Path_walking_actor_action *create_path(Tile_coord src, Tile_coord dest, Pathfinder_client& cost); // Handle time event. virtual int handle_event(Actor *actor); int open_door(Actor *actor, Game_object *door); virtual void stop(Actor *actor);// Stop moving. // Set simple path to destination. virtual Actor_action *walk_to_tile(Actor *npc, Tile_coord src, Tile_coord dest, int dist = 0); // Get destination, or ret. 0. virtual int get_dest(Tile_coord& dest); // Check for Astar. virtual int following_smart_path(); }; /* * Follow a path to approach a given object, and stop half-way if it * moved. */ class Approach_actor_action : public Path_walking_actor_action { Game_object *dest_obj; // Destination object. Tile_coord orig_dest_pos; // Dest_obj's pos. when we start. int cur_step; // Count steps. int check_step; // Check at this step. public: Approach_actor_action(PathFinder *p, Game_object *d); // Handle time event. virtual int handle_event(Actor *actor); }; /* * Follow a path and execute one action if successful, another if * failed. */ class If_else_path_actor_action : public Path_walking_actor_action { bool succeeded, failed, done; Actor_action *success, *failure; public: If_else_path_actor_action(Actor *actor, Tile_coord dest, Actor_action *s, Actor_action *f = 0); ~If_else_path_actor_action(); void set_failure(Actor_action *f); bool done_and_failed() // Happens if no path found in ctor. { return done && failed; } // Handle time event. virtual int handle_event(Actor *actor); virtual If_else_path_actor_action *as_usecode_path() { return this; } }; /* * Just move (i.e. teleport) to a desired location. */ class Move_actor_action : public Actor_action { Tile_coord dest; // Where to go. public: Move_actor_action(Tile_coord d) : dest(d) { } // Handle time event. virtual int handle_event(Actor *actor); }; #if 0 /* +++Maybe not needed. */ /* * Approach an enemy during combat. */ class Combat_path_actor_action : public Actor_action { PathFinder *path; // Allocated pathfinder. int frame_index; // Index within frame sequence. public: Combat_path_walking_actor_action(PathFinder *p); virtual ~Combat_path_walking_actor_action(); // Handle time event. virtual int handle_event(Actor *actor); // Get destination, or ret. 0. virtual int get_dest(Tile_coord& dest); }; #endif /* * Activate an object. */ class Activate_actor_action : public Actor_action { Game_object *obj; public: Activate_actor_action(Game_object *o) : obj(o) { } // Handle time event. virtual int handle_event(Actor *actor); }; /* * Go through a series of frames. */ class Frames_actor_action : public Actor_action { signed char *frames; // List to go through (a -1 means to // leave frame alone.) int cnt; // Size of list. int index; // Index for next. int speed; // Frame delay in 1/1000 secs. Game_object *obj; // Object to animate public: Frames_actor_action(signed char *f, int c, int spd = 200, Game_object *o = 0); virtual ~Frames_actor_action() { delete [] frames; } // Handle time event. virtual int handle_event(Actor *actor); int get_index() { return index; } }; /* * Call a usecode function. */ class Usecode_actor_action : public Actor_action { int fun; // Fun. #. Game_object *item; // Call it on this item. int eventid; public: Usecode_actor_action(int f, Game_object *i, int ev) : fun(f), item(i), eventid(ev) { } // Handle time event. virtual int handle_event(Actor *actor); }; /* * Do a sequence of actions. */ class Sequence_actor_action : public Actor_action { Actor_action **actions; // List of actions, ending with null. int index; // Index into list. int speed; // Frame delay in 1/1000 secs. between // actions. public: // Create with allocated list. Sequence_actor_action(Actor_action **act, int spd = 100) : actions(act), index(0), speed(spd) { } // Create with up to 4. Sequence_actor_action(Actor_action *a0, Actor_action *a1, Actor_action *a2 = 0, Actor_action *a3 = 0); void set_speed(int spd) { speed = spd; } virtual ~Sequence_actor_action(); // Handle time event. virtual int handle_event(Actor *actor); }; // // The below could perhaps go into a highact.h file. // /* * Rotate through an object's frames. */ class Object_animate_actor_action : public Actor_action { Game_object *obj; int nframes; // # of frames. int cycles; // # of cycles to do. int speed; // Time between frames. public: Object_animate_actor_action(Game_object *o, int cy, int spd); Object_animate_actor_action(Game_object *o, int nframes, int cy, int spd); // Handle time event. virtual int handle_event(Actor *actor); }; /* * Action to pick up an item or put it down. */ class Pickup_actor_action : public Actor_action { Game_object *obj; // What to pick up/put down. int pickup; // 1 to pick up, 0 to put down. int speed; // Time between frames. int cnt; // 0, 1, 2. Tile_coord objpos; // Where to put it. int dir; // Direction to face. public: // To pick up an object: Pickup_actor_action(Game_object *o, int spd); // To put down an object: Pickup_actor_action(Game_object *o, Tile_coord opos, int spd); virtual int handle_event(Actor *actor); }; /* * Action to turn towards an object or spot. */ class Face_pos_actor_action : public Actor_action { int speed; // Time between frames. Tile_coord pos; // Where to put it. public: Face_pos_actor_action(Tile_coord p, int spd); // To pick up an object: Face_pos_actor_action(Game_object *o, int spd); virtual int handle_event(Actor *actor); }; #endif /* INCL_ACTIONS */ exult-1.2/ChangeLog0000644000175000001440000121766110062225256007762 2004-06-07 Ryan Nunn * msvcstuff/Exult.vcproj: Fixing compiling 2004-05-23 Dominik Reichardt * docs/xml/*.xml: updated documentations and FAQ * docs/*.html: updated documentations and FAQ * docs/ucc.txt: added command line options * Readme, FAQ: updated * Makefile.studio.mingw: installs necessary files for new games now as well 2004-05-22 * exult.cc: Skip intro if "development" game. * gumps/Face_stats.cc (Face_stats): Same for face stats. 2004-05-22 Willem Jan Palenstijn * gumps/Face_stats.cc: fix crash 2004-05-21 Ryan Nunn * various files: Some minor extremely changes that to compile for PocketPC 2004-05-10 Darke * vec.h objs/objiter.h: gcc3.4 'fixes'. 2004-04-27 Willem Jan Palenstijn * exulticon.h, exult.cc: set a window icon 2004-04-15 * actors.cc (Npc_actor): Removed code to set initial schedules in BG, since it sometimes caused former companions to wander off even when you told them to "Wait here". 2004-04-10 * cheat_screen.cc: Implement 'party' flag in cheat screen. 2004-03-12 Willem Jan Palenstijn * various: 1.1.11cvs 2004-03-08 Willem Jan Palenstijn * exult.spec.in: new desktop/ file locations 2004-02-29 Willem Jan Palenstijn * various: updated to 1.1.10rc2 2004-02-25 Willem Jan Palenstijn * configure.ac, mapedit/Makefile.am, mapedit/u7shp.c: made gimp plugin compile in both gimp 1.2.x and gimp 1.3/2.0(pre) 2004-02-25 Ryan Nunn * msvcstuff/*.* : Replacing MSVC 6.0 projects with MSVC.Net projects * other files: Removing some MSVC hacks * Since MSVC 6.0 is no longer going to be supported, and MSVC.Net is more standards compliant, if you are writing standards compliant code you shouldn't step on my toes anymore. 2004-02-24 Willem Jan Palenstijn * data/bg/custom_sword.shp: custom sword paperdoll art 2004-02-22 Willem Jan Palenstijn * actors.cc: paint NPCs translucently to prevent palette-cycling * shapes/shapevga.cc: removed Spark-translucency hack 2004-02-21 Willem Jan Palenstijn * desktop/*: put .desktop file in /usr/share/applications, icon in /usr/share/icons. 2004-02-19 Willem Jan Palenstijn * mapedit/studio.cc: fixed main_window not getting toplevel_focus 2004-02-18 Willem Jan Palenstijn * shapeid.h: fixed uninitialised member variable * mouse.cc: removed dynamic_cast 2004-02-17 Willem Jan Palenstijn * audio/midi_drivers/Makefile.am: add win_midiout.* 2004-02-13 Willem Jan Palenstijn * mouse.cc: fixed dead actors causing movement slowdowns and/or crashes * data/bg/musket.shp: musket paperdoll art (by servus) * docs/art.txt: updated art table 2004-02-13 Willem Jan Palenstijn * objs/chunks.cc: fix crash after activating eggs and teleporting * data/bg/pants.shp: use correct pants (by servus) 2004-02-12 Willem Jan Palenstijn * data/bg/pants.shp: pants paperdoll art (by servus) * data/bg/collar.shp: leather collar paperdoll art (by servus) * data/bg/*gorget.shp: fixed female gorgets * data/bg/hawk.shp: tweaked hawk on female shoulder a bit * data/bg/hoods.shp: hoods paperdoll art (by servus) 2004-02-11 Willem Jan Palenstijn * data/bg/shoes.shp: shoes paperdoll art * data/bg/triple_xbow.shp: triple crossbow paperdoll art * data/bg/musket_ammo.shp: musket ammo paperdoll art (by WishStone) 2004-02-11 Willem Jan Palenstijn * gumps/AudioOptions_gump.cc: only display midi settings when relevant * audio/Midi.cc: label music player id output 2004-02-11 Dominik Reichardt * docs/xml/docs.xml: updated and added screenshots * docs/images/docs*.png added * docs/readme.html: updated and added screenshots * Readme updated 2004-02-10 Willem Jan Palenstijn * data/bg/hawk.shp: hawk paperdoll art * gumps/Paperdoll_gump.cc: fixed dropping items in BG belt slots 2004-02-08 Willem Jan Palenstijn * data/bg/death_scythe.shp: death scythe paperdoll art * data/bg/firewand.shp: fire wand paperdoll art * data/bg/knife.shp: knife paperdoll art * data/bg/starburst.shp: starburst paperdoll art (belt-only) * data/bg/hawk.shp: hawk paperdoll art 2004-02-07 Willem Jan Palenstijn * exult.cc: rotate colours 0xFC-0xFE (Juggernaut Hammer) 2004-02-06 Willem Jan Palenstijn * cheat.cc: move dead bodies to avatar before resurrecting them 2004-02-05 Willem Jan Palenstijn * Makefile.am: add empty install-exec-local target if not on Mac OS X * configure.ac: add extra X11 include directory on freebsd * Makefile.am: distribute autogen.sh 2004-02-03 Dominik Reichardt * docs/xml/exult_studio.xml: converted JPGs to PNGs * docs/exult_studio.html: converted JPGs to PNGs * docs/images/*.jpg removed, *.png added instead * docs/xml/faq.xml: eliminated another jpg * docs/faq.html, readme.html: updated * ReadMe, FAQ: updated 2004-02-02 Willem Jan Palenstijn * gumps/Gump_manager.cc: don't disable unicode if any modal gumps left 2004-01-30 Willem Jan Palenstijn * audio/Audio.cc: prevent crash when loading an invalid wave file * docs/xml/docs.xml: updated a bit 2004-01-30 Ryan Nunn * Various files : Updating version to 1.1.10cvs. That's one point one point ten see vee ess. * audio/Audio.cc : Fixing up resampling bias problem. Fixing up what was actually causing the high pitch voices for Windows users. Using = instead of == is never good. 2004-01-27 Dominik Reichardt * docs/xml/docs.xml,faq.xml: updated * docs/ReadMe.html, Faq.html: updated * FAQ, ReadMe: updated * README.MacOSX: added compile instructions as discussed ages ago on the forum 2004-01-26 Willem Jan Palenstijn * various: update version to 1.1.9rc1, adjust copyright dates * configure.ac: remove --enable-usecode-debugger configure option 2004-01-19 Willem Jan Palenstijn * objs/egg.cc: never set hatched on the Serpent Staff egg (bug#879253) 2004-01-19 Ryan Nunn * actors.h : Added get_sexed_coloured_shape() for fixing paperdolls and face stats always having white skin colour in serpent bond mode. * gumps/Paperdoll_gump.cc, gumps/Face_button.cc : Fixing serpent bond bug * files/utils.* : Made U7exists() return type bool. 2004-01-19 Willem Jan Palenstijn * shapeid.cc: don't corrupt game palette to get special colours * palette.*, various: replaced update() by apply(false) 2004-01-18 Willem Jan Palenstijn * game.*: added Game::has_expansion() to check for FoV/SS * objnames.cc: fixed SI-without-SS object names * files/utils.cc: made U7remove() case-insensitive * various: cleaning up output * CombatOptions_gump.cc: made buttons wide enough for text * various: added config/debug/trace/combat option to enable combat msgs 2004-01-17 Willem Jan Palenstijn * gamewin.cc: fix check for original gamedat * various: cleaned up some output 2004-01-17 Ryan Nunn * audio/midi_drivers/fmopldrv.cc : 'Fixing' hanging note problem 2004-01-17 Willem Jan Palenstijn * files/utils.cc: make sure path_map contains no invalid/empty entries * audio/Audio.cc: use Mix_GetError after Mix_OpenAudio * fmopldrv.cc: don't crash if u7voice.flx not found * exult.cc: always load BG/SI paths * shapeid.cc: use SERPENTISLE_STATIC instead of SERPENT_STATIC 2004-01-10 * gamemap.cc: create_ifix_object() added to create the right type of object. * files/utils.cc: Clone_system_path should check that entry exists. * exult.cc: Always set , defaulting to datadir/patch. 2004-01-06 * usecode/intrinsics.cc: Yet another intrinsic: set_barge_dir(). 2004-01-03 * gamerend.cc,chunks.cc: Handle dungeons slightly differently to avoid black squares in SI Sunrise Isle area. I'm assuming a certain shape (941 with frame 0) means "whole chunk is dungeon". 2004-01-03 Willem Jan Palenstijn * exult.cc, *game.cc: cleared up startup output a bit * audio/Midi.cc: show errors when unable to find .ogg files * actorio.cc: made the "NPC #x is unused" messages debug-only * exult.cc: changed default music path to music subdir of the current data path (instead of the hardcoded default data path) 2003-12-16 * Applied Debian signed-char patch. 2003-12-12 Willem Jan Palenstijn * docs/xml/*: updated .xsl's to indent config file examples 2003-12-01 * gamemap.cc: Fixed map-editing bug involving cached-out superchunks. 2003-11-30 * mapedit/chunklst.cc, etc.: Added a 'delete' option for chunks. 2003-11-29 * usecode/ucinternal.h,intrinsics.cc: Only force barge to do a 'gather' when we've actually add/deleted/moved an object. * objs/egg.cc (Egg_object): Teleport eggs should not automatically reset (unless they have the auto_reset flag). 2003-11-28 * mapedit/npcedit.cc: Each schedule line now has a "Game" entry that sets the location from where the Avatar is standing. 2003-11-15 Willem Jan Palenstijn * cheat_screen.cc: don't show unimplemented options 2003-11-12 Ryan Nunn * tools/u7voice2syx.cc : Small tool that will convert various files ("u7voice.flx" BG, "u7intro.tim" BG, and "mainmenu.tim" SI) into syx (SysEx) format files for people with MT32s. For everyone else these files are kinda useless. Doesn't do anything with the XMIDI.MT files which are used for the BG endgame xmis, and the SI intro, in game and endgame xmis. 2003-11-09 Ryan Nunn * exultmenu.cc, gamewin.cc, audio/Midi.*, audio/xmidi.*, gumps/AudioOptions_gump.* : Removing the, IMO horrible, hack to the XMIDI convert types to support OGG and FMSynth Midi drivers. Added a separate setting that can be used to select which driver you want. Config key is "config/audio/midi/driver". Current settings are "normal", "digital" and "fmsynth" (if compiled in). Gumps and menus modified to reflect the changes. It is no longer possible to change midi driver in Exult menu, you must use the Audio Options Gump. Changing midi driver is now immediate. Restarting Exult is no longer required if you switch to or from the Ogg or FMSynth drivers. These changes are just the beginning... after 1.1 has gone final, I will integrate the New Pentagram midi system into Exult, which will bring all sorts of wonders with i... ok, maybe not, it's just better. :-) * vec.h, files/U7file.*, msvcstuff/msvc_kludges.h : Minor changes so Exult will compile in MSVC.Net. No projects yet, probably will add them after 1.1. 2003-11-02 * combat.cc,actors.cc,npcnear.cc: No longer automatically put 'hostile' NPC's in combat. Should fix Wisp problem. 2003-11-01 * schedule.cc (Waiter_schedule): Create plates if needed. 2003-10-31 * combat.cc: Play music only when someone can approach an enemy. 2003-10-30 * gameclk.cc,actors.cc: Check hunger every hour, instead of every 3 hours. * objs/citerate.h,barge.cc: Fixed world-wrapping bug. 2003-10-26 * schedule.cc (Walk_to_schedule): Changed pathfinding so you can follow Patterson to his tryst. * npcnear.cc: Don't call usecode for NPC's walking to schedule, so we don't see them snoring while they're walking. 2003-10-26 Max Horn * configure.ac: Patch #794229: OpenGL on Mac OS X * conf/Configuration.cc: Patch #794231: Find exult.cfg in ~/Library/Preferences on Mac OS X 2003-10-18 Willem Jan Palenstijn * FAQ, README, docs/xml/*: updated for beta3 * autogen.sh: don't delete docs/xml/Makefile 2003-10-17 Ryan Nunn * gamemap.cc : Fixing cacheout bug that was causing the SI post Frigidazzi trial item chest problem among other possible problems. 2003-10-07 Ryan Nunn * usecode/intrinsics.cc : Doing what needs doing (std) 2003-09-17 Jeff Freedman * usecode/ucinternal.cc: New opcode 0x52, CALLO, calls original usecode function if a version from patch replaced it. 2003-09-12 Jeff Freedman * usecode/ucsched.cc (Usecode_script): Finish some scripts before purging them. Fixes Test-O-Love bug. 2003-09-06 Jeff Freedman * delobjs.cc: Adding a timestamp, so objects don't get deleted until they've been there a few minutes. 2003-09-01 Jeff Freedman * objs/animate.cc,gamemap.cc: Check for 'sfx' objs. that aren't animated. Black gate and vortex cube now have sound effects. 2003-08-31 Ryan Nunn * imagewin/scale.cc : Fixing 2xSaI (No mouse problems, should generally look better) 2003-08-31 Willem Jan Palenstijn * all: if we're GPL, don't refer to the LGPL for details. (thanks to Colourless for spotting this one) 2003-08-30 Willem Jan Palenstijn * intrinsics.cc: fix crash in get_npc_name * chunks.cc: don't delete non-temporary npc on cache_out 2003-08-27 Willem Jan Palenstijn * gamemap.cc: enable WANT_MAP_CACHE_OUT permanently 2003-08-25 Willem Jan Palenstijn * schedule.cc: don't create special potions in lab schedule 2003-08-23 Jeff Freedman * usecode/ucsched.cc, usecode/ucscriptop.h, actors.cc: Schedule 'resurrection' instead of doing it immediately. 2003-08-16 Jeff Freedman * shapes/shapeinf.cc: Kludge: Don't use sfx 123 for weapons in SI; use 61 instead. 2003-08-15 Jeff Freedman * mapedit/shapefile.cc (Image_file_info): Write out single-shape files correctly. * data/estudio/new: Added (primitive) fonts.vga, pointers.shp. 2003-08-14 Ryan Nunn * usecode/intrinsics.cc, usecode/siintrinsics.h, usecode/ucinternal.h : B5 Intrinsic in SI (modify_schedule) 2003-08-13 Darke * usecode/ucxt/head2data.cc: Updated to append function number to the end of UNKNOWN functions. 2003-08-11 Ryan Nunn * gamemap.cc : Fixing the item duplication problem. h4XoRz beware we'll be deleting all accounts of people exploiting this bug in the period till next release, or something... oh wait... Exult isn't a MMORPG. 2003-08-08 Willem Jan Palenstijn * various: 1.1beta2 2003-08-08 Aurelien Marchand * data/exultmsg_fr.txt: added French translation of exultmsg.txt. Now Exult only needs to support it. ;-) 2003-08-06 Dominik Reichardt * data/exultmsg_de.txt: added German translation of exultmsg.txt. Now Exult only needs to support it. 2003-08-05 Willem Jan Palenstijn * game.cc: create 2003-08-02 Jeff Freedman * schedule.cc: Rewrote Preach schedule. * usecode/ucsched.cc: Fixed the add(int, char*) method. 2003-07-31 Willem Jan Palenstijn * gamewin.cc: fixed memory corruption issue breaking item descriptions 2003-07-29 Aurelien Marchand * README.Qtopia: More accurate details. 2003-07-25 Ryan Nunn * WinNT and Win2K are forced to use the Win9x style IPC that i wrote. This should now meant that Exult Studio will now work. 2003-07-22 Ryan Nunn * Minor changes to fix errors in MSVC * Updating Win32 stuff for 1.1Beta1 2003-07-06 Jeff Freedman * actors.cc (public): Dont_move flag stops Avatar. Also rewrote the flags tests as a 'case' statement. Always give at least a small possibility of a 'hit' in combat. * objs/contain.cc: Don't let user add items to a locked chest. 2003-06-25 Jeff Freedman * items.{cc,h},msgfile.{cc,h}: Adding support for an 'exultmsg.txt' file containing strings used in C++ code. 2003-06-24 Willem Jan Palenstijn * gamewin.cc, gumps/VideoOptions_gump.cc: fixed screen corruption when changing scaler from video options gump 2003-06-24 Max Horn * audio/midi_drivers/mac_midi.cc: Fixed pan controller in QuickTime midi. 2003-06-24 Max Horn * files/rwregress.cc, conf/xmain.cc, usecode/compiler/ucfun.cc, usecode/ucxt/include/ops.h: added #include to please GCC3.3 2003-05-21 Tristan Tarrant * files/databuf.h, tools/cmanip.cc: added #include to please GCC 3.3 2003-05-11 Jeff Freedman * gamewin.cc: 'Formation' walking is now on permanently. * mapedit/*: Now uses gtk_drag_begin() so that DND works with GTK2.x. 2003/05/09: Aurelien Marchand (artaxerxes@users.sf.net) * added command option to tools/cmanip.cc to return the value of a key 2003-05-05 Tristan Tarrant * exult.cc, audio/Midi.cc: add new configuration config/disk/music_path, where the user can specify a path to the OGG files 2003-05-04 Dominik Reichardt * docs/xml/*.xml: updated * docs/*.html, exult_studio.txt: updated * docs/usecode_bugs.txt: added SI-SS pillars bug * FAQ, ReadMe : updated and spellchecked 2003-04-26 Willem Jan Palenstijn * mapedit/objedit.cc: properly load/save shape/frame/quality for objs * palette.cc: removed unnecessary palette changes 2003-04-21 Willem Jan Palenstijn * docs/usecode_bugs.txt: added some bugs from the forum 2003-04-18 Willem Jan Palenstijn * shapes/font.cc: use unsigned char to index font frames. 2003-04-12 Jeff Freedman * party.cc,gamewin.cc: Experimental (and half-done) code to have the party walk in formation. 2003-04-09 Jeff Freedman * party.h,party.cc,etc: Moved party handler to new file/class, which will possibly be used to implement 'formation' following later. 2003-03-26 Jeff Freedman * objs/objnames.cc: Check that index is within valid list of names. 2003-03-22 Jeff Freedman * bgintrinsics.h,intrinsics.cc,gamewin.cc: Implemented 'call_guards()' usecode intrinsic. 2003-03-19 Jeff Freedman * gamemap.cc: Quality 'okay-to-take' flag should override default, so that food can be treated as 'stolen'. 2003-03-18 Jeff Freedman * objs/egg.cc (Egg_object): Mark egg as 'hatched' even if it fails the probability test. (This is experimental.) 2003-03-15 Willem Jan Palenstijn * wuc.c: 256 bytes just isn't large enough for a static string buffer 2003-03-12 Willem Jan Palenstijn * exult.cc: ignore fullscreen mode for --buildmap (in a hackish way) * ucinternal.cc: fixed sleeping crash * INSTALL: updated 2003-03-10 Jeff Freedman * Various: Support for 'static' (persistent) usecode variables, both local and global. * usecode/compiler/ucparse.yy: Can now use '.' instead of '->'. 2003-03-06 Aurelien Marchand * docs/usecode_bugs.txt: added a file for people interested in fixing some usecode bugs 2003-03-06 Willem Jan Palenstijn * Spellbook_gump.cc: bookmark doesn't stop clicking on buttons 2003-03-05 Jeff Freedman * mapedit/objbrowse.h (public): Get_selected() now returns correct index when scrolled. Fixed 'remove' bug in EStudio groups. 2003-03-05 Willem Jan Palenstijn * exult.cc: fixed --buildmap * */.cvsignore: added some misc files to .cvsignore * sigame.cc, bggame.cc: use unicode translation for avatar name input 2003-03-04 Jeff Freedman * imagewin/scale.cc,etc.: Added Andrea Mazzoleni "Scale2X" scaler. 2003-03-03 Tristan Tarrant * mapedit/studio.cc: implemented GtkTreeView stuff * mapedit/exult_studio.glade: changes for above 2003-02-28 Jeff Freedman * gamerend.cc (using): Draw modal gumps after text. * combat.cc (Combat): Only play victory music when there are no more enemies around. Also, play one of two pieces. 2003-02-27 Willem Jan Palenstijn * conversation.cc: don't use BG multiracial hack if not in BG 2003-02-25 Tristan Tarrant * Exult Studio compiles and runs with GTK+ 2.0. It doesn't work quite yet. I've ported GtkText to GtkTextView, but I still need to port to GtkTreeView instead of the awful GtkCTree * mapedit/*: "gtk+ 2.0"-ification 2003-02-25 Tristan Tarrant * configure.ac: use pkg-config to search for GLIB 2.0/GTK+ 2.0/LIBGLADE 2.0 search for a gimptool >= 1.3.12 * usecode/compiler/Makefile.am: use AM_YFLAGS instead of YFLAGS * mapedit/u7shp.c: ported to GIMP 1.3.x * mapedit/Makefile.am: use $GIMPTOOL instead of gimptool 2003-02-24 Willem Jan Palenstijn * configure.ac: renamed configure.in to configure.ac; updated for autoconf 2.53+; removed acconfig.h * audio/Makefile.am: missing header from sources 2003-02-20 Willem Jan Palenstijn * version.cc: output HAVE_OPENGL setting * imagewin.h: disable OpenGL in the video options if not HAVE_OPENGL 2003-02-20 Willem Jan Palenstijn * forked_player.cc: don't go into infinite loop when player fails * shapeid.*: minor cleanup * objs/egg.cc: prevent egg from retriggering immediately * gamerend.cc, Gump_manager.*: draw modal gumps even when in dont_move 2003-02-20 Jeff Freedman * combat.cc (Combat): Wisps can teleport (partly done). * actors.cc: Wisps (and others) always get at least 1 attack point for their builtin weapon. 2003-02-18 Jeff Freedman * actors.cc: Exploding weapons implemented. 2003-02-17 Jeff Freedman * objs/chunks.{cc,h},etc: find_door() speeds up pathfinding. 2003-02-16 Jeff Freedman * drag.cc (Dragging_info): Don't drop above where we can see. 2003-02-15 Jeff Freedman * drag.cc,objs/objs.cc,objs/chunks.cc: A removed object now has its chunk coords set to (255, 255). * objs/chunks.cc (Chunk_cache): Rewrote 'blocking' code. Now a 0-3 element count is maintained. * usecode/intrinsics.cc: Mark object as deleted before putting it back in the world. 2003-02-12 Jeff Freedman * objs/iregobjs.cc,gamemap.cc: Use 'invisible' flag from quality byte. Fixes 'caltrops not invisible' bug. * gamerend.cc (using): Render all flat tiles before rendering the RLE flats. Fixes 'chopped-off' rocks in desert. 2003-02-11 Jeff Freedman * monsters.cc: Cyclops cause quakes when they walk. 2003-02-05 Aurelien Marchand * README.Qtopia: few changes to match the current compile method * configure.in: reverted the zaurus/embeddix $host_vendor variable 2003-01-27 Jeff Freedman * actors.cc: When resurrecting, set schedule to something reasonable. 2002-12-17 Willem Jan Palenstijn * keyactions.cc: fixed crash in alternate SI intro * sigame.cc: fixed wrong char* initializer (Philipp Thomas ) 2002-12-09 Jeff Freedman * gumps/Spellbook_gump.cc (public): Bookmark always shows, and clicking on it gets you back to its page. 2002-11-26 Jeff Freedman * CombatOptions_gump.cc: Added "Combat" menu. 2002-11-23 Jeff Freedman * gamewin.cc: When combat is paused, you can direct a party member by right-clicking, then clicking on a target to attack. * combat.cc,keys.cc,etc.: Suspend/resume combat (space key). * combat.h (public): Combat class with options. * actors.cc: Optionally show hits on screen. 2002-11-22 Jeff Freedman * gamewin.cc (Game_window): Don't show new screen res. if in gump mode. * gumps/Gump_manager.cc: Paint at start of do_modal_gump(). The back-saving is no longer needed. 2002-11-21 Jeff Freedman * gumps/Spellbook_gump.cc (Spellbook_gump): Use correct font so that the circles and spell-counts get palette animation. (Spellbook_gump): Show turning page (what a pain!) 2002-11-09 Dancer Vesperman * configure.in: --enable-mmx (default: off) * configure.in: --enable-3dnow (default: off) * vec.h: Explanatory comment. 2002-11-09 Jeff Freedman * gamewin.cc: For theft, see if NPC is facing Avatar. * objs/objs.cc: get_dir_facing(). 2002-11-08 Jeff Freedman * objs/egg.cc (Egg_object): Implement sound-effect eggs. * mapedit/eggeddit.cc: SFX eggs. 2002-11-07 Willem Jan Palenstijn * mapedit/execbox.*: don't compile this for win32 2002-11-04 Max Horn * conf/Configuration.*, conf/XMLEntity.*: some cleanup (in function args, using 'const string &' instead of just 'string' or 'const string' is more efficient as the string doesn't have to be cloned temporarily) * menulist.cc: do not swallow certain command combos (Cmd-Q, Alt-X, ...) when nothing is selected * game.cc, file/utils.*: Added and make use of clone_system_path() 2002-11-03 Willem Jan Palenstijn * actors.cc: fixed division by zero * shapes/Makefile.am: removed outdated OMIT_DEPENDENCIES * mapedit/compile.cc: std::string * mapedit/execbox.cc: #include 2002-10-31 Willem Jan Palenstijn * shapes/font.cc: fixed hang in french BG 2002-10-21 Willem Jan Palenstijn * mapedit/shapelst.cc,chunklst.cc,paledit.cc,combo.cc: mouse wheel 2002-10-18 Jeff Freedman * exult.cc,mapedit/chunklst.cc,etc: "Paint with chunks" mode added. * mapedit/shapelst.cc,etc: Keep shape browsers around so that they're at the same spot and selection when you return to them. 2002-10-15 Willem Jan Palenstijn * mapedit/exult_studio.glade: East is a direction too :-) * objs/egg.cc: use shape 200, frame 1-5 for new missile eggs * mapedit/exult_studio.glade: removed tabs from two names * mapedit/exult_studio.glade: made egg_window notebook unscrollable, since the scrollable option is apparently broken in windows 2002-10-10 Max Horn * Info.plist.in: No .nib file used anymore * configure.in: Removed some unnecessary flags on MacOS X * audio/midi_drivers/mac_midi.cc: Use assert() instead of DebugStr() * gumps/AudioOptions_gump.cc: Work around a compiler bug on MacOS X 2002-10-10 Jeff Freedman * mapedit/execbox.cc (Exec_process): Split off separate class to handle the plotform-dependend exec'ing. 2002-10-08 Jeff Freedman * mapedit/execbox.cc,compile.cc: Added a 'compile' window for running the usecode compiler and seeing the errors. 2002-10-07 Max Horn * data/credits.txt: Jackchaos.com hosted the old forum * several files: got rid of #pragma implementation/interface - it didn't help us much anyway but triggered a compiler error on MacOS X * many files: get rid of using std::snprintf - according to the standard, snprintf is *not* in namespace std 2002-09-29 Jeff Freedman * usecode/intrinsics.cc: Get_distance() looks at owners of objs. This fixes the bug with selling the bread you bake in BG. 2002-09-24 Jeff Freedman * usecode/intrinsics.cc: Guessing 'npc_nearby2()'. Fixes Moonshade bug where companions don't show up to the trial. 2002-09-21 Jeff Freedman * pathfinder/*: GetNextStep returns a 'done' flag if the tile returned is the last in the path. * actions.cc: Check for last step & return 0 if so. 2002-09-19 Jeff Freedman * usecode/ucsched.cc (Usecode_script): Moved the 'no_halt' test to start(). * schedule.cc: Patrol schedule: Look for path after executing Usecode, and keep going after sitting. This fixes Freedom bug where the automaton doesn't talk to you upon arrival. * schedule: Don't follow Avatar if paralyzed. 2002-09-14 Jeff Freedman * gamewin.cc: Taking a guess to fix the 'savegump repaint' bug. * drag.cc (Dragging_info): If not dragging, don't paint! 2002-09-13 Jeff Freedman * keyactions.cc,etc: USEFOOD added to support SI goblet. * gamewin.cc: activate_item() now returns true/false. 2002-09-12 Jeff Freedman * actors.cc: In BG, get_shape_real() should only return the normal 2 possible shapes for the Avatar. 2002-09-11 Dominik Reichardt * docs/xml/*.xml: updated and/or spellchecked * docs/*.html, exult_studio.txt: updated and/or spellchecked * FAQ, ReadMe : updated and spellchecked 2002-08-29 Willem Jan Palenstijn * intrinsics.cc: reverted click_on_item change from 2002-08-02 (it broke hitting Draygan with sleep arrows) * intrinsics.cc: restored mentioned change, but for the avatar only 2002-08-27 Jeff Freedman * effects.cc: It's now okay to show rain/clouds when gumps are shown. * tqueue.cc: Got to fix time when tqueue is paused (like when gumps are open). * gumps/Spellbook_gump.cc: Close all gumps after casting spell. * objs/objs.cc: Weapons with 0 HP's should never do damage. 2002-08-26 Aurelien Marchand * configure.in: Added -FMOPL and disabled debug in configure.in for the zaurus. * audio/Midi.cc: Make it work on the zaurus * imagewin/imagewin.cc: prevent fullscreen at all cost for the zaurus or it would crash 2002-08-23 Jeff Freedman * usecode/ucinternal.h: Fixed "in_usecode()" so it works with new stack-frames. * usecode/ucsched.cc (Usecode_script): Don't purge script if it has already started. 2002-08-22 Jeff Freedman * objs/objs.h (public): Added is_pos_invalid(). * effects.cc: Don't delete 'explode' if already off map. 2002-08-15 Aurelien Marchand * audio/Audio.cc: corrected cast error to prevent bus error on Zaurus 2002-08-12 Aurelien Marchand * shapes/fontgen.cc: prevent freetype if building for Zaurus. 2002-08-12 Jeff Freedman * schedule.h,usecode/intrinsics.cc: Always use bed that was double-clicked. * schedule.cc: Bug in getting tz. * usecode/conversation.cc: Repaint when you pop_answers(). 2002-08-11 Jeff Freedman * usecode/intrinsics.cc (public): Explosion should explode the outermost container. 2002-08-09 Ryan Nunn * audio/midi_drivers/fmopl_midi.*, audio/midi_drivers/fmopldrv.cc, gumps/AudioOptions_gump.cc : Fixing compiling issues * audio/midi_drivers/Makefile.am: Added fmopl files to the makefile, but I'm not going to touch the configure script. 2002-08-07 Ryan Nunn * cheat_screen.cc : Added missing tqueue header. * exultmenu.cc, audio/Midi.cc, audio/xmidi.h, gumps/AudioOptions_gump.cc : Added 'Music Conversion' option to enable the FM Synth. Requires a restart of Exult once it has been set in order for it to work. * gamewin.cc : Removed screen offset test that wasn't meant to be committed * msvcstuff/*.*, audio/midi_drivers/win_midiout.cc : Doing some tests compiling Exult using UNICODE * files/*.* : Some initial changes for PocketPC support 2002-08-06 Ryan Nunn * midi_drivers/fmopl*.* : Emulatled FM Synth. Compiling in by defining USE_FMOPL_MIDI. Makefiles will probably need updating. Has a 'dual' mode for stereo sound. Use "config/audio/midi/dual_opl" set to "yes" or "no" to enable/disable it. Default is "yes". BG support is 'work in progress', while SI is pretty much finished. Requires xmidi.ad and u7voice.flx files. * audio/Audio.*, audio/Midi.*, audio/xmidi.h : For FM Synth. * bggame.cc, sigame.cc : FM Synth stuff, and fixing things that look like they could be causing crashes. * cheat_screen.cc, audio/soundtest.cc : Will pause game when using these * msvcstuff/*.* : 'Fixing' some precompiled header problems. * Lots of files : Added mode to allow the world to run when gumps are open. Has config setting, and option in Gameplay options gump. * A few files: Added option to disable double right pathfinding move. Option in gump and config. * Misc files: Namespace issues. 2002-08-06 Willem Jan Palenstijn * Makefile.am: correct windows Makefiles in EXTRA_DIST 2002-08-04 Willem Jan Palenstijn * gumps/Gump_manager.cc: fixed combat stats crash 2002-08-02 Willem Jan Palenstijn * tools/Makefile.am: no longer build ucdump * audio/Audio.cc: free -> delete[] 2002-08-02 Jeff Freedman * objs.cc,objs.h: Game_object::add will try to combine. * monsters.cc (Monster_actor): When using monster itself as weapon, return the shape. Should fix problem where slimes weren't doing any damage. * combat.cc: Remove dead NPC's from opponents list. Fixes problem where party stands around not attacking remaining monsters. * usecode/intrinsics.cc: To make combat spell-casting work, click_on_item now takes the target of the caller_item. Let me know if this breaks anything. 2002-07-31 Willem Jan Palenstijn * mouse.cc: fixed uninitialized variables (box,dirty) * shapeid.cc: delete -> delete[] 2002-07-31 Jeff Freedman * gumps/Spellbook_gump.cc,objs/spellbook.cc: Move functionality to Spellbook_object in preparation for spellbook combat. 2002-07-30 Jeff Freedman * gamemap.cc,spellbook.{cc,h}: Save/restore bookmarked spell. * shapes/vgafile.cc: Update image when offsets are changed. 2002-07-29 Jeff Freedman * tqueue.cc,gamewin.cc,Gump_manager.cc: Pause time queue (with Text_effects as an exception) whenever gumps are open. 2002-07-28 Jeff Freedman * effects.cc,gamerend.cc: Text_effects are in a separate list. * gamerend.cc: Show sprites below gumps, text over them. 2002-07-28 Ryan Nunn * pathfinder/path.cc : Fixed seriously broken non hash pathfinding (z coord was being ignored in comparisons of nodes). This fixes the Monitor Training problem. Probably fixes countless other pathfinding problems too. 2002-07-27 Max Horn * audio/Audio.cc: Replaced the pseudo-breshenham audio interpolation code with 'proper' cubic interpolation code. 2002-07-27 Willem Jan Palenstijn * monstinf.*: armur? armour! ;-) 2002-07-27 Jeff Freedman * combat.cc: Call ready_ammo() if NPC needs it. * objs/barge.cc (Barge_object): Exit barge mode when you go into combat, and lower sails when you exit barge mode. 2002-07-26 Jeff Freedman * usecode/intrinsics.cc,objs/flags.h,drag.cc: In_dungeon flag. Also don't assume theft if inside a dungeon. * shapeinf.{cc,h},combat.cc,effects.cc: Not_blocked flag for weapons and ammo. 2002-07-26 Aurelien Marchand * README.Qtopia: updated * imagewin/ibuf8.cc: added a test to prevent fast copy on the zaurus * configure.in: added test for $host_vendor under the linux clause * shapes/monstinf.*: renamed "arm" into "armur" as "arm" is reserved 2002-07-24 Dominik Reichardt * docs/xml/exult_studio.xml: updated * docs/exult_studio.html, exult_studio.txt: updated 2002-07-24 Dominik Reichardt * exult.cc: little correction of the --help screen (--bg, --si instead of -bg -si) * Readme, FAQ: updated. * docs/xml/docs.xml, faq.xml: updated * docs/readme.html, faq.html: updated 2002-07-24 Jeff Freedman * shapeid.cc,vgafile.h,glshape.cc: Translucent shapes supported in OpenGL. May not look entirely right, as I had to guess at the colors (in 'shapeid.cc'; look for 'blends'.) 2002-07-23 Jeff Freedman * imagewin/imagebuf.h (public): Xform_palette is now a class containing the color that's being blended. 2002-07-23 Tristan Tarrant * keyactions.*: renamed functions to use north/south/east/west and added diagonals (north-west, etc.), implemented running * data/bg/defaultkeys.txt data/si/defaultkeys.txt: added mapping keypad keys for all 8 directions, added shift-arrows and shift-keypad for running 2002-07-23 Jeff Freedman * imagewin/iwin8.h,etc: fill8() works in OpenGL. 2002-07-22 Jeff Freedman * shapes/glshape.cc (GL_manager): Paint_image() used for images larger than 256x256. Also, units changed from tiles to 'pixels'. 2002-07-22 Dominik Reichardt * README.Qtopia : added instructions by Artaxerxes on how to compile Exult for the Zaurus PDA. 2002-07-22 Tristan Tarrant * exult.cc: pass key releases to the action handler too * keyactions.*: added ActionWalk* functions * keys.*: implemented mapping for key release * data/bg/defaultkeys.txt data/si/defaultkeys.txt: added walking via arrows and remapped scrolling to alt-arrow 2002-07-22 Willem Jan Palenstijn * content/islefaq/usecode.uc: fixed some typos and spacing 2002-07-22 Ryan Nunn * gumps/Gump_manager.cc, gumps/Spellbook_gump.cc, usecode/ucinternal.cc: std stuff. * msvcstuff/Exult.dsp, msvcstuff/msvc_kludges.h : Just enabled OpenGL for myself. * shapes/glshape.cc : Disabled Depth Writing and Testing (see inline note). Enabled Texture Clamping (vs wrapping) to clean up the output a bit. Added a note about Alpha Blending (no code change though). 2002-07-22 Willem Jan Palenstijn * glshape.h: dummy GL_manager class * exult.cc, gamewin.cc, mouse.h: include glshape.h * configure.in, Makefile.am: --enable-opengl 2002-07-22 Tristan Tarrant * mouse.h: #ifdef HAVE_OPENGL was missing around call to GL stuff 2002-07-21 Jeff Freedman * usecode/conversation.cc (Conversation): Still a bit rough, but Conversation::paint() no repaints the whole conversation in its current state. * gumps/Newfile_gump.cc (Newfile_gump): Fixed crash I caused. * exult.cc, etc: Get_click takes a Paintable parameter. * drag.cc,gamerend.cc: Dragging_info::paint() added. 2002-07-20 Jeff Freedman * mouse.cc,font.cc,etc.: More things kind-of work in OpenGL (though mouse doesn't clean up after itself and conversation text disappears, so there's LOTs to fix.) 2002-07-18 Willem Jan Palenstijn * exult.cc: SIGCHLD handler to clean up forked playmidi processes * configure.in: check for sys/wait.h, signal.h (see above) * lots: modal-gump-keyevent-handling related cleanup 2002-07-16 Jeff Freedman * objs/flags.h,actors.h,etc: Moved 'dont_move' and 'no_spell_casting' flags to the spots in Obj_flags where they're referred to in Usecode. *imagewin/ibuf.{cc,h}: rgba() converts to 32-bit format (untested). 2002-07-16 Willem Jan Palenstijn * orangedress.shp, bluedress.shp: new paperdoll art by sbx 2002-07-15 Willem Jan Palenstijn * data/bg/greentop.shp: new paperdoll art. Thanks sbx! * usecode/ucxt/Makefile.am: fixed --disable-tools * configure.in: install gnome things to $(datadir) (instead of $(GNOMEDATADIR)). This allows non-root installs. * data/Makefile.am: don't install estudio data when not building that 2002-07-14 Willem Jan Palenstijn * Spellbook_gump.cc: fixed up offsets; fixed NULL shape error 2002-07-12 Willem Jan Palenstijn * chunks.cc: worked around compiler bug (gcc 2.96-110) for is_blocked 2002-07-12 Jeff Freedman * actors.cc (public): Call_guards logic moved to Actor::reduce_health(), so spells will get you in trouble. 2002-07-11 Jeff Freedman * actors.h,actors.cc: All NPC's except Avatar get 4-frame (smooth) walking. This matches the original U7. 2002-07-10 Jeff Freedman * Lots: Added gumpman to Singletons class. * gumps/GameplayOptions_gump.cc,gamewinc.cc: Walk_after_teleport option is no longer needed (it's always TRUE now). * gamewin.cc,etc: Cleanup: NPC list in Chunks has been removed. 2002-07-10 Willem Jan Palenstijn * exult.cc: undo double click change. (it broke gumps) 2002-07-10 Jeff Freedman * gamewin.cc,paths.cc: Removed limit on finding/dragging items on different lift from Avatar. * objs/egg.cc (Egg_object): Party_near + auto_reset == avatar_near; avoids too much monster spawning. * drag.cc (Dragging_info): Calling unreadied-usecode AFTER the drop should only be done for the SI black sword. 2002-07-09 Willem Jan Palenstijn * ucinternal.cc: allow (but ignore) large changes to loop arrays 2002-07-08 Jeff Freedman * actors.cc,monsters.cc: Bare hands weapon gets 1 damage point. * objs/egg.cc (Animated_egg_object): Fields continue to check for NPC's standing in them so they can add damage. * shapes/vgafile.h (public): Added set_offset(); * mapedit/shapeedit.cc: Update shape origin. 2002-07-08 Willem Jan Palenstijn * Newfile_gump.cc: use SDL's unicode translation for text input * lots: moved gump_utils.cc into Gump_manager class * exult.cc: don't count dragging for double clicks 2002-07-07 Willem Jan Palenstijn * ucinternal.cc: allow small changes to loop-array in mid-loop in SI * useval.*: added operator!= (and changed operator== to return bool) * objnames.cc: fixed "x's ashes" code for teleported urn at start 2002-07-05 Jeff Freedman * shapeinf.{cc,h}: Figured out 'actor frame' flags in Weapon_info. * actors.cc,etc: Rewrote get_attack_frames() to use the 'frame' flags in Weapon_info. 2002-07-04 Willem Jan Palenstijn * exult.cc: fixed --buildmap * autogen.sh: fixed problem when automake was compiled with aclocal data directory /usr/local/share/aclocal 2002-07-04 Jeff Freedman * actors.cc,exult.cc,ucsched.cc: Added 'rest_time', so Avatar will return to a standing position when not doing anything else. This fixes the spell-casting bug where you're stuck in the last casting frame, but it may cause some new bugs... * gamewin.cc,exult.cc: Attempting to remove the halt-after-teleport, which I think is no longer needed (and is obviously wrong). 2002-07-03 Jeff Freedman * effects.cc (Projectile_effect): Delay for delayed-explosions. * gamewin.cc: Fade palette back in at end of setup(). * usecode/ucinternal.cc: Always call link_party(), even if new game, and set party_count to 0. 2002-07-03 Willem Jan Palenstijn * objnames.cc: implemented "x's ashes" name in SI * font.cc: fixed word wrapping off-by-hlead 2002-07-02 Jeff Freedman * gamewin.cc (Game_window): Set singleton after creating pal. * Various: Merged in activate() fixes from 1.00 branch. 2002-07-02 Willem Jan Palenstijn * objs.cc: fixes to SI item names (thanks sb-x) * objnames.cc: moved naming code to separate file 2002-07-01 Willem Jan Palenstijn * objs.cc: even more item names for SI 2002-07-01 Willem Jan Palenstijn * shapeid.h: let paint_shape paint non-rle shapes properly * vgafile.cc: assert(rle); in the paint_rle_* functions * objs.cc: more item names for SI 2002-06-30 Willem Jan Palenstijn * objs.cc: finally fixed 'blood' names 2002-06-30 Willem Jan Palenstijn * Configuration.*, exult.cc: added -c option for alternate config files (quite useful if you have multiple data dirs or languages of BG/SI) 2002-06-29 Willem Jan Palenstijn * singles.h, shapeid.cc: added pal = gwin->get_pal() to singles * *game.*, txtscroll.*: got rid of extra Palette objects 2002-06-28 Jeff Freedman * gamewin.h (public): Game_clock is now a pointer. * exult.cc,game.cc: --nomenu arg skips game menu. 2002-06-28 Jeff Freedman * gamewin.h (public): Reordered and added comments. 2002-06-27 Jeff Freedman * shapeid.*,etc: Text routines moved to Shape_manager. * palette.*,etc: All palette vars/methods moved to Palette. * objs.h: Added get_chunk(). * gamewin.h,etc: get_chunk* removed (it's in Game_map). 2002-06-27 Max Horn * objs/objiter.cc: Fixed compilation with CodeWarrior 7 (MacOS Classic) 2002-06-26 Jeff Freedman * objs/*: Removed umachine parm. from activate() methods. * objs/*: Removed most 'gwin' parameters. * objs/objs.h (public): Game_object::paint() no longer takes gwin as a parameter. Same for paint() in Special_effects. * gumps/*: Got rid of gwin parm. in ALL methods. * singles.h: A class to hold the common 'singletons'. 2002-06-25 Jeff Freedman * effects.h, etc.: Cleanup: Effects_manager class added. * actions.cc: Wrote Approach_actor_action for use in combat to make approach of combatants work better. * npcnear.cc: Hostile monsters don't wait as long to get activated. * pathfinder/Astar.cc,etc: Get_num_steps. 2002-06-24 Jeff Freedman * gamewin.cc: Commented out add_nearby_npcs(). I think it's not needed anymore. 2002-06-24 Ryan Nunn * ChangeLog : Added comment that was meant for this branch, but I accidently put in the other branch 2002-06-24 Ryan Nunn * actors.cc : Fixed a problem with gloves not using both fingers in BG. * actors.cc, gumps/Gump_manager.cc : Fixed a problem where using a Female avatar in BG with ye olde style inventories would stop the 'I' key from working * actors.h, gumps/Actor_gump.cc : Blue lines are now removed when two handed or two fingered item equiped in BG with ye olde style inventories * msvcstuff/Exult.dsp : Updated to remove RTTI compile option since dynamic casts are no longer used. 2002-06-24 Max Horn * audio/Audio.cc: removed usage of malloc.h; removed some unused variables 2002-06-24 Jeff Freedman * actions.h,usecode/intrinsics.cc: as_usecode_path(). 2002-06-23 Ryan Nunn * msvcstuff/find_nearby.h : Removed because it's now shared for all * Makefile.am : Removed msvcstuff/find_nearby.h * objs/find_nearby.h : Added so it can be used by all * objs/Makefile.am : Added find_nearby.h * objs/*.* : Removed old Game_object::find_nearby template and now use find_nearby.h and macros. 2002-06-22 Ryan Nunn * LOTS OF FILES : Added code to do caching out to memory. However, it's disabled for the moment. Need to #define WANT_MAP_CACHE_OUT to enable it. Added lots of get_ireg_size() methods that return the size required to save the ireg of each object. * gumps/Paperdoll_gump*.* : Fixing up various paperdoll related problems * actors.h, objs/*.*, msvcstuff/find_nearby.h, usecode/intrinsics.cc : Cleanup removing dynamic_casts. * windrag.* : Is now windows only, and is only compiled if actually compiling with Exult studio support. * various other files: Fixing misc compiling problems 2002-06-21 Jeff Freedman * gamerend.h: Helper-class added to do rendering. * gamewin.h,shapeid.h, etc: ShapeID::paint_shape() replaces one of the paint_shape()'s in Game_window, and gamewin.h no longer includes shapeid.h. 2002-06-21 Willem Jan Palenstijn * Paperdoll_gump.cc: fixed bug when displaying usecode container * objs.cc: zero-weight fix * gamewin.cc: display object weight 2002-06-21 Jeff Freedman * actors.cc (Npc_actor): Cleanup: Lots more dynamic_cast's are gone. 2002-06-21 Darke * shapeid.cc: Added using declarations. Committed for Kirben. 2002-06-20 Jeff Freedman * objs.{cc,h},etc: Added 'change_frame()' to set repaint area. * gamewin.h (public): get_info(), etc. moved to ShapeID. * gamewin.h: Hit pixel, etc. replaced by an array. 2002-06-19 Jeff Freedman * shapeid.h (public),etc: New 'Shape_manager' class takes over the various .vga files from Game_window. 2002-06-19 Jeff Freedman * shapeid.cc,etc: Game_window::get_info(Game_object *) is replaced by ShapeID.get_info(). * Lots: Cleanup: Game_window::get_game_window() => get_instance(). * Lots: ::as_actor() replaces lots of dynamic_cast's. 2002-06-19 Willem Jan Palenstijn * data/bg/*, gumps/Paperdoll_gump_info.cc: new art by Oblivious 2002-06-18 Dominik Reichardt * data/bg/defaultkeys.txt: mapped ctrl-c to copy and INSERT to "create item * data/si/defaultkeys.txt: the same * docs/xml/docs.xml, faq.xml : updated * docs/readme.html, faq.html : updated * readme/FAQ : updated 2002-06-13 Simon Quinn * Fixed sound crashing on startup and in-game when sound was disabled 2002-06-13 Ryan Nunn * exult.cc, audio/xmidi.cc : Getting around some problems with (our) snprintf not supporting floating point types. 2002-06-13 Ryan Nunn * Any file that I changed, but not the 2 below : Changed lots of things to use DataSources rather than directly use streams. Hopefully nothing is broken. I expect that there will be numerous signed/unsigned problem for people who are using more standards compliant compilers than me. * usecode/ucinternal.cc, msvcstuff/Exult.dsp : Getting to compile in MSVC once again 2002-06-10 Jeff Freedman * actors.cc (Npc_actor): Fixed a nasty bug I caused which could make NPC's disappear when they're moved. * content/islefaq: Find the missing FAQ:-) 2002-06-10 Simon Quinn * added more details to the audio/README 2002-06-09 Jeff Freedman * gamewin.cc (public): Check for player != 0. * mapedit/npcedit.cc,etc: New NPC's are now created using the 'unused' entries, and deleted NPC's are marked 'unused'. * actors.{cc,h},actorio.cc,readnpcs.cc: Use iflag2 correctly. If 0, it means NPC is unused in game (like the extra trappers). * conf/Configuration.cc: Not everyone has sstream! * usecode/ucxt/src/ucfunc.cc: Same here. 2002-06-08 Max Horn * configure.in: fixed check for SDL_mixer * gamemap.cc: #include objiter.cc instead of objiter.h to get template linking right on all compilers (I hope...) * objs/objiter.cc: removed template instantiation hack 2002-06-08 Willem Jan Palenstijn * autogen.sh: always include /usr/local/share/aclocal if it exists 2002-06-08 Willem Jan Palenstijn * data/Makefile.am: add estudio/new files to dist/data * exult.spec.in: add estudio/new files to studio rpm 2002-06-08 Darke * usecode/ucxt/src/ucfunc.cc: Removed the 'fix' we needed for strstreams. * usecode/ucxt/*: Updated a few things to avoid name collisions between ucxt/include/opcodes.h and usecode/opcodes.h. 2002-06-07 Jeff Freedman * ucinternal.cc: Fixed a couple compile errors if UC debugging isn't enabled. * Audio/*: A couple headers needed to be included. 2002-06-08 Willem Jan Palenstijn * */Makefile.am: cleaning up distro stuff * exult.spec.in: fixed * usecode/ucxt/head2data.cc: removed utils.cc dependency * version.cc: added USECODE_DEBUGGER symbol to version output 2002-06-07 Willem Jan Palenstijn * exult.cc: typo 2002-06-07 Willem Jan Palenstijn * *: merged audiotest branch back into main tree: > 2002-06-06 Simon Quinn > * Recorded Exult title music in OGG pack and implemented in code > > 2002-06-03 Simon Quinn > * Play different SFX track at night and crickets > * Add config option