• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Hypercard Serial

Phipli

Well-known member
Hey folks,

I've been putting together a Hypercard stack to control a serial i/o box and was doing quite well. I'm using the Hypercard Serial Toolkit. Everything was fine until I tried to read in data with values above 127 - it seems the recvBytes command accidentally uses the char datatype or something and effectively only reads 7 bits of an 8 bit number!

Does anyone have any experiece of this? Any suggestions - this was meant to be a hypercard project, yes I can and have used other environments, but I would like to get it working in Hypercard.

 

Phipli

Well-known member
Solved it - the code I based my setup on called "configureSPort stripOn" which I assumed was to do with white space... but was for stripping the top bit. Why? I don't know. Perhaps some systems used it for something else while sending regular 7bit ascii in 8 bits.

 

cheesestraws

Well-known member
Perhaps some systems used it for something else while sending regular 7bit ascii in 8 bits. 
That would be my guess too.  I vaguely remember reading about something like that, but I honestly cannot remember anything useful about it in order to look it up...

 

MrFahrenheit

Well-known member
If you ever want to experience faster speed and some simplicity, there's an app called CompileIt! that takes HyperTalk scripts and compiles them into an XCMD.  Makes them PPC native, too.  I used it back in the day when I had written an email client/server that I sold and I wanted to hide the code I was running, and I wanted to make it run faster.

 

Phipli

Well-known member
Thanks folks, @MrFahrenheit - that is interesting. I'm using a IIx so extra speed may be useful later.

Next question - is there any way to test bits in a variable? I can't see any bitwise operations. At the moment I'm just subtracting 128, 64, 32 etc and testing if the result is negative before moving on (with the non-subtracted number if it was negative)... but this is a bodge!

Basically, I'd like to test a single bit in an 8 bit value efficiently.

 
Last edited by a moderator:

Crutch

Well-known member
In HyperTalk? I don’t recall if bitwise operators were supported  ... but you can test bit n by dividing by 2^n (truncate the fractional part) and checking if the result is odd. 

 
Last edited by a moderator:

Phipli

Well-known member
@Crutch, yes, I'm using Hypertalk.

Thanks for the tip. That will speed up my code. Do I round or floor the result?

 

uliwitness

Active member
If you ever want to experience faster speed and some simplicity, there's an app called CompileIt! that takes HyperTalk scripts and compiles them into an XCMD. Makes them PPC native, too. I used it back in the day when I had written an email client/server that I sold and I wanted to hide the code I was running, and I wanted to make it run faster.
I think you have things mixed up a bit. CompileIt! was never made to output anything beyond 680x0 code.

However, Heizer shipped a demo of a stack that could be used on those XCMDs and recompile the 680x0 code to PowerPC (!). I'm not sure if they ever actually shipped that stack or if the demo was as far as it got. The mentioned version 3 of CompileIt! definitely never saw the light of day. Tom Pittman at least told me that "it had a lot of problems" and Heizer shut down and HyperCard got discontinued around that time and he never had much time to fix the problems in it.

Apparently, this all was a side effect of an abandoned attempt to write a faster version of Apple's 68k emulator on Tom's side.
 

Attachments

  • Screen Shot 2014-02-18 at 22.42.37.png
    Screen Shot 2014-02-18 at 22.42.37.png
    20.7 KB · Views: 4

uliwitness

Active member
However, Heizer shipped a demo of a stack that could be used on those XCMDs and recompile the 680x0 code to PowerPC (!).
Full text and the script from this stack for the curious:

Sample “Fat” XCMD compiled by CompileIt

The script of this field (click “See Script” button below) contains the source HyperTalk for the XCMD in this stack, which was compiled by CompileIt with a developmental binary recompiler module added. The recompiler will be made available from Heizer Software as an add-on to CompileIt, hopefully in the first half of 1995. CompileIt 3.0 (still under development) will integrate the recompiler and include improved symbol table management.

The recompiler allows XCMD developers to create “fat” XCMDs that run in any version of HyperCard, but when they are on a Power Macintosh they use native code for accelerated performance. You can also build mostly-native XCMDs with a 68K wrapper that exits gracefully if called on a 68K Mac. These XCMDs gain the full performance advantage of the PowerPC without any need for a native version of HyperCard. If and when Apple ships a native code version of HyperCard, these fat XCMDs will continue to take advantage of their native code acceleration, while the stack and card scripts come up to the native-code enhanced speed the fat XCMDs already enjoy.

How to Write a Fat XCMD (details subject to change):

Just write your XCMD or XFCN for CompileIt as you normally would, but separate out the main loops into subroutines and/or functions called by the main handler. Then duplicate these new handlers and give the copies slightly different names. Collect the copies at the end of your script, followed by a special function that lists them for recompilation (see the example script). You can also use this function to determine if it is safe to call the native code: your XCMD will bomb if you try to call native code handlers on a 68K Mac.

