Jump to content
IGNORED

Is 10 FPS a too low framerate for a LYNX tile based game?


Nop90

Recommended Posts

The header is there (or it won't compile) and tryed to add more space to the RAM segment (used the cart template and changed RAM from $3000 to $3800) with no luck.

 

But I think the problem is something else because I compiled the template code with no changes and there is the same problem, so looking in the code I found the clock() function in the intro. Commenting out the whole intro code, the demo works fine.

 

I think there is a problem with my compiler: I had to compile the CC65 from the code on your repository because my Ubuntu machine (64 bit) doesn't run the pre built tools.

Link to comment
Share on other sites

I think there is a problem with my compiler: I had to compile the CC65 from the code on your repository because my Ubuntu machine (64 bit) doesn't run the pre built tools.

 

32Bit or library issue? You can tell Linux to run also 32bit programs.

Link to comment
Share on other sites

I run cc65 on 64 bit Ubuntu 18.04. I fixed all 64-bit stuff on that compiler and tools long ago.

 

Perhaps it is time to put together a new template. I really don't know how old template you have in use.

 

In this template I have updated the Common.mk to also work on Android tablets as I prefer to carry a tablet instead of a laptop.

 

Could you please unzip this.

 

cd template

make

 

It should build using cc65 on a 64-bit os without any tricks.

 

The cc65 installation is done by:

 

git clone https://bitbucket.org/atarilynx/lynx.git

cd lynx/tools

make -f Makefile.deb

 

Edit: I also checked that the official cc65 can be used. It has a few corruptions in sp65 that cause extra stripes. They are fixed in my repo but I forgot to fix them in Olivers cc65. So for sp65 my repo is currently "better" for other aspects I believe Oliver's could be better.

template.zip

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

No luck. The new template builds, but like the other one it freezes on startup.

 

The toolchain was downloaded from your repository and built like you say.

 

If I can't find a workaround in the next days, I'll clean the toolchain and build it again. If nothing changes, I'll move it to a windows machine.

Link to comment
Share on other sites

Did you run this line before building cc65?

sudo apt-get install git checkinstall mednafen

Could you please remove the current cc65 package before installing the new one.

sudo dpkg -r cc65

Then just unzip cc65.zip and install my compiled version with

sudo dpkg install cc65_14.09-1_amd64.deb

You should be able to also compile and generate this deb file by the previous command.

cc65.zip

Edited by karri
Link to comment
Share on other sites

I found the reason for the clock() error. There is a bug in cc65 that I fixed in 2016-09-11. Obviously you have an older or stock version of cc65.

 

The old clock() routine had references to segments that are not allocated on the Lynx.

 

The working clock() routine is in my repo since 2016.

 

Here are the changes:

 

post-2099-0-22574700-1548091341_thumb.png

 

Link to comment
Share on other sites

Yes, I have the old clock.s file, but I downloaded the last version of cc65 from your site.

 

Maybe in my setup there is some garbage from a previouse setup not properly cleaned.

 

Thank you for finding the problem. I'll let you know if a fresh install will solve the issue.

Link to comment
Share on other sites

I found the reason for the clock() error. There is a bug in cc65 that I fixed in 2016-09-11. Obviously you have an older or stock version of cc65.

 

The old clock() routine had references to segments that are not allocated on the Lynx.

 

The working clock() routine is in my repo since 2016.

 

Here are the changes:

 

attachicon.gifScreenshot from 2019-01-21 19-21-35.png

 

 

 

Have you thought of submitting this fix to the CC65 repo since most people building it from source would end up with this problem?

Link to comment
Share on other sites

I searched, but couldn't see any pull requests or issues that were raised that had to do with clock.s for the Lynx. You're right about releases being far and few between though, but there are code updates and merges happening regularly to the master branch. Is it worthwhile going through both repositories and seeing what changes have been made and submitting anything that's still missing? Or is it better to tell everyone to just use the version from your repository?

 

Nop90 sorry to highjack this - as someone who is also starting to use cc65 on the Lynx, I think it's important to have all the fixes in one place.

Link to comment
Share on other sites

My interest is to have a stable compiler as it is only a tool for making games. After Uz stopped maintaining cc65 it became unstable and I did not have the same possibilities to influence where cc65 was heading. My choice was to freeze the last good version made by Uz and continue development outside the compiler. That is why there is a separate directory lynx/contrib. Instead of making a branch of the compiler I decided to develop abcmusic and other libraries outside the cc65 environment as separate non-portable Lynx libraries.

 

The real cc65 did not like my use of the TGI library. So my version is not compatible with the new TGI library specification.

 

I am helping Oliver to keep the Lynx port working in the main cc65 release also. But the compiled code looks different in these two versions. My code is frozen at the 2014 level and I do not intend to develop it at all. Just fix bugs.

 

The advantage of a frozen compiler is that if I need to re-compile something years later I get the exactly same rom. Bit by bit. So it is a deterministic tool for me.

 

Please feel free to choose the compiler that makes you happy.

  • Like 2
Link to comment
Share on other sites

Little update: linking the sprites and removing animations the game reached more than 30 FPS. Now it is playable, but I have to adjust the speed and remove some glitches.

 

I got more exprienced with Chipper and adapted the original mod tracks. A couple of them are very nice and are fine for the prototype, but already asked help to someone more expert for a professional work.

 

The same for the graphics.

 

Now it's time to work on the sfx: I'm going to use chipper to make some effects (starting from some examples I found in the forum), but it's not so easy.

  • Like 4
Link to comment
Share on other sites

Optimized everything I could in the gfx code and now the FPS is 48-50.

 

I'm satisfied of this speed.

 

Today karri tested the alpha version on a real Lynx and the game seems to work fine (thanks again karri).

 

there is only a strange issue with the timer.

 

Every level has an amount of seconds to complete it, and there is a timer decreasing every second.

 

karri reports that if in a level you don't move, after little time the timer starts to decrease faster. This doesn't happen on emulators.

 

 

I use this code for the timer:

 

unsigned long int tick1, tick2;
tick1 = tick2 = clock()/CLOCKS_PER_SEC;;

...

 

/* count the time to zero */
tick1 = clock()/CLOCKS_PER_SEC;
fcount++;
if(tick1 != tick2)
{
gametime -= 1;
tick2 = tick1;
fps =fcount;
fcount=0;
}

 

 

Any hint on why this happens?

Edited by Nop90
Link to comment
Share on other sites

The clock runs in burstes both on Lynx I and Lynx II. Not all the time, but once every 3-4 seconds you get a fast burst of a few seconds that get dropped. Really weird. The clock should be connected to TIMER2_INTERRUPT's.

 

The first question: is there some uninitialized variables related to the time handling? Mednafen works correctly but all variables are initialized to zero at startup. I am mainly interested in BSS variables.

Edited by karri
Link to comment
Share on other sites

I believe I have some idea of what is going on.

 

CLOCKS_PER_SEC is not a constant. It is tied to the routine __clk_tck which is a function that reads the BACKUP register from TIMER2 and tries to find out the VBL frequency. My guess is that there may be times when the BACKUP value cannot be correctly read due to some hardware related things.

 

Could you read the value once at startup and just use that constant as a divisor instead of using CLOCKS_PER_SEC?

Edited by karri
Link to comment
Share on other sites

Could you read the value once at startup and just use that constant as a divisor instead of using CLOCKS_PER_SEC?

 

yes, I can do it. Or simply i can consider the framerate constant (e.g. 49 FPS) and decrease the counter every 49 frames.

 

I'll make some experiments and send you a new build soon.

Link to comment
Share on other sites

I would not go for 75Hz, 60Hz is fine.

Also a (constant) frame rate of 49 is not possible unless you have triple buffering.

I'd suggest 60Hz, because you can have a constant (fixed) frame rate of 30.

 

If you add a little counter in the VBL interrupt, you have an exact time. No divide needed ...

Link to comment
Share on other sites

Please educate me why 75 is bad? If I make a game where I cannot keep up with the hardware framerate and catch every frame so how long do I need to wait for the next opportunity to swap buffers. 1/75 , 1/60 or 1/50 of a second? Imho the 1/75 is the shortest time.

Edited by karri
Link to comment
Share on other sites

Sorry I did not explaned clearly.

 

With tgi_setframerate you set the phisical framerate, that is the LCD refresh rate. I know of the possible values for tgi_setframerate, and since I didn't change it, I expect it is 75Hz.

 

I was talking about the number of buffer swap i can perform in a second, that depends on the time the code can do a game loop. 49 FPS is the average value of tgi_updatedisplay() that I can do in 1 second after a lot of code optimizations.

Link to comment
Share on other sites

The timekeeping is based on the number of VBL interrupts per second. So the CLOCKS_PER_SEC divisor is a constant that should match the VBL timer's programming. But there may be some real-life things that affect reading the timer register at such a high rate on a real Lynx. At least that could be one explanation of why the results are not steady.

 

You could also skip the division and just compare the clock() to the previous value.

now = clock();

....


while (clock() != now) {
    // Interrupt has occurred
    now++;
    if (now - lastsecond == 75) {
        lastsecond = now;
        fps = frames;
        frames = 0;
    }
}
  • Like 1
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...