Jump to content
IGNORED

Illegal Storage Class Compile Error


OldAtAtari

Recommended Posts

Hi, everybody. I wonder if anyone has time to look at some code and tell me what I'm doing wrong. Ok, I'm sure I'm doing many things wrong, but the first compile error in the list is "Illegal Storage Class" in line 12 "extern unsigned char sprite[];". I've found that the Illegal Storage Class error goes away if I comment out the tgi_setpalette(pal) line, so I'm sure something's wrong with the way I've set up my palette.

 

I've taking my working treeJumper game, based on Karri's template, and I've pulled out almost all the code to get the simplest testcase possible. I want to have a custom palette with one sprite. I've been staring at this for hours. I just don't know what I'm doing wrong. Below is my code, Makefile, palette file, and the compile errors. If anyone is kind enough to advise me, I'd really appreciate it. Thank you.

My game.c file:

#include <lynx.h>
#include <conio.h>
#include <joystick.h>
#include <tgi.h>
#include <stdlib.h>

unsigned char checkInput(void);
extern unsigned char reset; 

tgi_setpalette(pal)

extern unsigned char sprite[];

static SCB_REHV_PAL Ssprite = {
    BPP_4 | TYPE_NORMAL,
    0x10, 0x20,
    0,
    sprite,
    0, 0,
    0x0100, 0x100,
    {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}
};

void draw_sprite (int x, int y)
    {
    Ssprite.vpos = y;
    Ssprite.hpos = x;
    Ssprite.vsize = 20;
    Ssprite.hsize = 20;
    tgi_sprite(&Ssprite);
    }

void game()
    {
    char x = 90; 
    char y = 50;
    
    while (!reset)
        {
        if (!tgi_busy())
            {
                draw_sprite(x, y);
                tgi_updatedisplay();
            }
        }
    }

 

My palette file pal.c:

/*
 * This file was generated by sp65 2.13.9 from
 * sprite.pcx (640x400, 16 colors, indexed)
 */
unsigned char pal[] = {
    0x0F,0x0F,0x00,0x0B,0x07,0x00,0x0C,0x08,0x0F,0x0C,0x0A,0x00,0x00,0x04,0x04,0x03,
    0x00,0xFF,0x00,0xBB,0x95,0xF0,0x11,0x01,0x0F,0x0F,0x0F,0x0F,0xFF,0x5B,0x07,0x04,
    };

 

My MakeFile:

include ../Common.mk

thisdir=game

objects= \
	game.o \
	sprite.o 

SEGMENTS= \
	--code-name GAME_CODE \
	--rodata-name GAME_RODATA \
	--data-name GAME_DATA \
	--bss-name GAME_BSS

all: objlist

objlist: $(objects)
	$(RM) objlist
	for obj in $(objects); do $(ECHO) ../$(thisdir)/$$obj >> objlist; done

sprite : sprite.pcx
	$(SP) -r $< -c lynx-sprite,mode=packed,ax=0,ay=0 -w $*.c,ident=$*,bytesperline=8

clean:
	$(RM) objlist $(temporaryobjects) $(objects)

My terminal window:

 

image.thumb.png.097642c8b134402dab8eae47a9084996.png

 

 

 

 

 

 

 

Edited by OldAtAtari
Link to comment
Share on other sites

@karri, when you showed me an example of specifying a custom palette in my "Journal" topic, you had a semicolon after the command

tgi_setpalette(pal)

But when I put a colon after it, I get an additional compile error and warning for that line "Error: Identifier expected. Warning: Implicit 'int' is an obsolete feature". But the Identifier it's talking about it "pal", right? My current guess is that my Makefile needs to have some way of converting pal.c to pal.o. Simply putting pal.o in the Objects list doesn't seem to do it. I bet I'm missing something important there.

 

image.thumb.png.ddec870b3428fc0995bbb9d7eea43f97.png

 

 

Link to comment
Share on other sites

10 minutes ago, karri said:

You need to declare this before using it.

 

