English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 21 May 2014, 02:14   #21
hukka
Wolf-bear thing
hukka's Avatar
 
Join Date: Jan 2014
Location: Finland
Age: 35
Posts: 56
Quote:
Originally Posted by Photon View Post
This gives you a lock on the current folder, though I've seen a lock of 0 is valid in some doc.
Thanks for the snippet! I didn't test it yet, but I'm assuming it should also work when launched from CLI, and not only Workbench?

I needed this for a little game I'm working on. I decided I wanted to have the game's data files in their own directory instead of the base directory where the executable resides. This is how I ended up implementing it:
  • Game is hardcoded to load data files from "PROGDIR:data/"
  • When booted from floppy, the first line in startup-sequence assigns PROGDIR to DF0:, to make up for the fact that Kickstart 1.x doesn't automatically make the assignment upon launching.
  • Game will now run properly from floppy, but can only be successfully launched from Workbench in later Kickstart versions. However this is probably good enough for my purposes.
hukka is offline  
AdSense AdSense  
Old 21 May 2014, 11:22   #22
Mrs Beanbag
Glastonbridge Software
Mrs Beanbag's Avatar
 
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,202
Quote:
Originally Posted by Photon View Post
I'm very weak on Workbench programming, but for a normal "double click icon" program I don't know what other folder it could be started from.
I'm not sure which folder it starts in but it doesn't start in the executable's path, from my experience. I have to get the lock from the WB Message and then CurrentDir to it.

Relative paths is the easiest way. I really wouldn't worry about all this "PROGDIR:" stuff. If you want to boot from floppy just prepend "data/" to the filenames in the code. "data/" is sufficient.

You could always output an informative error message if the data files are not found, like "make sure the current directory contains the program data files" or somesuch.

Last edited by Mrs Beanbag; 21 May 2014 at 11:29.
Mrs Beanbag is offline  
Old 21 May 2014, 15:13   #23
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,503
The snippet was for Leffmann - and it still only allows building up the absolute path from the current directory, not the one the exe is in.

For example, if you put the exe in c:, then cd sys:, then run c:exename, getting a lock on the dirname "" (empty string) is a lock on sys: because that was your current directory (for that shell process, presumably).

