|
QUICK ACCESS BITTEN BY BYTES!! VARIOUS CODE SAMPLES & GOTCHAS DON'T TRY THIS AT HOME PALETTES DECLARATIONS ASSEMBLY FLASHING ANIMATION [return to FAQs page] [next FAQsheet] [previous FAQsheet]
Ultimo aggiornamento:
21 Gen 2000 |
FAQsheet #3 :: CODE & COMPLICATIONS BITTEN BY BYTES!! Tech note: When byte vars are put in registers they become a long. Turn registers off if you need the limited byte range.... VARIOUS CODE SAMPLES & GOTCHAS [Q]: Is there any way to stop the leading space in STR$( a$)?[A]: You can use the following:
[Q]: Why does this loop never end? FOR i = 1 to 32767[A]: You add the step (default 1), then see if it is past the end value. So a step that exceeds the limit of a variable type may cause an infinite loop. When you get to 32767 and you add the step (1) to it, it becomes -32768. So you are stuck in loopy land. FB^3 will now give this error: Error: FOR/NEXT final value out of range for Variable type! in file Temp Project at line 18 in FBMain *FOR i = 1 to 32767* [Q]: This set of routines works just fine under FB2, but loops forever (In the Sort routine) in FB^3. Here's the code... GAP%= INT( GAP% /1.3)[A]: 2/1.3 = 1.538461 which rounds to 2In other words, your DO/UNTIL loop runs forever because you are waiting for GAP% to equal 1[Q]: Yes, 1.5xxxx does round to 2, but I wasn't rounding. Look at the code again... GAP%= INT( GAP% /1.3)FB^3 should return the INTEGER portion only, not the ROUNDED value. The problem is that INT(1.5xxxx) should equal 1, but is returning 2. (Unless you are changing the definition of the INT() function? Bad idea.)[A]: We used to set the rounding value in FBII by preference. Back then, we manipulated the numbers on our own. Now we use PPC math and no longer have control over how a number is rounded. This is one of a million decisions where we had to decide if we wanted to go forward with fast math or stay back in the dark ages with BCD. Judging from the hoopla over the new G4's floating point speed, I think we made the right decision. :) [Q]: The following: dim a&,aa&,b%,bb%,c#,cc#prints: 2147483646 -2 -2The value for the INT b% = -4 is divided by two, an arithmetic shift right, and of course the float is divided by two. The LONG a& receives a logical shift right, the value for aa& being 2^31 - 2.I understand this may be what seems the best compromise at this point, perhaps not breaking some old FBII code. Just looked at the docs on this (in Appendix D of the Reference Manual). My concern is that in the long run the different treatment of LONG and (two byte) INT is likely to continue to cause problems for the unwary, including those who use shifts often but are not always careful to keep LONGs and INTs strictly separate in regard to the expected behavior under shift right. In any case the difference is not explained or even referred to in the Manual. [A]: Just a note about integer math... var% is a 16 bit integervar& is a 32 bit integerinteger math in FB^3 is always done using 32 bit integers, so 16 bit signed integers are sign extended to 32 bits before any math... so a 16 bit -4 is 0xFFFC and a 32 bit -4 is 0xFFFFFFFCafter integer math if it is stored in a 16 bit integer the top 16 bits are lost... so a -4 shifted down 1 bit is 0x7FFFFFFE = 2147483646 which is a large positive 32 bit integer, or a small negative 16 bit integer = 0xFFFE = -2, the upper 0x7FFF is lost... so the integer math is done exactly the same....float, like FBII is just * or / by 2^n [Q]: To stop this code crashing I had to add the line marked '*': LOCAL FN Crashes (T AS POINTER)[A]: Try this: '----------------------------------FB^3 makes an auto XREF to an incoming array...[Q]: I think I've found a problem in certain boolean comparisons involving integer-based tests. This comparison: LONG IF firstcase AND lastcasedoes not always work in my programs. Note that 'firstcase' and 'lastcase' are always either zero or positive integers. Occasionally this test will fail even if both are >0 (I have checked this carefully). The following change does seem to work all the time (including the same data sets where the previous code failed):LONG IF firstcase>0 AND lastcase>0[A]: FB's Boolean comparisons are bitwise, and if you don't think about it, can bite you (been there). If firstcase = 1 and lastcase = 2, then the statement:LONG IF firstcase AND lastcase is evaluated as: 0000 0000 0000 0001AND = : 0000 0000 0000 0000Each corresponding bit is ANDed with the corresponding bit of the second term. You arrived at your own solution: make sure the terms being evaluated can only be true or false, i.e., firstcase>0 AND lastcase>0, which in the above scenario would both be true, or -1 (1111 1111 1111 1111), and therefore would return true as the result.[Q]: The program below crashes, evidently from the GOTO transferring control out of the SELECT structure. Can the compiler provide an admonitory error, instead?LOCAL FN CrashGOTOInSELECT[A]: We can't protect you on that one. The GOTO may later return to the structure. (Yes. This is properly referred to as code from hell.) We did set up the EXIT FN to automatically handle this automatically.[Q]: I like true records, but miss the versatility of the old way. Can anyone think of a way of defining a true record 8-byte structure ( BEGIN RECORD customRect...) that allows all three ways of accessing the rect and its components? Yes, I have tried BEGIN UNION... but without success.[A]: Ah, here's a delightfully sleazy trick. Taking a step further in the direction of simplicity: DIM r1 as rect, r2 as rect, r3 as rectWhich is exactly what was asked for. Even though a RECT is officially defined as 4 short integersBEGIN RECORD rectyou can trick the compiler into accessing the component LONGs (i.e. POINTs) by appending the type identifier suffix & to the field names top and bottom. I would never have guessed that was legal. [Andy also added: My preferred way of doing it is... LOCAL DIM @t,l,b,ror FN myRectFunction(myRect)Using local var 'l' is faster and smaller then using theRectPtr&.left% when it is used in a loop or more than a few times...][Q]: Ok, if: DIM myRect.8in FB II is different thanDIM myRect AS RECTIn FB^3, then I don't understand how. But for the sake of solving this problem, please tell me which I should use in FB^3. That's all I want.[A]: If you dim "AS RECT" then FB^3 knows what is in the structure. (top, left, bottom, right). If you dim ".8" then FB^3 has no idea what might be in those 8 bytes. So:DIM myRect AS RECTor... DIM myRect.8[Q]: I had (in FBII) DIM'ed my global rects like this: dim gHdw1ItemRect.8In another part of your code, I accessed the contents of these by referring to offsets from the address of gHdw1ItemRect. This works (in FBII) because those 10 global variables are luckily stored in contiguous locations in memory.However, I don't know if I can count on them being stored contiguously in FB^3. A lot has changed about the way FB^3 stores its variables (more than I fully understand); and there are fewer situations in which one can safely rely on consectutively-DIM'ed variables to be stored in contiguous locations. My guess is that a reference like " @gHdw1ItemRect + 8" may not be pointing to gHdw2ItemRect as I expect (and as it did in FBII). It may be pointing to some forbidden area of memory, which when altered causes a crash.[A]: I'm not sure if anything can be done about this without some redesign of your program. You might consider declaring your global rects as an array, like this: dim gHdwItemRect(9) AS RECTThis has two advantages:1. You can use nicer looking syntax to access the global rects in your loop: i.e. this: theHdwItemRect& = @gHdwItemRect(loop)...instead of this:theHdwItemRect& = @gHdw1ItemRect + 8 * loop2. The elements in an array are guaranteed to be in contiguous locations in memory (in case there are other places in your code that depend on all your rect's being stored contiguously). |
||||||||
|
[ritorna all'inizio] |
[Q]: I've been attempting to convert a PG/FBII project to FB^3 and I've hit a problem with the function FN useAlias. The manual says to use it like this:DIM fSpec;0,fVRefNum,fParID&,63 fName$But I'm not getting a valid fName$. Is the problem in the DIM statement?[A]: If you automatically align variables (prefs) this will not work. Maybe we should remove that option. With the pref turned on, you must use... DIM dummy%,fSpec;0,fVRefNum,fParID&,63 fName$[Q]: Huh? All right, I'll byte.. What's the dummy% variable for/do?[A]: Align vars sets everything to align on the correct boundaries.
[Q]: This won't work... CLEAR LOCAL[A]: The following is the problem; passed parameters get shoved into registers when possible (if prefs for that are on) but LOCALTOGLOBAL can't work on a register. Try this;CLEAR LOCAL[Note from : This sample code should not be used for another reason! It looks suspiciously like the author/coder is poking information directly into low-level address... Apple actively discourages this, as it is guaranteed to break soon, if it hasn't already!][Q]: Errm... I hesitate to say this... but what is the difference between a variable and a register variable? TIA [A]: Hmm.... need a "car parking attendant" type example! How about this: Jim has a roll-top desk, with a filing cabinet next to it. When he's sorting the mail, bills to be paid go immediately into a slot in the desk (REGISTERS). Receipts and such go in the filing cabinet (RAM). Both are easily accessible, but there are only a few slots in the desk, and they're small, so only a few things will fit there; the "most important" ones. Anything else has to go in the file cabinet, which takes longer to open up and dig through to get something back out of. (But not as long as stuff in the storage boxes in the closet - HARD DRIVE.) So the slots (REGISTERS) are real fast, and it'd be great to put everything there, but the Monkey Wards catalogue (STRINGS) just won't fit! And only one thing will fit in each slot, so if they're all full, you've either got to put the thing in your hand in the filing cabinet, or move something out of a slot first. We control whether we use the slots at all with the preferences; if we say "yes", the compiler then "guesses" at what's important, thus reserving a register, by saying "first come first served" (mostly). We can tell it "this thing will fit but isn't important, or we don't want it there for some other reason" by using DIM@. |
||||||||
|
[ritorna all'inizio] |
[Q]: As far as the list manager, I am referring to Apple's List Manager, not to a CDEF. I was hoping that someone has conclusively proved that the list manager works with FB3, (not that it shouldn't). [...] I have been unsuccessful at making it work. [A]: I suspect that if you reset the prefs to match FBII, you'll get it to start working. The list manager uses a lot of points that are dimmed as celly,cellx. If you use DIM celly,cellx, those items are put in registers and will not work. You can bypass this with DIM@ celly,cellx.[Q]: Could someone tell me how to get started with using a TOOLBOX FN for which no addresses are given. When they are given, for example toolbox Fn Gestalt(long,@long) = longI have no problem, but it seems many of the newer functions and procedures are given without such addresses being listed in any of the Interfaces libraries from Apple's documentation, in particular not in the C Includes. To take an example we have all seen, [...] the Sprockets FB^3 project that uses the DrawSprocket and InputSprocket libraries. The Toolbox defs do not include addresses, for exampletoolbox fn DSpStartup () = intand when I try to run the project it crashes on reaching this call - the first Toolbox call in the program. When I have tried to add similar calls without addresses to headers then call them I get the same result - Crash. I thought maybe the trick was to put the corresponding StubLibrary in the Extensions folder, or possibly in the same folder as the compiler, but this did not help at all. So, if you know what is needed, or how to get the Sprockets libtest to work, would you please explain. [A]: That's the problem with C and the MacOS. At some point, everyone thought it would be a great idea to use shared libraries for everything, instead of the a-trap addresses. The advent of the PowerPC necessitated this change and the various headers are kind of 'mixed and matched' now. First thing's first. If a call has no trap words then it is PowerPC only. A 68k compile will die a horrible death. So don't do that. (There is a 68k version of the cfm which the LIBRARY statement uses but I have no knowledge of whether FB currently uses it) The next important thing is you must find out what Shared Library the calls you are defining live in. For the DrawSprocket example you'll need the DrawSprocketLib and the InsputSprocketLib files in either a), your applications folder, or b) the extensions folder. Take special note that adding a library to your extensions folder does not normally require a restart. Feature :-) Of course I bet you are wondering how to figure out what headers refer to what libraries. Well so are the C programmers. The C header files that a C programmer includes will resolve to any...oh boy gotta think... shared library that has been loaded to that point. Kinda like how GetResource scans all open resource files, a C header will eventually find the shared library that has the given call. I'm not sure how CodeWarrior works that magic, buts its a pretty nifty trick. But a C programmer still has to include the library or stub. Reasons that your code may have crashed: Missing DrawSprocket or InputSprocket libraries or they are in the wrong place or you tried to use those libraries on a 68k machine or with a 68k compile on a ppc which only Andy can say if it would work. It is possible. Try dragging DrawSprocketLib into your project folder to be sure that the Lib can be found. The one that will get you for sure are the Libraries that have been rolled into the System file itself. The System folder counts as being one of the open code fragment chains just like it counts as an open resource file so some C headers are resolving to procedures in the System file. The problem is that in FB we have to *specify* the shared library the calls we are defining live in, while C programmers just have to find it somewhere and drop it into their project manager and the compiler will link the prototypes to the right symbols. |
||||||||
|
[ritorna all'inizio] |
DON'T TRY THIS AT HOME [Q]: If you run Example One below, it will change the system font for the Finder and everything else! It seems to be because there is no window open when the call is made to "TEXT". Note that this only happens in FB^3, as FBII protects you from such stupidity. The second example will correct the problem, so that you can get back to work. '------- Cut Here For Example One --------[A]: Thank you. Even better still... don't call TEXT until you have a window open! |
||||||||
|
[ritorna all'inizio] |
PALETTES [Q]: If a window is already open, and you open a window with a _keepinback, the already open window's edit fields are also disabled. The modal window works ok and is not a palette?[A]: In FBII, there really isn't such a thing as a palette. There are keepinback windows and other windows. When a keepinback window is present, other windows are palettes. When a keepinback window is not present, other windows are just windows.Is a modal window a palette? Yes, if a keepinback document is present. No, if a keepinback document is not present. |
||||||||
|
[ritorna all'inizio] |
DECLARATIONS [Q]: In a Begin Record structure I have this: DIM to as unsigned LongWorks great even though to is a keyword. However when I have this:DIM Error as Unsigned LongWhich FB doesn't like; it gives a "Already defined" Error. Why does one keyword type work but not the other? Just curious. The true records have been letting me use just about anything under the sun except this field name. [A]: DEFINE fails if the variable type is defined. Being a keyword and being a variable type are actually two different things. |
||||||||
|
[ritorna all'inizio] |
ASSEMBLY [Q]: I'm a bit unclear on how to handle BEGINASSEM and ENDASSEM. The following bit of 68K code [... snip...] works fine in FBII or in FB3 compiled for 68K. However, I haven't been able to get it to work in a fat or PPC compile, even if enclosed by the BEGINASSEM cpu68K and ENDASSEM structures.[A]: Sorry. No 68k assem in PPC compiles. [Q]: I have 68K assembler in my FBII app; Should I translate it to PPC assembler? [A]: A general answer to this is NO! Here's why. That code was in 68K assembler for speed. But don't forget that the code that FB^3 generates is fast. In some cases several hundred times faster than FBII! But FB^3 is more than damn fast, it's a whole new animal. And it's no secret that Andy Gariepy - FB engineer 'par excellence' - has stated that FB^3 is designed to be platform independent. (He has not, however, made any promises...). This means then that you should keep as much of your code as pure FB as possible. Why? Let's us suppose that one day we see a version of Mac OS that works on Intel boxes (I can't for my life think why anyone should want this, but as we are in the realms of supposition, just suspend belief and continue reading). So with a Mac OS on an Intel box, your PPC code will break your app. If your code is FB code however, you'll just have to install the 'MacOS-on-Intel back-end' for FB, probably change a few header files, installing the ones that Andy'll sent you with the 'M-o-I b-e', and Robert's your uncle... you're one of the first apps running on an MacIntel box! [Q]: I have 68K assembler code in my FBII app; How can I translate this to FB? [A]: Some has already been translated by Andy Gariepy himself for the benefit of Beta testers who asked this same question. (I'll put up a web page of snippets and their FB^3 equivalents - watch out for a URL here). But for stuff that hasn't already been translated... Just post the snippets on the FBII list, with the label [68K->FB^3], and then others can help you translate this to FB^3. I can then collect the stuff for the FAQ pages, and everyone will be coding much better and faster! [Q]: Are there cases when I would need to code in PPC assembler? [A]: It would be foolhardy to say 'No'! I can imagine at least 2 cases: Ultra-fast pumping of graphics to screen - even though Apple has, under pressure from game coders, slipped some damn fast routines that cut through QuickDraw bottlenecks. These sorts of things are hidden in the GameSprockets libraries. Another case would be PhotoShop style number crunching, but in this case you're not talking about number crunching in assembler, but more about "a library to number crunch with G4s and AltiVec", and "a library to number crunch with G3s", and "a library to number crunch with PPC 604s"... because if speed is really your concern you can't optimise just for a 'standard' PPC, you'll have to optimise down to generation level on the different processors. All this goes to argue for avoiding PPC code in FB^3, but feel free to try it out. And don't forget to share your experience with others. [Q]: Hi, all. I have a data acquisition program that talks to National Instruments A/D cards. This is done through 20 or 30 small functions provided by Nat. Instruments for FBII. They all use the CALL F&(...) structure, which FB3 doesn't seem to like. Here is an example:LOCAL MODE[A]: Andy replied: LOCAL MODEUntested but should work in general PPC & 68k [Q]: I use this code - how should I go about translating it for FB^3? ' -------------------------------------------------------[A]: Andy replied: LOCAL MODEin FB3 this code should be fast... |
||||||||
|
[ritorna all'inizio] |
FLASHING ANIMATION [Q]: Paste in this FB^3 program, run it (using FB II Runtime) and play with it for a few seconds. '-----The Flasher----- doRemind you of something? It reminds me of hours struggling with my animation programs, trying to eradicate this behaviour. The phenomenon was discussed at length on the FB list many moons ago. One of the solutions given then was an ingenious patch to the FBII runtime. I do remember Staz announcing with justifiable pride that in FB^3 we would be able to examine and modify the runtime. [A]: The content area has to be erased or you would end up with gibberish on the screen after grows and zooms. If you change your window type to _docZoom and put the rect at 10,10, you'll see one of the problems.One way to fix this is to put in a VALIDRECT after the calls to PAINTRECT. But [...] drawing to a window at any time other than an update just won't work.[Q]: Having a look at the Lite Runtime, I find that the cause lies in FN FBWindowUpdate in "Rntm FBII.Incl". FN FBWindowUpdate deals with the _wndRefresh event, and contains the lineEraseRect(#thisPort&+_PortRect)If I comment out the line, save the file, and re-run The Flasher, [...] the problem is cured. [A]: This is a standard Macintosh behavior. It is not something that is within our control. [Q]: So why is my window erased after I draw in it? [A]: You should never draw into a window until you have received an update event. Here's an explanation of how the Mac handles updates and why you should react at the proper time: When a window is built or brought forward, most often all of part of its content must be refreshed. The window manager collects these "clobbered" areas in a structure called an update region (sometimes called the clobbered region). You can force pieces of a window to be added to this region by calling CALL INVALRECT(t), and force pieces to be subtracted from the region by calling CALL VALIDRECT(t).When nothing else is going on in MacDom, the Window Manager looks around to see what needs to be fixed and sees that it has an update region for your window. It builds a fake event ( _updatEvt) and sends it through the event queue.FutureBASIC sees the update event and calls BEGINUPDATE. This swaps the visible region with the clobbered region. FB then erases the clobbered area, redraws all controls and fields, then calls your program to do its drawing via the _updatEvt. When your program receives the _updatEvt event, you are expected to draw the windows contents. When everything is finished, FB calls ENDUPDATE to reset all regions back to normal.Remember: anytime a window is built, the Window Manager automatically sends you an update event - without fail. You can count on it. If you draw into a window when it is first built or when some button is clicked or a menu item is selected, rather than in response to an update event, the update sequence will erase your work; and after the update you'll be looking a blank window. Always do your drawing in response to update events. |
|
© 2000 Pix&Mix
Tutti i diritti riservati |
||
|
FutureBASIC è un marchio registrato di Staz Software, Inc ed è usato previa autorizzazione. |
||