extern unsigned char pal[];

 

Then you can use it.

Thanks, Karri.

 

Figures it would be a basic C problem.

 

I'm not sure where to declare it.

 

I've tried declaring it in the palette, and that didn't change my compile results

extern unsigned char pal[] = {
    0x0F,0x0F,0x00,0x0B,0x07,0x00,0x0C,0x08,0x0F,0x0C,0x0A,0x00,0x00,0x04,0x04,0x03,
    0x00,0xFF,0x00,0xBB,0x95,0xF0,0x11,0x01,0x0F,0x0F,0x0F,0x0F,0xFF,0x5B,0x07,0x04,
    };

And I've also tried declaring in in my main code, which also didn't change my compile results

unsigned char checkInput(void);
extern unsigned char reset; 

extern unsigned char pal[];

tgi_setpalette(pal);

extern unsigned char sprite[];

static SCB_REHV_PAL Ssprite = {
    BPP_4 | TYPE_NORMAL,

 

And, finally, I've tried it in both files at the same time, with no change in my compile results.

 

So I'm still doing something wrong. Probably I'm misunderstanding your advice. Thank you for your patience.

Link to comment
Share on other sites

Don't add the "extern" in the place where you declare the data. So take it away from the code that already compiled without errors (pal.c).

 

Declare your data before you use it. So add extern in the file that complains that it does not compile.

  • Like 2
Link to comment
Share on other sites

You seem to run in 'simple' C problems. Maybe pick up a C learning book as well? You cannot throw a function call somewhere in the code. It has to be inside a function.

 

I mean tgi_setpalette(pal); it is a function call in the middle of nowhere.

 

 

Edited by 42bs
  • Like 2
Link to comment
Share on other sites

5 hours ago, OldAtAtari said:

tgi_setpalette(pal)

Unless tgi_setpalette is defined with a #define (which replaces the usage with the text of the macro), C sees this as a K&R style function declaration.  If no type is specified, the function return type is assumed to be 'int'.  Modern C would like to forget that K&R ever existed, so now considers this to be obsolete and will cry a river if you use it.

 

K&R style for a function declaration goes:

 

[return type, defaults to int] function_name( [param1_name [,param2_name ...]])

param1_type param1_name;

param2_type param2_name;

{

  Function body;

}

 

(The [ and ] represent optional items, not actual syntax)

 

As you can see, as soon as it thinks you are trying to declare a K&R style function, your variable declarations had better be arg names.  So your code looks (to the compiler) like:

 

Declare function tgi_setpalette with arg named 'pal'.

Define arg of name extern unsigned char sprite[] .... but 'sprite' is not in the arg list!  Only 'pal' is!  Even worse, it was declared as extern.  Args are not externs!

As you can see, the compiler is not correctly interpreting what you mean to say, but rather it's following its rigid rule structures.

 

 

So, somebody mentioned that tgi_setpalette is a function call.  In that case, it needs to be within a function, such as main.  'main' is always the first function called when you run a program.

A couple side notes:  C2x (which I assume is a specification for the 2020's) has finally dropped K&R style completely.  YAY!  But even if there are compilers that comply with this standard already, most will default to earlier, more permissive specifications.

Note #2:  When you want to tell one .c module how to use resources in another .c module, place your declarations in your own .h file.  Then both modules can #include the .h file and know what is available, as well as what it looks like.

 

Note #3:  Many people declare a function with no args as such:  mytype myfunctionname( );   This is wrong, as it is interpreted in K&R style mentioned above, as a function with indeterminate args.  We don't know how many it takes or what type they must be, but we know the function exists!  The proper definition is:  mytype myfunctionname( void );   The 'void' with no additional text says that this is a function that definitely takes no args.

 

Edited by ChildOfCv
  • Like 1
Link to comment
Share on other sites

9 hours ago, karri said:

Don't add the "extern" in the place where you declare the data. So take it away from the code that already compiled without errors (pal.c).

 

Declare your data before you use it. So add extern in the file that complains that it does not compile.

karri, thanks for this. When I didn't see pal.o in my post-compile directory, I assumed that pal.c had not compiled. But now I think the reason it didn't compile isn't because it was mis-coded. It didn't compile because Make never got to that step, as it crashed in the compilation of game.c. Either way, your point is well-taken. Compile was complaining about game.c, so I had no good reason to add anything to pal.c, except for latenight desperation. So thank you again.

Edited by OldAtAtari
Link to comment
Share on other sites

12 hours ago, 42bs said:

You seem to run in 'simple' C problems. Maybe pick up a C learning book as well? You cannot throw a function call somewhere in the code. It has to be inside a function.

 

I mean tgi_setpalette(pal); it is a function call in the middle of nowhere.

 

 

You, 42bs, are always on point, keeping me honest. Thank you for speaking some truth to me. Yes, my excitement about the Lynx programming, and my initial success with my little practice game (success due to the help of you and others), caused me to forget my general lack of knowledge in the C fundamentals. I'm fairly experienced (in a hack kind of a way) in Perl, and I assumed that would help, but C turns out to not be as similar as I expected. So I need to regain the C skills I learned in college.

And the thing about tgi_setpalette(pal) being in the middle of nowhere? Yep. Turns out ya can't do that. I moved it down to my main game() routine, and the compile no longer complains about it. It complains about something else now (stack smashing when compiling the sprite - I haven't looked that up yet), but it doesn't complain about tgi_setpalette. Thank you for correcting me there.

Edited by OldAtAtari
Fixed a typo
Link to comment
Share on other sites

6 hours ago, Turbo Laser Lynx said:

Things like that happen late in the night (and at other times too), don't give up. :) :thumbsup:

Yes, late at night and other times too. ? You are correct. Turbo Laser Lynx, thank you for always pushing me to keep trying. 42bs pushes me to improve my skills, and you push me to not give up. The two of you are a good team, and I'm fortunate to have you both. And karri and everyone else here, you all are so smart and good at this stuff, and you're so generous with your time. Thank you so much. If I fail at this, it will be because I gave up, not because I didn't have people to help me out.

Link to comment
Share on other sites

4 hours ago, ChildOfCv said:

Unless tgi_setpalette is defined with a #define (which replaces the usage with the text of the macro), C sees this as a K&R style function declaration.  If no type is specified, the function return type is assumed to be 'int'.  Modern C would like to forget that K&R ever existed, so now considers this to be obsolete and will cry a river if you use it.

 

K&R style for a function declaration goes:

 

[return type, defaults to int] function_name( [param1_name [,param2_name ...]])

param1_type param1_name;

param2_type param2_name;

{

  Function body;

}

 

(The [ and ] represent optional items, not actual syntax)

 

As you can see, as soon as it thinks you are trying to declare a K&R style function, your variable declarations had better be arg names.  So your code looks (to the compiler) like:

 

Declare function tgi_setpalette with arg named 'pal'.

Define arg of name extern unsigned char sprite[] .... but 'sprite' is not in the arg list!  Only 'pal' is!  Even worse, it was declared as extern.  Args are not externs!

As you can see, the compiler is not correctly interpreting what you mean to say, but rather it's following its rigid rule structures.

 

 

So, somebody mentioned that tgi_setpalette is a function call.  In that case, it needs to be within a function, such as main.  'main' is always the first function called when you run a program.

A couple side notes:  C2x (which I assume is a specification for the 2020's) has finally dropped K&R style completely.  YAY!  But even if there are compilers that comply with this standard already, most will default to earlier, more permissive specifications.

Note #2:  When you want to tell one .c module how to use resources in another .c module, place your declarations in your own .h file.  Then both modules can #include the .h file and know what is available, as well as what it looks like.

 

Note #3:  Many people declare a function with no args as such:  mytype myfunctionname( );   This is wrong, as it is interpreted in K&R style mentioned above, as a function with indeterminate args.  We don't know how many it takes or what type they must be, but we know the function exists!  The proper definition is:  mytype myfunctionname( void );   The 'void' with no additional text says that this is a function that definitely takes no args.

 

Wow, ChildOfCV, thank you! There is a lot to unpack there. Some terms I don't understand. My C learning can start right here with your post. And your line

Quote

tgi_setpalette is a function call.  In that case, it needs to be within a function, such as main.  'main' is always the first function called when you run a program.

is dead-on. A C program seems to be little more than a collection of functions calling other functions. And the fact that the tgi_setpalette() function exists in an include file does not make it an exception. I think that's part of what threw me. Regardless of where it exists, it's still a function to be called from within another function. If I learn nothing else today, I've learned that, and that's a biggie. Thank you for reinforcing and expanding on the advice of 42bs. And thank you for all the other notes and information. I'll dig in sometime and pick it apart.

Link to comment
Share on other sites

? yepp,. coming from Perl, C is very restrictive. But I think you re-learned some of the basics the hard way.

When ever a C compiler throws misterious error messages, check the semicolons are all set.

Also I recommend to uses braces always. Even if C allows you to omit them for example after an if.

 

 if ( a )
    if ( b )
      doit();
  else
    doitalso();
Quote

 

Test: When will doitalso() be called?

Link to comment
Share on other sites

48 minutes ago, 42bs said:

? yepp,. coming from Perl, C is very restrictive. But I think you re-learned some of the basics the hard way.

When ever a C compiler throws misterious error messages, check the semicolons are all set.

Also I recommend to uses braces always. Even if C allows you to omit them for example after an if.

 


 if ( a )
    if ( b )
      doit();
  else
    doitalso();

Test: When will doitalso() be called?

Ha! A test! I love it! The lack of curly braces is throwing me, and the weird indentation of the else (doesn't line up with either if).

 

I wonder if it means

 

if ( a )
	{
	if ( b )
		{
		doit();
		}
	else
		{
		doitalso();
		}
	}

 

in which case doitalso() would be called if a is true and if b is false. If a is false, then b will never be tested, and the else won't matter. If a is true and b is true, then we'll call doit() instead of doitalso().

 

But my inclination is to believe that it really means the following, as I bet you would be forced to use curly braces if the intention was to have the else nested inside the first if statement. I believe that the lack of curly braces would cause the compiler to read the code this way, where the else is paired with the first "if", not the second "if":

 

if ( a )
	{
	if ( b )
		{
		doit();
		}
	}
else
	{
	doitalso();
	}

in which case doitalso() will be called if a is false. If a is true, then the else will never come into play. And that is my final answer.

 

Both of those answers might be incorrect. I think that the bigger point is that the style you used without the curly braces is completely foreign to me. I need to get comfortable with all the forms of C syntax so that I can make sense of code like this.

 

*** UPDATE ***

I'm changing my final answer. Without curly braces, I think the compiler must assume that the else is paired with the if that immediately comes before it. In this case, that would equate to the first scenario I described above, where doitalso() will be called if a is true and b is false. Final answer.

 

Edited by OldAtAtari
Updated my final answer.
Link to comment
Share on other sites

2 minutes ago, 42bs said:

Perfect, intention versus indention.

You got my point, the code does what you wrote on top. But w/o curly braces it is hard to read.

Therefore my company's style guide makes them mandatory.

Excellent. I'm glad it's hard for you to read as well. Thank you so much for the test. That was fun, and it's a reminder to me to make my code easily understandable for the next person.

Link to comment
Share on other sites

Just to finish off this topic, I'm compiling fully now.

I had two big problems causing this error:

1) I had not declared my pal variable. Thank you, karri for helping me with that.

2) My tgi_setpalette() command was in the wrong place. That function needs to be called from within another function, which in this case, is my main game() function. Thank you, 42bs for that.

 

I did have another problem where the pcx image wouldn't compile. It was talking about "stack smashing." I just regenerated my pcx file, and it worked fine.

And just in general, I need to brush up on my C skills. Thanks all of you for the encouragement to do that.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...