English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 07 March 2017, 17:00   #1
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Help please 1st c programme in decades, and it does not work....

Hi,

I used to write system software in C, many many years ago. I thought it would be interesting to see how much I had forgotten (most of it) by seeing if I could write a few simple Amiga progs.

With this in mind I got the ade archive from the aminet and set up gcc. Then I went looking for a noddy programme to compile to check all was OK.

I found this : https://github.com/cahirwpz/libnix/b...s/helloworld.c
Code:
#include   <dos/dos.h>
#include   <workbench/workbench.h>
#include   <inline/exec.h>
#include   <inline/dos.h>
         
int   __nocommandline=1; /* Disable commandline parsing */
int   __initlibraries=0; /* Disable auto-library-opening */
          
struct   DosLibrary *DOSBase=NULL;
extern   struct WBStartup *_WBenchMsg;
          
int   main(void)
{   if(_WBenchMsg==NULL)
    {   if((DOSBase=(struct DosLibrary  *)OpenLibrary("dos.library",33))!=NULL)
         {   Write(Output(),"Hello world\n",12);
               CloseLibrary((struct   Library *)DOSBase); } }
      return   0;
}


but it won't compile, giving test2.c:16 'SysBase' undeclared (first use in this function)

Given that SysBase is not used in the programme, I'm guessing it's a problem with one of the includes. Problem is I have no idea which.
Having never developed for an Amiga before I'm a bit stuck.


Im compilling with gcc -noixemul -lamiga -libnix test.c

Can someone point me in the right direction?

Thanks in advance.
chocsplease is offline  
Old 07 March 2017, 17:06   #2
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,190
OpenLibrary() is called from Exec.library which is pointed to by SysBase.
Samurai_Crow is offline  
Old 07 March 2017, 20:37   #3
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
if I add
Code:
struct ExecLibrary *SysBase;
right there with the DOSBase declaration the program compiles and runs with
Code:
m68k-amigaos-gcc -noixemul -o helloworld helloworld.c
alkis is offline  
Old 08 March 2017, 17:26   #4
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Hi

Many thanks for the replies, adding that declaration gets the prog to compile and it works. (though the executable is big for what it does...)

Problem is, I don't really understand how it works. There are bits that make sense, the includes, int __somethings, structs etc. But when we get to the actual library calls I get lost.