The best option to me seems to be to use relative paths for all loaded files and make sure those work in some way external to the program, like executing a script or editing an icon (if that's possible).
Photon is offline  
Old 25 May 2014, 22:28   #24
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,085
Thanks for the code, though the solution I presented earlier is still complete, and solves all of this... it will find the program directory and CD into it, and it works on all Kickstarts, from both Workbench and from any directory on the command line.
Leffmann is offline  
Old 03 June 2014, 14:15   #25
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,503
Quote:
Originally Posted by Leffmann View Post
Thanks for the code, though the solution I presented earlier is still complete, and solves all of this... it will find the program directory and CD into it, and it works on all Kickstarts, from both Workbench and from any directory on the command line.
Hm, ok sorry. The way you wrote it made me unsure if it was tested. Buuut... wouldn't the same "current, not executable's dir" problem still be there for Process->pr_CLI->cli_SetName?
Photon is offline  
Old 09 June 2014, 22:13   #26
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,085
Well like I wrote in my first post, you have to make use of cli_CommandName to find the program directory, and actually you don't have to concatenate with cli_SetName at all because Lock() works on relative paths.

Code:
          include macros.i
          include dos/dosextens.i
          include workbench/startup.i

;------------------------------------------------------------------------------
          section code

          ; Find our Process and CLI structure

          sub.l     a1, a1
          execall   FindTask
          move.l    d0, a2                   ; A2 = Process
          move.l    (pr_CLI, a2), a3         ; A3 = CommandLineInterface
          add.l     a3, a3
          add.l     a3, a3

          ; Get startup message and directory lock if we started from Workbench

          move.l    a3, d0
          if_null
           lea      (pr_MsgPort, a2), a0
           libcall  WaitPort
           lea      (pr_MsgPort, a2), a0
           libcall  GetMsg
           move.l   d0, a4                   ; A4 = WBStartup
           move.l   (sm_ArgList, a4), a0
           move.l   (wa_Lock, a0), a5        ; A5 = FileLock on program dir
          end_if

          moveq     #33,d0
          lea       .doslib, a1
          libcall   OpenLibrary
          move.l    d0, _DOSBase

          ; Get FileLock via command name if we started from CLI

          move.l    a3, d0
          if_not_null
           sub      #200, sp

           ; Copy BCPL string to C-style string

           move.l   (cli_CommandName, a3), a0
           add.l    a0, a0
           add.l    a0, a0
           move.b   (a0)+, d0
           move.l   sp, d1                   ; D1 = command name string
           move.l   sp, a1
.1         move.b   (a0)+, (a1)+
           subq.b   #1, d0
           bne      .1
           sf       (a1)

           ; Get a lock on the program and its parent

           move.l   #SHARED_LOCK, d2
           doscall  Lock
           move.l   d0, d2
           move.l   d0, d1
           libcall  ParentDir
           move.l   d0, a5                   ; A5 = FileLock on program dir
           move.l   d2, d1
           libcall  UnLock

           add      #200, sp
          end_if

          ; CD to the program dir, run the main program, and CD back to the
          ; previous dir

          move.l    a5, d1
          doscall   CurrentDir
          movem.l   d0/a3-a5, -(sp)
        ; bsr       mainprogram
          movem.l   (sp)+, d0/a3-a5
          move.l    d0, d1
          doscall   CurrentDir

          ; Clean up and exit

          move.l    a3, d0
          if_not_null
           move.l   a5, d1
           libcall  UnLock
          end_if

          move.l    _DOSBase, a1
          execall   CloseLibrary

          ; Reply to the startup message

          move.l    a3, d0
          if_null
           libcall  Forbid
           move.l   a4, a1
           libcall  ReplyMsg
          end_if

          moveq     #0, d0
          rts

.doslib   dc.b      "dos.library", 0
          even


;------------------------------------------------------------------------------
          section bss

_DOSBase  ds.l      1
Here's the C-version as well:
Code:
/* CD into program's own directory on Kickstart 1.3.
   Link with minimal C-startup. */

#include <string.h>
#include <dos/dosextens.h>
#include <workbench/startup.h>
#include <proto/exec.h>
#include <proto/dos.h>

typedef void* PTR;
struct DosLibrary* DOSBase;

static void mainprogram();


int main()
{
  struct Process* proc = (PTR)FindTask(NULL);
  struct CommandLineInterface* cli = (PTR)(proc->pr_CLI*4);
  struct WBStartup* wbmsg = NULL;
  BPTR progdir, prevdir;

  /* If we started from Workbench then we must retrieve the startup message
     before doing anything else. The startup message also contains a lock on
     the program directory. */

  if (!cli)
  {
    WaitPort(&proc->pr_MsgPort);
    wbmsg = (PTR)GetMsg(&proc->pr_MsgPort);
    progdir = wbmsg->sm_ArgList[0].wa_Lock;
  }

  DOSBase = (PTR)OpenLibrary("dos.library", 33);

  /* If we started from CLI then we have to go via the command name to get
     a lock on the program dir. */

  if (cli)
  {
    unsigned char* p;
    BPTR prglock;

    /* Copy the command name BCPL string to a C-style string. */

    char cmd[200];
    p = (PTR)(cli->cli_CommandName*4);
    memcpy(cmd, p+1, p[0]);
    cmd[p[0]] = 0;

    /* Lock on the command name and get its parent, which will be the program
       dir. This works because Lock() accepts relative paths. */

    prglock = Lock(cmd, SHARED_LOCK);
    progdir = ParentDir(prglock);
    UnLock(prglock);
  }

  /* Save the current dir, CD into the program dir, and run our program.
     We must always CD back to the dir we started in before we exit. */

  prevdir = CurrentDir(progdir);
  mainprogram();
  CurrentDir(prevdir);

  if (cli)  UnLock(progdir);
  CloseLibrary((PTR)DOSBase);

  /* Reply to the startup message if we received one. */

  if (wbmsg)
  {
    Forbid();
    ReplyMsg((PTR)wbmsg);
  }

  return 0;
}



static void mainprogram()
{
  /* See if we can find "file", and print a status message. */

  BPTR con = Open("con:50/50/200/50/Console", MODE_NEWFILE),
       lock = Lock("file", SHARED_LOCK);

  if (lock)  Write(con, "OK file found", 13);
  else       Write(con, "ERROR file not found", 20);

  Delay(50);
  Close(con);
  if (lock)  UnLock(lock);
}
Leffmann is offline  
Old 10 June 2014, 10:46   #27
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 764
Interesting.. didn't think you could do ParentDir() on a file lock..
hooverphonique is offline  
Old 13 June 2014, 23:40   #28
itix
 
Posts: n/a
Quote:
Originally Posted by hukka View Post
Thanks for the snippet! I didn't test it yet, but I'm assuming it should also work when launched from CLI, and not only Workbench?

I needed this for a little game I'm working on. I decided I wanted to have the game's data files in their own directory instead of the base directory where the executable resides. This is how I ended up implementing it:
  • Game is hardcoded to load data files from "PROGDIR:data/"
  • When booted from floppy, the first line in startup-sequence assigns PROGDIR to DF0:, to make up for the fact that Kickstart 1.x doesn't automatically make the assignment upon launching.
  • Game will now run properly from floppy, but can only be successfully launched from Workbench in later Kickstart versions. However this is probably good enough for my purposes.
There is another trick you can try. Relabel your floppy to have somewhat unique name, lets say HUKKAGAME. Now you can access all files using absolute path "HUKKAGAME:data/". This works on Kickstart 1.3 and 2.0+, it works from CLI and WB and it works even when installed to harddisk if you add HUKKAGAME assign to game executable directory.

This is how many old Amiga games worked with floppies and harddisk install.
 
Old 01 January 2018, 07:58   #29
alpine9000
Registered User

 
Join Date: Mar 2016
Location: Australia
Posts: 493
Quote:
Originally Posted by Leffmann View Post
Well like I wrote in my first post, you have to make use of cli_CommandName to find the program directory, and actually you don't have to concatenate with cli_SetName at all because Lock() works on relative paths.

Code:
          include macros.i
          include dos/dosextens.i
          include workbench/startup.i

;------------------------------------------------------------------------------
          section code

          ; Find our Process and CLI structure

          sub.l     a1, a1
          execall   FindTask
          move.l    d0, a2                   ; A2 = Process
          move.l    (pr_CLI, a2), a3         ; A3 = CommandLineInterface
          add.l     a3, a3
          add.l     a3, a3

          ; Get startup message and directory lock if we started from Workbench

          move.l    a3, d0
          if_null
           lea      (pr_MsgPort, a2), a0
           libcall  WaitPort
           lea      (pr_MsgPort, a2), a0
           libcall  GetMsg
           move.l   d0, a4                   ; A4 = WBStartup
           move.l   (sm_ArgList, a4), a0
           move.l   (wa_Lock, a0), a5        ; A5 = FileLock on program dir
          end_if

          moveq     #33,d0
          lea       .doslib, a1
          libcall   OpenLibrary
          move.l    d0, _DOSBase

          ; Get FileLock via command name if we started from CLI

          move.l    a3, d0
          if_not_null
           sub      #200, sp

           ; Copy BCPL string to C-style string

           move.l   (cli_CommandName, a3), a0
           add.l    a0, a0
           add.l    a0, a0
           move.b   (a0)+, d0
           move.l   sp, d1                   ; D1 = command name string
           move.l   sp, a1
.1         move.b   (a0)+, (a1)+
           subq.b   #1, d0
           bne      .1
           sf       (a1)

           ; Get a lock on the program and its parent

           move.l   #SHARED_LOCK, d2
           doscall  Lock
           move.l   d0, d2
           move.l   d0, d1
           libcall  ParentDir
           move.l   d0, a5                   ; A5 = FileLock on program dir
           move.l   d2, d1
           libcall  UnLock

           add      #200, sp
          end_if

          ; CD to the program dir, run the main program, and CD back to the
          ; previous dir

          move.l    a5, d1
          doscall   CurrentDir
          movem.l   d0/a3-a5, -(sp)
        ; bsr       mainprogram
          movem.l   (sp)+, d0/a3-a5
          move.l    d0, d1
          doscall   CurrentDir

          ; Clean up and exit

          move.l    a3, d0
          if_not_null
           move.l   a5, d1
           libcall  UnLock
          end_if

          move.l    _DOSBase, a1
          execall   CloseLibrary

          ; Reply to the startup message

          move.l    a3, d0
          if_null
           libcall  Forbid
           move.l   a4, a1
           libcall  ReplyMsg
          end_if

          moveq     #0, d0
          rts

.doslib   dc.b      "dos.library", 0
          even


;------------------------------------------------------------------------------
          section bss

_DOSBase  ds.l      1
Here's the C-version as well:
Code:
/* CD into program's own directory on Kickstart 1.3.
   Link with minimal C-startup. */

#include <string.h>
#include <dos/dosextens.h>
#include <workbench/startup.h>
#include <proto/exec.h>
#include <proto/dos.h>

typedef void* PTR;
struct DosLibrary* DOSBase;

static void mainprogram();


int main()
{
  struct Process* proc = (PTR)FindTask(NULL);
  struct CommandLineInterface* cli = (PTR)(proc->pr_CLI*4);
  struct WBStartup* wbmsg = NULL;
  BPTR progdir, prevdir;

  /* If we started from Workbench then we must retrieve the startup message
     before doing anything else. The startup message also contains a lock on
     the program directory. */

  if (!cli)
  {
    WaitPort(&proc->pr_MsgPort);
    wbmsg = (PTR)GetMsg(&proc->pr_MsgPort);
    progdir = wbmsg->sm_ArgList[0].wa_Lock;
  }

  DOSBase = (PTR)OpenLibrary("dos.library", 33);

  /* If we started from CLI then we have to go via the command name to get
     a lock on the program dir. */

  if (cli)
  {
    unsigned char* p;
    BPTR prglock;

    /* Copy the command name BCPL string to a C-style string. */

    char cmd[200];
    p = (PTR)(cli->cli_CommandName*4);
    memcpy(cmd, p+1, p[0]);
    cmd[p[0]] = 0;

    /* Lock on the command name and get its parent, which will be the program
       dir. This works because Lock() accepts relative paths. */

    prglock = Lock(cmd, SHARED_LOCK);
    progdir = ParentDir(prglock);
    UnLock(prglock);
  }

  /* Save the current dir, CD into the program dir, and run our program.
     We must always CD back to the dir we started in before we exit. */

  prevdir = CurrentDir(progdir);
  mainprogram();
  CurrentDir(prevdir);

  if (cli)  UnLock(progdir);
  CloseLibrary((PTR)DOSBase);

  /* Reply to the startup message if we received one. */

  if (wbmsg)
  {
    Forbid();
    ReplyMsg((PTR)wbmsg);
  }

  return 0;
}



static void mainprogram()
{
  /* See if we can find "file", and print a status message. */

  BPTR con = Open("con:50/50/200/50/Console", MODE_NEWFILE),
       lock = Lock("file", SHARED_LOCK);

  if (lock)  Write(con, "OK file found", 13);
  else       Write(con, "ERROR file not found", 20);

  Delay(50);
  Close(con);
  if (lock)  UnLock(lock);
}
Digging up an old thread. I just used this code for searching for data files in KS1.3 (Does anyone use KS1.3 anymore ?!

Seemed to work great, I don't suppose you have made any updates in the past 4 years ?

Thanks for posting
alpine9000 is offline  
Old 01 January 2018, 22:03   #30
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,085
Quote:
Originally Posted by alpine9000 View Post
Seemed to work great, I don't suppose you have made any updates in the past 4 years ?
Glad someone found this useful! And no, no updates, but please post if you come up with something.
Leffmann is offline  
AdSense AdSense  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
screenshot of my current project ara Coders. General 10 08 October 2012 17:07
My current mini-project. Desverger support.Hardware 0 21 August 2004 06:44
limit to files in a directory? yadster support.Hardware 7 09 August 2003 15:00
assembly TV L8-X Amiga scene 2 04 August 2002 02:36

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 16:28.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.
Page generated in 0.12930 seconds with 14 queries