Don’t try to do too much in one native-code handler. To get the performance we all hope for, the PowerPC must put all its variables in registers. There are only 18 integer (plus 20 floating-point) registers available for variables; when these are used up in a handler, variables must be flushed to memory, which makes everything much slower.

How Much Faster Is It?

Apple has been telling developers that most code runs two to five times faster by going native. This is not strictly true. Programs with small, numerically intensive loops will do very well. Large program loops (like Excel, larger than your typical XCMD) will only go about 30% faster than emulated. XCMDs that mostly work on character strings will probably see no improvement at all, because these operations are done by Toolbox routines in ROM, which are already in native code. Your best improvement will be seen in floating-point operations. The CompileIt recompiler has been designed especially to optimize small loops with floating-point operations, which the PowerPC does well.

Anything that does not execute at least dozens of times in one XCMD call is probably not worth taking native, because the cost of calling the XCMD in the first place will dominate the first ten or more times through the loop.

What About Native-Only XCMDs?

As of this writing, Apple has not published guidelines for native-only XCMDs, but I do not expect them to perform significantly better than fat XCMDs, for the simple reason that the cost of loading the XCMD into memory, moving its handle high, and locking it down is the same whether native or emulated — it could even be somewhat higher for native XCMDs because they are bigger. CompileIt 3.0 will support the creation of native-only XCMDs if that is appropriate, along with other native-code or fat code resources.

One hurdle yet to be overcome is the file format for these: Apple is restricting the use of their native-code PEF file format to big developers willing to pay large $$ license fees. We are still looking at ways to get around that (our fat XCMDs do not use PEF).

The code:

-- Sample “Fat” XCMD compiled with (developmental) CompileIt! -- This script will not run as-is in HyperCard, it must be compiled global x:F -- shared variable required for return float value on TestNativeX theTest -- compile this with Sane turned off -- validate the test number and (if necessary) the CPU.. put theTest+0 into testnum if testnum<1 or testnum>4 then -- invalid param, say what? answer "Usage: TestNativeX theTest -- theTest:" & return ¬ & " -- 1= 68K integer, 2= 68K Sane," & return ¬ & " -- 3= native int, 4= native float" exit TestNativeX end if if testnum>2 then if not ThisIsPowerPC() then answer "That test requires a Power Macintosh" exit TestNativeX end if -- initialize test data.. if testnum mod 2 =0 then -- floating-point data.. put 2147483648.00000190921128 into x put 536870912.00000047730282 into y put -1152921504606846976.0 into z put 1 into testData else put 0 into testData if testnum>2 then put "(PowerPC)" into theCPU else put "(68K)" into theCPU put Ticks into here -- synchronize clocks.. repeat while Ticks=here end repeat put Ticks into here -- start timer if testData>0 then -- floating-point test.. if testnum=2 then Do68Kfloat y,z put 1000 into testData -- else too slow! else DoPPCfloat y,z get (Ticks-here)*testData answer "x*y+z = " & x & ", " & it & " ticks " & theCPU else -- integer test.. if testnum=1 then put Do68Kint(2,3) into testData else put DoPPCint(2,3) into testData get Ticks-here answer "x*y+5 = " & testData & ", " & it & " ticks " & theCPU end if end TestNativeX function Do68Kint a,b -- identical 68K & native for comparison repeat 1000000 put a*b+5 into c end repeat return c end Do68Kint on Do68Kfloat yy,zz -- 68K is simpler than PowerPC, because it’s slower put x into xx repeat 10000 -- then multiply time x 1,000 put xx^1*yy+zz into rr end repeat put rr into x end Do68Kfloat -- best: collect all native-code handlers at end.. function DoPPCint a,b -- identical 68K & native for comparison repeat 1000000 put a*b+5 into c end repeat return c end DoPPCint on DoPPCfloat yy,zz put x into xx repeat 10000000 -- yes, ten million! put xx^1*yy+zz into rr end repeat put rr into x end DoPPCfloat function ThisIsPowerPC -- this must be after last native handler -- call this function once before calling native handlers -- check for PowerPC Mixed-Mode Manager.. if Gestalt("mixd",ppc)≠0 then put false into ppc if not ppc then return false -- important: exit now if not PowerPC -- translate the 68K into PowerPC code.. INLINE ">Recompile,DoPPCint" -- recompiles at compile-time, INLINE ">Recompile,DoPPCfloat" -- also initializes run-time INLINE ">PPClibrary" -- last, necessary to link library & Toolbox return true end ThisIsPowerPC
 

Attachments

  • Screenshot 2021-08-14 at 13.05.52.png
    Screenshot 2021-08-14 at 13.05.52.png
    77.8 KB · Views: 3

MrFahrenheit

Well-known member
I think you have things mixed up a bit. CompileIt! was never made to output anything beyond 680x0 code.

Interesting. I bought CompileIt! 2.6.1 back in .... 1995 or 1996 (can't remember) and I had thought it compiled fat binary XCMDs. If it didn't, my bad. By 1996, I would expect most software to be PPC fat/native. I guess CompileIt! had issues.
 
Top