21 May 2014, 02:14 | #21 | |
Wolf-bear thing
Join Date: Jan 2014
Location: Finland
Age: 41
Posts: 56
|
Quote:
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:
|
|
21 May 2014, 11:22 | #22 | |
Glastonbridge Software
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,243
|
Quote:
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. |
|
21 May 2014, 15:13 | #23 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
|
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). |
25 May 2014, 22:28 | #24 |
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
|
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.
|
03 June 2014, 14:15 | #25 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
|
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?
|
09 June 2014, 22:13 | #26 |
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
|
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 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); } |
10 June 2014, 10:46 | #27 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
Interesting.. didn't think you could do ParentDir() on a file lock..
|
13 June 2014, 23:40 | #28 | |
Posts: n/a
|
Quote:
This is how many old Amiga games worked with floppies and harddisk install. |
|
01 January 2018, 07:58 | #29 | |
Registered User
Join Date: Mar 2016
Location: Australia
Posts: 881
|
Quote:
Seemed to work great, I don't suppose you have made any updates in the past 4 years ? Thanks for posting |
|
01 January 2018, 22:03 | #30 |
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
|
|
30 April 2021, 17:06 | #31 |
68k
Join Date: Sep 2005
Location: Somewhere
Posts: 828
|
I think that section with copying command name can be changed for following code
Code:
move.l cli_CommandName(a3),d1 lsl.l #2,d1 ;into address addq.l #1,d1 ;skip size ;out d1 - address to command name (as I checked on kick1.3 and kick3.1 is zero ended) |
02 May 2021, 16:06 | #32 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,216
|
On 1.3, this is probably only a coincidence as the name is put into MEMF_CLEAR memory. However, for some ( improper) name lengths, this is not true. The interface doesn't define it to be NUL-terminated.
|
02 May 2021, 23:24 | #33 |
68k
Join Date: Sep 2005
Location: Somewhere
Posts: 828
|
@Thomas Richter. Its very interesting, could you provide some 'bad' name example. I tried some cases but without luck. Always was zero at the end.
I tried following name length cases (kick 1.3): one char , two chars, 31 chars. I know that cli_CommandName is a BCPL type, but I think that internally is copied c-style string into address of cli_CommandName. As I checked on kick1.3 name in cli_Command is always 'clear' mean there is no trash after 'end' of name. Probably because there is no history buffer in k1.3. In kick3.1 there is a trash chars but name is always ends with zero. If I am wrong then please correct me. Thanks a lot. |
03 May 2021, 17:29 | #34 | ||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,216
|
Quote:
Quote:
But anyhow: There is nothing to depend upon - it's not documented. This is a BCPL string, so treat it as one. |
||
03 May 2021, 22:24 | #35 |
68k
Join Date: Sep 2005
Location: Somewhere
Posts: 828
|
@Thomas Richter.
Thanks for your replies. Next approach. Code:
move.l cli_CommandName(a3),a0 add.l a0,a0 add.l a0,a0 moveq #0,d0 move.b (a0)+,d0 clr.b (a0,d0.w) move.l a0,d1 |
04 May 2021, 09:16 | #36 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,216
|
|
04 May 2021, 12:07 | #37 |
68k
Join Date: Sep 2005
Location: Somewhere
Posts: 828
|
@Thomas Richter
Thanks for your reply. The obvious reason is clearing byte right after end of bcpl string. But according this link startup.asm you can find following block of code Code:
;[...] move.l cli_CommandName(a0),d0 lsl.l #2,d0 ; bcpl pointer conversion ;[...] ;-- copy command name move.l d0,a0 moveq.l #0,d0 move.b (a0)+,d0 ; size of command name clr.b 0(a0,d0.l) ; terminate the command name |
04 May 2021, 13:59 | #38 | ||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,216
|
Quote:
Quote:
|
||
21 May 2021, 03:52 | #39 |
Engineer
Join Date: Oct 2018
Location: Shadow realm
Posts: 165
|
Here's a "type" command. This is written by me; license is MIT like my pyamigadebug/amigaXfer project, which is very close to "do whatever you want" with it.
It uses LVOs and some defines for flags used in library calls, but otherwise is quite crude, Should work with AmigaDOS 1/2/3. Code:
include "lvo/exec_lib.i" include 'exec/exec.i' include "lvo/dos_lib.i" include "dos/dos.i" bufsize equ $1000 ;d0 dosCmdLen, a0 dosCmdBuf start: ;d5 filehandle, d6 dosCmdLen, d7 consolefh ;a3 buffer, a4 dosCmdBuf, a5 dosbase move.l d0,d6 ;save dosCmdLen movea.l a0,a4 ;save dosCmdBuf movea.l $4,a6 lea.l dosname,a1 jsr _LVOOldOpenLibrary(a6) tst.l d0 beq.b .exit movea.l d0,a5 movea.l a5,a6 lea.l conname,a0 move.l a0,d1 move.l #MODE_OLDFILE,d2 jsr _LVOOpen(a6) tst.l d0 beq.b .closedos move.l d0,d7 move.l $4,a6 move.l #bufsize,d0 move.l #MEMF_PUBLIC,d1 jsr _LVOAllocMem(a6) tst.l d0 beq.b .closecon movea.l d0,a3 move.b #0,(-1,a4,d6) ;replace ending \n with 0 in dosCmdBuf movea.l a5,a6 move.l a4,d1 move.l #MODE_OLDFILE,d2 jsr _LVOOpen(a6) tst.l d0 beq.b .openerr move.l d0,d5 .mainloop move.l d5,d1 move.l a3,d2 move.l #bufsize,d3 jsr _LVORead(a6) move.l d7,d1 move.l a3,d2 move.l d0,d3 jsr _LVOWrite(a6) cmp.l #bufsize,d0 beq.b .mainloop .closefile movea.l a5,a6 move.l d5,d1 jsr _LVOClose(a6) .freebuf movea.l $4,a6 move.l a3,a1 move.l #bufsize,d0 jsr _LVOFreeMem(a6) .closecon movea.l a5,a6 move.l d7,d1 jsr _LVOClose(a6) .closedos movea.l $4,a6 move.l a5,a1 jsr _LVOCloseLibrary(a6) .exit clr.l d0 rts .openerr lea.l openerrmsg,a0 move.l #openerrmsg_len,d0 jsr printmsg bra .freebuf ;a0 addr, d0 len, d7 fh printmsg: movea.l a5,a6 move.l d7,d1 move.l a0,d2 move.l d0,d3 jsr _LVOWrite(a6) rts dosname: dc.b "dos.library",0 conname: ;dc.b "CONSOLE:",0 ;'*' is deprecated, but kick <36 doesn't like 'CONSOLE:'. dc.b "*",0 openerrmsg: dc.b "Cannot open file.",10 openerrmsg_len equ *-openerrmsg Last edited by admiral; 21 May 2021 at 04:34. Reason: better description |
21 May 2021, 12:00 | #40 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,216
|
Quote:
A couple of minor comments: The buffer size should probably align with a (multiple) of the block size of the medium. This is of course not strictly necessary, but having a block size aligned may allow the file system to "burst" directly into your buffer instead of copying through a second level buffer. I would suggest 1024 bytes. Also, for a buffer that small you would not need to allocate memory, the stack would be sufficient. Last but not least, "*" is not deprecated. There is a small subtle difference between CONSOLE: and "*", and without knowing anything else, I would suggest to go for "*". "*" is the current console, "CONSOLE:" is the default console. It doesn't make a difference with CON: right now, but it may make a difference in the future to allow "job control". |
|
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 |
|
|