[comp.sys.mac.programmer] Init help again

mxmora@unix.SRI.COM (Matt Mora) (05/04/90)

[ this post is kinda long]

I would like to thanks all the people who responded to my plea. They
convinced me that I should NOT be doing trap patching without using
assembly (or C). (and without knowing what the hell I'm doing) :-) This is
because you have to becareful about returning the stack and the registers
back to the way they were before the patch. (not an easy task in pascal)

Oh and I love the tech note # 110, an INIT that goes beep. Give me a
*ucking break. It doesn't say anything about patching a trap or installing
anything. The MacTutor article was helpful but it explains how to install a
vbl task. My Code will definitely move memory.

What this init will do: This init will make the remaining fkeys on the
extended keyboard actually do something. In your system folder you create a
folder called FKeys. In this folder you put fkey files named FKEYn. (where
n is the number of the fkey. i.e 'FKEY5' will be launched when the user
hits the F5 key.). This way you don't have to install the fkey in the
system file and you don't have to worry about the fkey ids. This also
allows you to keep the standard command shift fkeys.

anyway...

So I decided to go the jGNEfilter route. I included into this post the
complete source code in hopes that some great soul could show me the errors
of my ways. (and give me a (pointer) math lesson) :-)


unit newJGNEFilter; interface

  procedure main;

implementation

  procedure DoJsr (addr: ProcPtr);
  inline
    $205F, $4E90;
  procedure DoJmp (addr: ProcPtr);
  inline
    $205F, $4ED0;           {is this Correct?}

  procedure main;
    const
      F5 = 96;
      F6 = 97;
      F7 = 98;
      F8 = 100;
      F9 = 101;
      F10 = 109;
      F11 = 103;
      F12 = 111;
      F13 = 105;
      F14 = 107;
      F15 = 113;
    var
      Filename, name: str255;
      error, refnum: integer;
      myfkeyhandle: handle;
      addr, oldjgne: procptr;
      id, i, thekey: integer;
      rType: restype;
      keys: keymap;
  begin
    GetKeys(keys);
    for i := 0 to 127 do
      begin
        if keys[i] then
          thekey := i
        else
          thekey := -1;
      end;

    if thekey <> -1 then
      case thekey of
        F5:
          Filename := 'FKEY5';
        F6:
          Filename := 'FKEY6';
        F7:
          Filename := 'FKEY7';
        F8:
          Filename := 'FKEY8';
        F9:
          Filename := 'FKEY9';
        F10:
          Filename := 'FKEY10';
        F11:
          Filename := 'FKEY11';
        F12:
          Filename := 'FKEY12';
        F13:
          Filename := 'FKEY13';
        F14:
          Filename := 'FKEY14';
        F15:
          Filename := 'FKEY15';
        otherwise
          Filename := '';
      end;
    if filename <> '' then
      begin
    
        name := concat('hd 40:System folder:FKEYS:', filename);
                  {hard coded just for testing purposes}
        refnum := OpenResFile(name);
        if refnum <> -1 then
          begin
            myfkeyhandle := Get1IndResource('FKEY', 1);
            if myfkeyhandle <> nil then
              begin
                GetResInfo(myfkeyhandle, id, rType, name);
                HLock(myFkeyhandle);
                addr := procptr(myfkeyhandle^);
                DoJsr(addr);
                hunlock(myfkeyhandle);
                ReleaseResource(myfkeyhandle);
              end;
          end;
      end;
    oldjgne := procptr(ord(@main) + 10);    {get address that was stored}
                                            {into header}
    DoJmp(procptr(oldjgne^));         {jmp to address stored in header}
  end; end.

The code that launches the fkey actually works. (I tried it as a
application). The problem I think is in my pointer math. I don't think I'm
getting the right address to jump to or maybe I'm storing the address in
the wrong spot.

Below is the code that installs the init. It seems to work because the Mac
won't crash untill the start up process reaches the finder then it goes
labomba. But then I could be really screwing something up and it doesn't
show up until the finder starts.

unit install; interface
  procedure main; implementation

  procedure main;
    var
      newjgne: Handle;
      addr: longint;
      JGNE: ^ptr;
  begin
    SetZone(SystemZone);
    newjgne := Get1Resource('CODE', 128);
    if newjgne <> nil then
      begin
        DetachResource(newjgne);
        HLock(newjgne);
        BlockMove(ptr($29A), ptr(ord(newjgne^) + 10), 4);
            {move old jgne address into header of newcode}
        JGNE := pointer($29A);
        JGNE^ := pointer(newjgne^); {store the new address into
                                    {lomemglobal}
      end;
  end; 
end.

According to the LSP manual on page 158:
  
When THINK Pascal creates a code resource it places this standard header
at the beginning:
  Offset        Contents
    0             BRA.S .+$10 (branch to header code)
    2             $0000  (unused)
    4             'TYPE'  (resource type)
    8             $000A  (resource ID)
   10             $0000  (unused)
   12             $0000  (unused)
   14             $0000  (unused)
 The standard header code puts the address of your code resource in TOLScratch
 and the branches to your main routine. You can do anything you like with the 
 unused words.

So I figured that I should stuff the address of where I should jump to into
the header at offset 10. Is this what I am doing?

Obviously I need all the help I can get.

Also, how does one get the name of the Init file? Do I just scan the system
folder until I see a file with my creator type?

Thanks in advance.

-- 
___________________________________________________________
Matthew Mora
SRI International                       mxmora@unix.sri.com
___________________________________________________________