How, for example would I write a variable out using the Write(Output() call? say my variable was a long int with 2000000 in it?. Write looks like it needs a byte count (12 in the case of the prog I posted).

Also why does *SysBase use a different structure to *DosBase if they are using the same library?

I'm confused....

Is there a web page anywhere that can lead somone with c knowledge through programming for the Amiga?

Thanks in advance.
chocsplease is offline  
Old 08 March 2017, 18:53   #5
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,174
Quote:
Originally Posted by chocsplease View Post
Hi

Many thanks for the replies, adding that declaration gets the prog to compile and it works. (though the executable is big for what it does...)

Problem is, I don't really understand how it works. There are bits that make sense, the includes, int __somethings, structs etc. But when we get to the actual library calls I get lost.

How, for example would I write a variable out using the Write(Output() call? say my variable was a long int with 2000000 in it?. Write looks like it needs a byte count (12 in the case of the prog I posted).

Also why does *SysBase use a different structure to *DosBase if they are using the same library?

I'm confused....

Is there a web page anywhere that can lead somone with c knowledge through programming for the Amiga?

Thanks in advance.
SysBase (exec.library) and DosBase (dos.library) point to different libraries which is why the structures are different. See http://amigadev.elowar.com/read/ADCD...0D.html#line49 for details (there's more pages than the linked one).

To output something you'd do something like:
Code:
char message[] = "Hello world!\r\n";
Write(Output(), message, sizeof(message)-1); // -1 because we don't want to print the NUL char at the end of message
If you need to be compatible with old WB versions (I think <2.0) you can format the message buffer using RawDoFmt or your C compilers easier sprintf:
Code:
sprintf(buffer, "%ld", my_long);
Write(Output(), buffer, strlen(buffer));
But you can probably simply do "printf("%ld", my_long)".

Links:
Amiga OS 3.5 Developer docs

An amiga C tutorial - Note I only looked at a couple of the pages and they seemed reasonable, but I can't vouch for the rest.
paraj is offline  
Old 08 March 2017, 20:48   #6
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
The easiest would be to use standard ansi c libraries. So, a normal printf would do all you want. I'd stay with normal C until there is a very good reason to go amiga-specific.

If you do want to go amiga-specific you need to tell us your constraints. What the minimum OS version your program should be able to run? (1.2? 1.3? 2.0? 3.x etc) What's your design-goal? Minimum executable size? Speed?
alkis is offline  
Old 09 March 2017, 17:39   #7
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Hi,

Many thanks for the replies.

Initially I want to re-learn c and at the same time get a handle on how the Amiga uses its libraries. So my first goal is to get a programme to compile using Amiga calls if possible, rather than c quick fixes (even though they are very nice quick fixes!)

My next goal is to try and re-write the cli Info command so that it can handle large disks - my version of info is 38.2 and it says that the size of 2 of my partitions is negative (-638321k for one), neither is greater than 4gb.

Finally, if I haven't gone mad trying this, I'd like to see if it is possible to patch/change or somehow fix workbench so that its windows also display the correct disk size info.

As for base os etc, prob no earlier than 2.04 as there seem to be a lot of docs from around that time, and fewer for later versions.

Currently though I am being hit by the Guru, #8000004, when I run my simple prog, below, and I don't know why.
Code:
#include <dos/dos.h>
#include <workbench/workbench.h>
#include <inline/exec.h>
#include <inline/dos.h>

int __nocommandline=1; /* Disable commandline parsing  */

int __initlibraries=0; /* Disable auto-library-opening */

struct DosLibrary *DOSBase=NULL;
struct ExecLibrary *SysBase;

extern struct WBStartup *_WBenchMsg;

int main(void)
{
   char buff[100];
   unsigned long int big;

   big=1000000000;
   sprintf(buff,"hello world big number %ld",big);

/*   printf ("large number %d",big);*/

   if(_WBenchMsg==NULL)
   {
      if((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",33))!=NULL)
      {
         Write(Output(),buff,strlen(buff));
         CloseLibrary((struct Library *)DOSBase);
      }
   }
   return 0;
}
Ive tried including string.h and stdio.h, but get the same guru.

Any ideas where I am going wrong? compile line is
gcc -noixemul -lamiga -O2 test3.c
I also tried gcc -noixemul -lamiga -lm -O2 test3.c but still guru.
chocsplease is offline  
Old 09 March 2017, 19:14   #8
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
The reason it crashes is probably that you have disabled libraries autoinit and some code (either startup, or pulled from stdio) needs some library open.

In general, when you are in strict amiga-specific (you've disabled c-startup and/or libraries-init etc) you can't mix normal c libraries calls. If you have a full uncut C enviroment, you can mix amiga libraries calls.

Anyways, solution is to roll your own sprintf
Have a look here: http://amigadev.elowar.com/read/ADCD.../node036C.html

Near the end you'll find an example.

So, here is sprintf.s (for gcc assembler)
Code:
_LVORawDoFmt    = -522
            .globl _mysprintf
_mysprintf:   |( ostring, format, {values} )
            movem.l a2/a3/a6,-(sp)

            move.l  4*4(sp),a3       | Get the output string pointer
            move.l  5*4(sp),a0       | Get the FormatString pointer
            lea.l   6*4(sp),a1       | Get the pointer to the DataStream
            lea.l   stuffChar(pc),a2
            move.l  _AbsExecBase,a6
            jsr     _LVORawDoFmt(a6)

            movem.l (sp)+,a2/a3/a6
            rts

|    ;------ PutChProc function used by RawDoFmt -----------
stuffChar:
            move.b  d0,(a3)+        | Put data to output string
            rts
and helloworld.c

Code:
#include <dos/dos.h>
#include <workbench/workbench.h>
#include <inline/exec.h>
#include <inline/dos.h>


int __nocommandline=1; /* Disable commandline parsing  */

int __initlibraries=0; /* Disable auto-library-opening */

struct DosLibrary *DOSBase=NULL;
struct ExecLibrary *SysBase;

extern struct WBStartup *_WBenchMsg;

void mysprintf(char *, char *, ...);

int main(void)
{
   char buff[100];
   unsigned int big;

   big=1000000000;
   mysprintf(buff,"hello world big number %ld\n",big);



   if(_WBenchMsg==NULL)
   {
      if((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",33))!=NULL)
      {
        Write(Output(),buff,strlen(buff));
         CloseLibrary((struct Library *)DOSBase);
      }
   }
   return 0;
}
Compiling with
Code:
m68k-amigaos-gcc -Wall -noixemul -o helloworld helloworld.c sprintf.s
works as intented.

PS: Since you mentioned minimum target OS: 2.04, you could use Printf (note capital 'P') http://amigadev.elowar.com/read/ADCD.../node01CE.html If you go that way, pump the 33 in OpenLibrary to 36
alkis is offline  
Old 10 March 2017, 02:07   #9
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Quote:
Originally Posted by alkis View Post
The reason it crashes is probably that you have disabled libraries autoinit and some code (either startup, or pulled from stdio) needs some library open.

In general, when you are in strict amiga-specific (you've disabled c-startup and/or libraries-init etc) you can't mix normal c libraries calls. If you have a full uncut C enviroment, you can mix amiga libraries
Many thanks for the reply, Ill try the code when I get away from work.

Im not sure that I have disabled autoinit and c-startup as to be honest I dont know how to. Perhaps it needs enabling in my version of gcc?

Is there any way to check? Also how would I re-enable the full c environment if it is disabled? Is it through a compiler switch, or do I have to dive into an include?

Hope you can suggest a way forward.
chocsplease is offline  
Old 10 March 2017, 18:27   #10
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
What version of GCC are you using? If you're using Cahir's tool-chain from the link in your first post then the full C runtime, standard C library, and the Amiga NDK should always be available by default.

Just compile with
m68k-amigaos-gcc -noixemul -o hello hello.c
, and you shouldn't need all the extra stuff and declarations, just the call to Write().
Leffmann is offline  
Old 10 March 2017, 19:44   #11
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Quote:
Originally Posted by Leffmann View Post
What version of GCC are you using? If you're using Cahir's tool-chain from the link in your first post then the full C runtime, standard C library, and the Amiga NDK should always be available by default.

Just compile with
m68k-amigaos-gcc -noixemul -o hello hello.c
, and you shouldn't need all the extra stuff and declarations, just the call to Write().
Hi Im using the Ade archive from Aminet - http://aminet.net/package/dev/gcc/ADE

Which has gcc ver 2.95.3 in it so Im not sure if they are the same thing. Im developing on a real Amiga rather than uae or cross compiling. To be honest Im not sure if Ive set gcc up correctly yet due to the guru.
chocsplease is offline  
Old 10 March 2017, 22:40   #12
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Quote:
Originally Posted by chocsplease View Post
Im not sure that I have disabled autoinit and c-startup as to be honest I dont know how to. Perhaps it needs enabling in my version of gcc?
actually, I was refering to those
Code:
int __nocommandline=1; /* Disable commandline parsing  */

int __initlibraries=0; /* Disable auto-library-opening */
remove them and then you have a full c runtime enviroment.
alkis is offline  
Old 11 March 2017, 07:42   #13
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
This version, helloworld2.c
Code:
#include <dos/dos.h>
#include <workbench/workbench.h>
#include <clib/dos_protos.h>
#include <stdio.h>
#include <string.h>

extern struct WBStartup *_WBenchMsg;

int main(void)
{
  char buff[100];
  unsigned int big;

  big=1000000000;
  sprintf(buff,"hello world big number %ld\n",big);

  if(_WBenchMsg==NULL) {
    Write(Output(), buff, strlen(buff));
  }
  return 0;
}
compiled with
Code:
m68k-amigaos-gcc -Wall -noixemul -o helloworld2 helloworld2.c
seems to work fine.

Things to note:
  • no openlibrary calls
  • can mix stdio and amiga calls
  • executable size bigger (~8k)
  • needs OS >=2.0
  • include <clib/dos_protos.h> instead of <inline/dos.h>
  • gcc version used 3.4.0 (cross-compiled), I hope it works the same with gcc 2.95.3
alkis is offline  
Old 11 March 2017, 14:18   #14
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,345
Look for the SAS/C archive in the EAB forum, it is arguably simpler to use for simple Amiga programs.
idrougge is offline  
Old 12 March 2017, 11:31   #15
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Many thanks for the replies,

Quote:
Originally Posted by alkis View Post
actually, I was refering to those
Code:
int __nocommandline=1; /* Disable commandline parsing  */

int __initlibraries=0; /* Disable auto-library-opening */
remove them and then you have a full c runtime enviroment.
I had assumed that these two lines just did what the comments said, and did not turn the whole of the standard c environment off! Anyway commenting them out allows printf , sprintf etc to work withou guruing. Thanks for the help.


Quote:
Originally Posted by alkis View Post
《Snip》
Things to note:
  • no openlibrary calls
  • can mix stdio and amiga calls
  • executable size bigger (~8k)
  • needs OS >=2.0
  • include <clib/dos_protos.h> instead of <inline/dos.h>
  • gcc version used 3.4.0 (cross-compiled), I hope it works the same with gcc 2.95.3
When you say no open library calls, does that mean I cannot use them , they don't work, or they are not needed to output? Im still going to need open libraries to do things like run through the devices linked list.

Do you know the differencies between clib/dosprotos.h and inline/dos.h?

I have noticed the executable is big for such a simple prog, 22,980 bytes where as the original info command is only 1980, though I guessing that was written in assembler.

Quote:
Originally Posted by idrougge View Post
Look for the SAS/C archive in the EAB forum, it is arguably simpler to use for simple Amiga programs.
Can SAS/C handle 64 bit arithmatic? Im going to need long longs.

That said I cant find a way to get gcc to output long longs, long ints yes, long longs no. %ull just displays %ull while passing a long long to sprintf with a %u in it just gives 0, any ideas?

While I wont need to output long longs in the final app I will need to for debugging.

Anyway Ill download sas, but would like to tackle the gcc issues as well.

While on the subject of gcc does anyone know the structure that holds the linked list of device names? I thought it was SYSBase, but cant find it in the incudes
chocsplease is offline  
Old 12 March 2017, 12:57   #16
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Quote:
Originally Posted by chocsplease View Post
When you say no open library calls, does that mean I cannot use them , they don't work, or they are not needed to output? Im still going to need open libraries to do things like run through the devices linked list.
I mean the compiler takes care of opening and closing libraries for you. As you can see in my short sample, I didn't Open'd Dos Library, YET I am calling Write() and Output() etc.

Quote:
Originally Posted by chocsplease View Post
Do you know the differencies between clib/dosprotos.h and inline/dos.h?
Haven't actually checked. I'd assume clib results to stub functions that take arguments from stack (normal C function calling) load the necesary registers and make the actual system call. Inline skips the stub calling part, by having the load of registers inline in your code.

Quote:
Originally Posted by chocsplease View Post
I have noticed the executable is big for such a simple prog, 22,980 bytes where as the original info command is only 1980, though I guessing that was written in assembler.
First of all my executable is 9k
Then, info was written in C. But its very amiga-c. (No standard IO, no standard C startup, no automatic opening/closing libraries...You do EVERYTHING by yourself)

If you want to go that path. Get SAS/C, and look at examples in a folder 'no startup' or something similar for cat.c which implements the unix cat command. If I recall does so in 568 bytes of executable. Study cat.c. See how it is done.
Quote:
Originally Posted by chocsplease View Post
Can SAS/C handle 64 bit arithmatic? Im going to need long longs.
No

Quote:
Originally Posted by chocsplease View Post
That said I cant find a way to get gcc to output long longs, long ints yes, long longs no. %ull just displays %ull while passing a long long to sprintf with a %u in it just gives 0, any ideas?
try %llu


Quote:
Originally Posted by chocsplease View Post
While on the subject of gcc does anyone know the structure that holds the linked list of device names? I thought it was SYSBase, but cant find it in the incudes
Could be this.
SysBase->DeviceList

Actually, you need http://amigadev.elowar.com/read/ADCD.../node0187.html

Last edited by alkis; 12 March 2017 at 13:42. Reason: added LockDosList()
alkis is offline  
Old 12 March 2017, 19:55   #17
chocsplease
Registered User
 
Join Date: Dec 2016
Location: london
Posts: 178
Thanks for the reply,

Quote:
Originally Posted by alkis View Post
I mean the compiler takes care of opening and closing libraries for you. As you can see in my short sample, I didn't Open'd Dos Library, YET I am calling Write() and Output() etc.
Very useful - I missed that completely!

Quote:
Originally Posted by alkis View Post
Haven't actually checked. I'd assume clib results to stub functions that take arguments from stack (normal C function calling) load the necesary registers and make the actual system call. Inline skips the stub calling part, by having the load of registers inline in your code.
Hmm, think I'll have a play and see which I can work with the easiest I don't want to spend years on this.

Quote:
Originally Posted by alkis View Post
First of all my executable is 9k
Then, info was written in C. But its very amiga-c. (No standard IO, no standard C startup, no automatic opening/closing libraries...You do EVERYTHING by yourself)
Wonder if this is because you are using a newer version of gcc, they've stopped releasing it for the Amiga so I think I am stuck with the version I have or cross compiling -PC is in bits at present.

Quote:
Originally Posted by alkis View Post
If you want to go that path. Get SAS/C, and look at examples in a folder 'no startup' or something similar for cat.c which implements the unix cat command. If I recall does so in 568 bytes of executable. Study cat.c. See how it is done.
Sadly I can't use SAS as...
Quote:
Originally Posted by alkis View Post
No
It cant handle 64 bits..

Quote:
Originally Posted by alkis View Post
try %llu
Thanks for the suggestion, I've tried %llu on spritntf and the mysprintf asm you kindly posted a while back. sprint returns %llu, where as my sprint returns a number - but can't handle 64bits if I pass 32 hex fs to it it returns 16777215, which must be the result of overflows. The 68020 etc are 32 bit processors and from my 8 bit (yes I am that old) days I seem to remember that they had ways of combining registers to handle 16 bits. Do the 68020s etc have a similar feature? I don't really want to have to learn assembler just to output debug info, but would it be possible to change mysprintf to handle 64 bits?

Oddly if I have both sprint and mysprintf in the same code the mysprintf fails to return anything.

Incidentally what does the -Wall switch do in the compile string you posted with mysprintf?
Code:
m68k-amigaos-gcc -Wall -noixemul -o helloworld2 helloworld2.c
Quote:
Originally Posted by alkis View Post
Could be this.
SysBase->DeviceList

Actually, you need http://amigadev.elowar.com/read/ADCD.../node0187.html
Thanks I'll give this a go.
chocsplease is offline  
Old 12 March 2017, 23:42   #18
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Get SAS/C just for the cat.c source code. Invaluable for seeing what you need to do for coding "system" command line applications.

The fact that SAS/C doesn't support 64bits doesn't mean you can't add the support. (it will be ugly function calls instead of a*b you'll use mul64(a, b) )

Gcc at least 3.4.0 that I have does have 64 bit support and %llu works in printf and sprintf. mysprintf.s that I posted was from the autodocs, which uses RawDoFmt() i.e. system-call. RawDoFmt() does not support 64bits.

-Wall is a switch for gcc that enables all warnings. (helps you catch an extra error or two before actually running the program)


Also note, that the partial source code of AmigaOS is leaked. If you happened to find it on the internets, and you proceed to illegaly download it, then you'll might get a glimpse of info.c

If you proceed to make a few changes, it could compile with gcc.
Code:
m68k-amigaos-gcc -s -nostdlib -noixemul -Os -o foo mystartup.s info.c
Then you might end up with an executable
Code:
-rwxrwxr-x 1 alex alex  2120 Mar 12 20:29 foo
2120 bytes. Not bad.
alkis is offline  
Old 13 March 2017, 11:59   #19
demolition
Unregistered User
 
demolition's Avatar
 
Join Date: Sep 2012
Location: Copenhagen / DK
Age: 44
Posts: 4,190
Quote:
Originally Posted by alkis View Post
The fact that SAS/C doesn't support 64bits doesn't mean you can't add the support. (it will be ugly function calls instead of a*b you'll use mul64(a, b) )
Maybe I am damaged from mainly using C++, but can't you overload the + operator if you make your own 64 bit type?
demolition is offline  
Old 13 March 2017, 12:01   #20
attle
Registered User
 
Join Date: Aug 2012
Location: RAM:
Posts: 83
No operator overloading in C.
attle is offline  
 


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

Similar Threads
Thread Thread Starter Forum Replies Last Post
This Amiga game was lost for two decades, and now it's out on Steam Shoonay Retrogaming General Discussion 16 22 May 2019 12:07
English Amiga Board Joins Electronic Arts' Affiliate Programme CodyJarrett News 14 07 April 2015 12:56
Falling at the 1st.... well last Hockmiester support.WinUAE 2 26 March 2013 16:46
On the 1st day of January... Fissuras Retrogaming General Discussion 1 12 January 2003 06:42
1st Sensible Soccer Nico request.Old Rare Games 1 13 May 2002 15:37

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 19:04.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10612 seconds with 13 queries