Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - devkitSMS - develop your homebrew in C

Reply to topic Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
Author Message
  • Joined: 12 Oct 2015
  • Posts: 42
  • Location: Ireland
Reply with quote
Post Posted: Thu Mar 31, 2016 3:15 pm
sverx wrote
It doesn't happen with my SDCC version, are you using a recent snapshot or and (old) official release? (BTW you can probably just ignore the warning...)


I'm on Windows 7 64-bit so I downloaded + installed snapshot sdcc-20160331-9531-x64-setup.exe so this is version 3.5.5 as recommended... I know it's just a warning and can be ignored but just a bit annoying + can clutter up the command prompt
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Thu Mar 31, 2016 3:24 pm
SteveProXNA wrote
I'm on Windows 7 64-bit so I downloaded + installed snapshot sdcc-20160331-9531-x64-setup.exe


This might be the problem. I'm using the 32bit version instead (and I always skip any build which fails regression tests...).
Anyway you can try isolating the problem into a small C file and send it to me, so that I can double check that, test it on the 32bit version and eventually file a bug on SDCC sourceforge website. Unfortunately I just can't fix that myself :|
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Thu Mar 31, 2016 3:45 pm
quick workaround: you can modify the
SMS_EMBED_SDSC_HEADER

macro replacing the '&0xFF' with '%256' and the warning should disappear.

Weird, anyway.
  View user's profile Send private message Visit poster's website
  • Joined: 12 Oct 2015
  • Posts: 42
  • Location: Ireland
Reply with quote
Post Posted: Thu Mar 31, 2016 4:04 pm
sverx wrote
quick workaround: you can modify the
SMS_EMBED_SDSC_HEADER

macro replacing the '&0xFF' with '%256' and the warning should disappear.


Awesome! That works... warnings gone after replacing the '&0xFF' in the macro with '%256'... thanks!
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Fri Apr 01, 2016 11:01 am
Pushing this small update. Thanks for letting me know about the warning :)
  View user's profile Send private message Visit poster's website
  • Joined: 12 Oct 2015
  • Posts: 42
  • Location: Ireland
Reply with quote
Post Posted: Sat Apr 02, 2016 10:51 am
sverx wrote
Pushing this small update. Thanks for letting me know about the warning :)


Awesome! No problem...
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Sat Apr 02, 2016 7:57 pm
Hi, I'm not good at C++ programming I'm not programming anything 10 years ago (I changed career) and I'm not familiar with this stuff, so I asking for help, so how could I add the compiler to Devcpp or DevC++ (free compiler version ) or whatever its name is, the compiler is SDCC btw.

I can't find a directory option for compilers or something related, or maybe another C++ editor could be suggested, thanks in advance .
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Sun Apr 03, 2016 5:15 pm
This isn't C++. AFAIK, there's no C++ compiler for the Z80 (but I might be very wrong!)
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Sun Apr 03, 2016 8:03 pm
Could you suggest me an c IDE? Is that what I need besides SDCC and devkitSMS? I'm totally lost...
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 308
  • Location: Spain
Reply with quote
Post Posted: Sun Apr 03, 2016 8:25 pm
i don't usually use a full fledged ide, only a good editor (Sublime text, Atom, etc), a bat file, and that's all.

But, if you want a very godd C and C++ IDE, Clion is the choice (from JetBrains). But is not free...
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Mon Apr 04, 2016 7:57 am
FeRcHuLeS wrote
Could you suggest me an c IDE?


I'm currently using ConTEXT, and I set up it as explained here on Maxim's Tutorial.
You can also check my devkitSMS tutorial topic, there's a post explaining how I set up my function keys to compile / run MEKA / run Emulicious.
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11824
  • Location: London
Reply with quote
Post Posted: Mon Apr 04, 2016 8:39 am
Notepad++ or even whatever the free version of Visual Studio is called now would probably be more helpful (autocomplete, parameter info).

I wonder how useful (and hard) it would be to make it possible to compile a native program against the same API, to enable native debugging? That's where a real IDE would become most useful. I'm assuming debugging into an emulator would be crazy hard.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Mon Apr 04, 2016 11:48 am
Yeah, probably there are a lot of tools better than what I'm using, but I really never cared spending time on that. Maybe some fellow devkitSMS user that's using a different IDE could teach us how to switch! :)
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Mon Apr 11, 2016 9:00 pm
Finally.... I was able to compile the devkiSMS tutorial, It was very hard for me btw, I followed Maxim's tutorial:

Quote
Then open ConTEXT and click on Options, Environment Options, Execute Keys. Click Add and enter “asm” in the box. Then click on F9 in the list. Enter the path to compile.bat in the “Execute” box, “%p” in the “Start in” box, “%n” in the “Parameters” box, “*:%n:%l: *” (asterisk, colon, percent, lowercase N, colon, percent, lowercase L, colon, space, asterisk) in the “Compiler output parser rule” box, and check the “Capture console output” and “Scroll console output to the last line” checkboxes


Im not sure if this is the right way to configure it, the differences are that I used "c" instead of "asm" and created a build.bat, and used instead of compile.bat So my point is you have to create a step by step friendly tutorial for dummies like me, I have to say I was about to give up only for not knowing how to work devkitSMS, thanks and please update your tutorial in order not to keep away unexperienced people like me.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Tue Apr 12, 2016 7:53 am
I'm happy you did it, and of course it's harder for inexperienced people... if you feel some steps of my tutorial weren't clear enough, please let me know exactly which and I'll try to fix them.
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Mon Apr 18, 2016 8:07 pm
Hello, I made an exercise to show sprites in frames like a gif image does by its own, the issues I had are the third sprite frame shows mixed sprites, and the frames go too fast, I don't know how could add a time contidition to show smooth update of the frames, so please help me I understand what is needed to add but I dont know how to code it.

PD: I had to edit the sprites in order there are no blank sprites with random lines, I'm attaching the exercise assets and the main.c.
sprite_framer.rar (1.98 KB)

  View user's profile Send private message
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Tue Apr 19, 2016 6:20 am
FeRcHuLeS wrote
Hello, I made an exercise to show sprites in frames like a gif image does by its own, the issues I had are the third sprite frame shows mixed sprites, and the frames go too fast, I don't know how could add a time contidition to show smooth update of the frames, so please help me I understand what is needed to add but I dont know how to code it.

PD: I had to edit the sprites in order there are no blank sprites with random lines, I'm attaching the exercise assets and the main.c.


About the timing, they key is changing the displayed cell every N frames, not every frame.

Decide how many frames (N) between cell changes, and use a counter. Increase such counter each frame. When the counter equals N, reset the counter and change the animation cell.

The bigger N is, the slower the animation happens.
  View user's profile Send private message
  • Joined: 04 Jul 2010
  • Posts: 198
  • Location: Angers, France
Reply with quote
Post Posted: Tue Apr 19, 2016 7:22 am
Like na_th_an said, use a counter to achieve what you want.

create a variable outside the main() : it will be declared in ram
far more easy to handle/access.

use a #define for your counter value in top of your code , it will be easier to change/make some tests.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Tue Apr 19, 2016 8:13 am
The basic concept is that the screen is refreshed (redrawn!) 60 times per second, 50 times if you've got a PAL console and TV. Thus, if you want your animation to "slow down", you'll have to add frames where you display the same contents, which is simply done by doing no changes at all and wait for the next frame.

Also, I suggest you don't duplicate your code unless there's really no other option. I mean, if you've got three functions that do the same stuff and just differ from some start value, you can make that value a parameter:

void frame_funct (unsigned char tile) {
// your code here
}

void main (void) {
  // ...
  frame_funct (0);
  // ...
  frame_funct (30);
  // ...
  frame_funct (60);
  // ...
}


(I hope the example is clear...)
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Wed Apr 20, 2016 2:00 pm
Thank you all @na_th_an, @ichigobankai, @sverx now It works I created a variable N the counter like this:


unsigned int N;
void main (void) {
  SMS_setSpriteMode (SPRITEMODE_TALL);
  loadAssets();
  SMS_displayOn();
  for (;;) {
    while (N<30){

        SMS_initSprites();
        drawFrame_1();
        SMS_finalizeSprites();
        SMS_waitForVBlank();
        SMS_copySpritestoSAT();
        N++;
    }
    N=0;
    while (N<30){
        SMS_initSprites();
        drawFrame_2();
        SMS_finalizeSprites();
        SMS_waitForVBlank();
        SMS_copySpritestoSAT();
        N++;
    }
    N=0;
    while (N<30){
        SMS_initSprites();
        drawFrame_3();
        SMS_finalizeSprites();
        SMS_waitForVBlank();
        SMS_copySpritestoSAT();
        N++;
    }
    N=0;
  }
}


But why the last frame has the tiles mixed? Have I reached the limit of sprites? and could anyone teach me how to save an image so that there are no blank tiles for 8x16 tiles? This is the image I'm using btw

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Wed Apr 20, 2016 2:06 pm
You probably converted the image with the "remove duplicates" check box activated. Try converting it again without duplicates removal.
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Wed Apr 20, 2016 3:57 pm
sverx wrote
You probably converted the image with the "remove duplicates" check box activated. Try converting it again without duplicates removal.


It was that, All my problems are solved now, thank you :)
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 308
  • Location: Spain
Reply with quote
Post Posted: Thu Apr 21, 2016 8:35 am
Waiting to see your work, FeRcHuLes!! :-D
  View user's profile Send private message
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Sat Apr 23, 2016 2:13 pm
kusfo wrote
Waiting to see your work, FeRcHuLes!! :-D


Let's see what comes from this homebrew, thanks kusfo!!.
  View user's profile Send private message
  • Joined: 04 May 2016
  • Posts: 5
Reply with quote
Post Posted: Wed May 04, 2016 7:22 am
sverx wrote
This isn't C++. AFAIK, there's no C++ compiler for the Z80 (but I might be very wrong!)


I think the problem would be that the C++ would have to be very simple for it to perform on a Z80 processor. Perhaps even so simple that you might as well right 'regular' C.

Is anyone here using Z88DK? I haven't really seen that pop up much. But the lib even has SMS examples in the standard download.
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11824
  • Location: London
Reply with quote
Post Posted: Wed May 04, 2016 9:30 am
I think haroldoop did the work on z88dk but it's apparently a much worse C compiler and the framework is not as mature.

C++ vs C shouldn't be as much of a deal as people seem to think, but it would be up to the developer to avoid things that would work badly, like virtual functions and STL. Raw C is kind of hard work compared to C-like C++.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Thu May 05, 2016 10:06 am
Before even thinking about developing a devkit, I read some docs about how SDCC 'outperformed' z88dk. Also, when I started reading SDCC docs I had the impression I would obtain transparent ROM paging using that. Unfortunately that's true but still very embryonic, so I choose not to use it.
  View user's profile Send private message Visit poster's website
  • Joined: 04 May 2016
  • Posts: 5
Reply with quote
Post Posted: Fri May 06, 2016 7:49 am
sverx wrote
Before even thinking about developing a devkit, I read some docs about how SDCC 'outperformed' z88dk. Also, when I started reading SDCC docs I had the impression I would obtain transparent ROM paging using that. Unfortunately that's true but still very embryonic, so I choose not to use it.


Ok. Sorry bout that, should've done my research. I'm very new to sms dev anyways. Got into it through NES homebrew.

I'll give the devkit a go later today!
  View user's profile Send private message Visit poster's website
  • Joined: 04 May 2016
  • Posts: 5
Reply with quote
Post Posted: Fri May 06, 2016 8:52 am
sverx wrote
Before even thinking about developing a devkit, I read some docs about how SDCC 'outperformed' z88dk. Also, when I started reading SDCC docs I had the impression I would obtain transparent ROM paging using that. Unfortunately that's true but still very embryonic, so I choose not to use it.


Ok.. I did some digging around the interwebs..
The difference in speed is astounding. Is there a similar speed difference with your SMSLib and zd88k?

I can't post the link because I'm a recent member apparently. Anyways it was on CPCmania dot com.
And it featured a whole lot of comparisons. Like the one I copied below.


     SDCC v3.1.0    z88dk v1.9    z88dk 2012-05-19    SDCC v3.2.0    z88dk v1.10    SDCC v3.3.0
Size    1546 bytes    2091 bytes    2050 bytes        1497 bytes    2178 bytes    1427 bytes
Speed    320 ms       1960 ms        2120 ms       260 ms          2100ms           300 ms
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Fri May 06, 2016 9:16 am
fritzvd wrote
The difference in speed is astounding. Is there a similar speed difference with your SMSLib and zd88k?


Honestly, I don't know, as I don't know z88dk lib.
Generally speaking, SMSlib aims to be as fast as possible, whilst keeping your code completely interrupt safe, and VRAM safe too, except for the few (clearly marked so) UNSAFE functions, so that it would run on the hardware with no problems whatsoever.
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11824
  • Location: London
Reply with quote
Post Posted: Fri May 06, 2016 11:10 am
Here's the link, which is a few years old now: http://www.cpcmania.com/Docs/Programming/SDCC_vs_z88dk_Comparing_size_and_speed....

I think sdcc tries to use registers for function calls but z88dk is stack oriented. It also has a weaker optimiser. So you end up with hundreds of clock cycles for every function call, and lots of use of the index registers to access the function parameters.

There are also some adaptations of gcc and llvm for the Z80, but they seem to focus on correctness rather than speed...

https://olduino.wordpress.com/2014/12/30/llvm-for-the-z80-another-source-of-insp...

short int foo(short int a, short int b) {
    return a + b;
}
becomes
foo:
    push    ix
    push    bc
    ld  ix, 0
    add ix, sp
    ld  sp, ix
    ld  b, h
    ld  c, l
    ld  l, (ix+6)
    ld  h, (ix+7)
    add hl, bc
    pop bc
    pop ix
    ret

...which is pretty scary.
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Fri May 06, 2016 11:25 am
If you know z88dk enough (I do, been using it for more than 10 years) you can "pre-optimize" with its code generator in mind, and get better results (for long programs) than those shown in the cpcmania site.

That is not a feature, more a workaround, of course.

SDCC has a better optimizer, but it is painfully slow. It takes like 3-4 minutes in something I'm developing, in the same machine where a simmilarly sized project for the NES using cc65 takes 5 seconds or z88dk produces a complete ZX Spectrum binary in 2.

Of course, this is a minor disadvantage as you are creating a game which is meant to be played and what matters most is that the game plays fast, not that it compiles fast. But many of the shortcommings generally attributed to z88dk can be worked around if you know what you are doing.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Fri May 06, 2016 11:41 am
SDCC calls are stack based, but there's the
__z88dk_fastcall

which will make your (single parameter) function use fastcall conventions, which avoid stack pushing for function call. Of course it took inspiration from (and is compatible with) z88dk, hence the name :)

SMSlib for instance uses it (under the hood) for both:
SMS_setNextTileatXY(x,y)  /* macro */
SMS_setTile (unsigned int tile)


thus generating quite plain and fast code.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Sat May 07, 2016 3:31 pm
na_th_an wrote
If you know z88dk enough (I do, been using it for more than 10 years) you can "pre-optimize" with its code generator in mind, and get better results (for long programs) than those shown in the cpcmania site.


The same applies also to SDCC, after 1+ year that I'm using it, I'm finally starting to learn how to make it create the code I expect. Well, most of times, at least ;)
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Sun May 08, 2016 8:34 pm
And that's the beautiful part of it, ain't it? :D Same applies to cc65, it has its own nice little quirks as well.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Mon May 09, 2016 11:09 am
na_th_an wrote
And that's the beautiful part of it, ain't it? :D


Not so sure. Honestly I would want small and fast code from the very beginning but I understand one can't have everything. Explicit type casting usually is needed to make it generate better code...
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Wed May 18, 2016 3:07 pm
Hi I finally figure out how the ball moves in the tutorial thread, the equation to describe the movement is a line the origin coordinates are (BallX, BallY), the thing is how could I make the speed to be slower than 1 and how to add another paths suchs as a circle, ellipse, parabola, sine wave to begin with?? I think some another libraries are needed which of them would be suitable?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Wed May 18, 2016 3:27 pm
If you want to make the ball move at a different speed, and you want that "speed" not be an integer number you should use fixed point arithmetic.
For instance, you could express the speed using 8 bits for the integer part and 8 bits for the fractional part... this is often called 8.8 fixed point.
But in fact it's simply a 16 bit integer, and if your X and Y are expressed as 8.8 fixed point vars too, you just add/subtract the 'speed' value to/from them to move the ball. To draw the ball, then, you'll take only the upper byte.

From MARKanoIIId code - two vars from the ball position:
unsigned int BallX,BallY;             // 8.8 fixed point values

the code that moves the ball to North East
BallX+=BALL_SPEED_NORM;
BallY-=BALL_SPEED_NORM;

... BALL_SPEED_NORM is a 8.8 constant (value is 1.25 which is 5/4) defined as follows:
#define BALL_SPEED_NORM    (unsigned int)((5<<8)/4)

and to draw the ball I do
SMS_addSprite((BallX>>8)-(BALLW/2), (BallY>>8)-(BALLH/2), BALL_SPRITE_TILE);

BALLW and BALLH are the constant sizes of the ball in pixels, as the variables keep track of the center of the ball but the sprite is positioned by its upper left corner, so we have need a translation (geometry).

See how I turn the 8.8 values into an integer value?
somevar >> 8

that's the key. Also, an integer can turn into a 8.8 fixed point by
somevar << 8

... which is the same that you get multiplying by 256, FYI.
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Thu May 19, 2016 3:42 pm
Thanks for the information, the thing is I don't know how to work the conditionals now This is some of the code:

Xspeed, Yspeed

#define    BALL_SPEED_NORM_X    (unsigned int)((1<<8)/32)
#define    BALL_SPEED_NORM_Y    (unsigned int)((1<<8)/4)


Cases: SE, SW, STOP

case DIR_SE:BallX+=BALL_SPEED_NORM_X; BallY+=BALL_SPEED_NORM_Y; break;
case DIR_SW:BallX-=BALL_SPEED_NORM_X; BallY+=BALL_SPEED_NORM_Y; break;
case STOP: BallX-=BALL_SPEED_NORM_X-BALL_SPEED_NORM_X; BallY-=BALL_SPEED_NORM_Y-BALL_SPEED_NORM_Y; break;


Walls:

#define    LEFT_WALL        (unsigned int)(15>>8)
#define    RIGHT_WALL       (unsigned int)((256-4)>>8)
#define    BOTTOM_WALL      (unsigned int)((192-8)>>8)


The conditionals dont't work neither the original position no matter the value I replace to (BallX, BallY) The ball always depart from the top right corner

Ball original position:

 BallX=100;
 BallY=50;


Sorry for not being familiar with this stuff I tried using the ">> and <<" no success.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Thu May 19, 2016 7:29 pm
OK, let's change approach.
Let's define everything which is 8.8 fixed in some simpler way: a real number multiplied by 256 and stored into an integer:

#define    BALL_SPEED_NORM_X    (unsigned int)(1.25*256)
#define    BALL_SPEED_NORM_Y    (unsigned int)(1.70*256)


in this example we're setting BALL_SPEED_NORM_X at 1.25 and BALL_SPEED_NORM_Y at 1.70.

If you want the ball start at X=100,Y=50 you've got to do:
BallX=100*256;
BallY=50*256;


as we're using 8.8 fixed.

Finally, if you're not going to change any value if case 'STOP' you simply do:
case STOP:break;


As to the walls, I wouldn't use 8.8 fixed for them... keep them regular integer and if you want to compare your ball position with the walls, you turn your position back to its integer value to compare:
if ((BallX/256)>RIGHT_WALL) ...


I hope this makes sense to you. I really can't explain better than this, sorry :|

edit: this one seems a good article on fixed point arithmetic
  View user's profile Send private message Visit poster's website
  • Joined: 22 Mar 2015
  • Posts: 123
Reply with quote
Post Posted: Sat May 21, 2016 4:11 am
Thank you very much @sverx for all the information you provided me, I have to say I was thinking fixed point and float point were the same and I never was good at programming aswell, thanks for the link I haven't finished reading it yet. I believe the lessons you've just taught me are the good enough to be linked in the tutorial thread. :)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Mon Jun 27, 2016 1:45 pm
devkitSMS/SMSlib has been just updated.

This is the last update for a while... well, unless a really nasty bug comes out... which I hope not!

The most important change is that common code has been moved to crt0 so that it will be accessed via reset vectors. In short, this means 1 byte of code and 11 CPU cycles for each call instead of 3 bytes of code and 17 CPU cycles, but that's not the only reason, as also the library itself should be now faster and smaller.
Note that to make this new 'feature' work correctly and at its full, you need to update both crt0_sms.rel and the peephole rule file, and you should compile your sources specifying that the optimizer should use the additional rules in the file. For instance you could do:
sdcc -c -mz80 --peep-file ..\SMSlib\peep-rules.txt your_program.c


Please let me know if something isn't clear or if something doesn't work as expected.
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Tue Jun 28, 2016 9:11 am
I'll try and adapt my current project and tell you what happens.

In the meantime, I was wondering which method you can use in the SMS to measure how much frame time is consumed and how long you are waiting for VBlank (i.e. how much frame time is left).

In the NES, you can activate a flag in the PPU Control register which immediately modifies the video output and makes it B&W. Activating this at the beginning of your loop and deactivating it just before waiting for VBlank makes a portion of the TV picture to be in B&W and that way you can measure how much of the frame time is spent in calculations. The colour part of the image is how much time is left. It's a quite handy way to measure this.

Is there any way to do something simmilar in the Master System? Palette changes are performed at once, or just once per frame? I know I could try, but I'm away from the dev computer for a while and I was just wondering.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Tue Jun 28, 2016 9:24 am
Well, you could update a color you use in your background, if you like that (yes, can be changed mid-frame).
I personally prefer having two small sprites (they look like dashes) on the right edge of the screen, they mark my current and maximum scanline reached.

Here's the code I use:

#ifdef DEBUG
      // DEBUG: CPU meter
      CPUtemp=SMS_getVCount();
      SMS_addSprite(248,CPUtemp,CPU_METER_TILE);
      if ((CPUtemp<=192) && (CPUtemp>CPUmax))
        CPUmax=CPUtemp;
      SMS_addSprite(248,CPUmax,CPU_METER_TILE);
      // DEBUG: CPU meter end
#endif


of course you need two unsigned chars:
#ifdef DEBUG
unsigned char CPUtemp,CPUmax=0;    // DEBUG CPU meter
#endif


and a small sprite loaded somewhere in your VRAM (but you can reuse something already there if you're short of VRAM).
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Tue Jun 28, 2016 11:16 am
Changing the palette seems to work, thanks :)

It strikes me how the very same code (bar the library calls) takes way less frame time in the NES (cc65 + neslib) than in SMS (sdcc + smslib). One is inclined to believe that the Z80 is much stronger than the 6502. Maybe cc65 is a better compiler, or my code is better suited for its architecture. The NES sprite DMA may also count (the 256 bytes "SAT" (OAM in the NES) is copied to VRAM via DMA).

I'm porting a game I recently finished for the NES and I'm really struggling in not missing the VBlank. I'm getting frame drops in NTSC at the moment.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Tue Jun 28, 2016 11:47 am
Way less? Some figures to compare?

Are you updating SAT (and VRAM tiles) during vblank only?
If so, use
void UNSAFE_SMS_copySpritestoSAT (void);

for the SAT and
UNSAFE_SMS_load1Tile(src,theTile)           /* copy ONE tile to VRAM */
UNSAFE_SMS_load2Tiles(src,tilefrom)         /* copy TWO tiles to VRAM */
UNSAFE_SMS_load4Tiles(src,tilefrom)         /* copy FOUR tiles to VRAM */

for the tiles, this will maximise the VRAM access times.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1917
Reply with quote
Post Posted: Tue Jun 28, 2016 1:37 pm
BTW, I usually fire up Emulicious profiler when suddenly something doesn't seems to work properly. First, I try to find which of my program functions is unreasonably eating too much CPU, then I check in the SDCC generated ASM file if -by chance- I inadvertently wrote some code there that made the compiler generate calls to slow standard library functions such as:
__mod*
__div*
__mul*
__get_remainder*

as they can take up to 2% of the whole CPU time (I've seen once one of these eating 5 scanlines...)
After removing these, if it isn't still enough, I would start refactoring a few functions, starting from the slower ones, of course.

Are you hitting the roof 100% of time?
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Tue Jun 28, 2016 9:13 pm
I use the unsafe operations during VBlank, yes. In this game, I don't have to update patterns during the game loop, so most of the time there's just SAT updates during VBlank and logic and SAT copy updates during the frame time.

Maybe the game is too heavy, some objects use fixed point maths and there can be several on screen.

I always use shifts, and/or and powers of two in my code, never trust a compiler optimization thus never use * or / at all. I've taken glances at the code generated and there's no library calls of such type at all.

Luckily I have solved the issue inlining tons of functions and unrolling some loops, for example those which are used to add my metasprites to the SAT.

It's been a surprise. I just thought the SMS was light years more powerful than the NES, but, at least in my scenario (my own compiled C code) they seem to be pretty simmilar if we don't count the advantageous DMA to transfer the SAT copy to VRAM in the NES.

For some of my fixed point objects, the physics are so simple that the increments can be precalculated, using lookup tables you can use plain bytes for coordinates eliminating the need to do and undo the fixed point (instead of adding 0.5 to X each frame, the lookup table adds 0, 1, 0, 1 to a pure, integer 8 bits variable, for example). To my surprise, almost no gain was obtained from this.

In the NES (6502), the generated code to use lookup tables of const unsigned chars use the indirect addressing mode LDA address,X, where address is the beginning of the array. Just incrementing X, which is a 8 bits pointer register, you can read the whole array.

Usually, b = lookup [c]; is just:

LDX _c
LDA _lookup, X
STA _b


(The above code takes just 12 or 13 cycles depending on if a 256 byte page boundary is crossed when adding X to _lookup or not)

In the SMS (Z80), the generated code is more complicated. The generated code, overall, takes more T-states in this processor.

   ld   bc,#_lookup+0
   ld   hl,(_c)
   ld   h,#0x00
   add   hl,bc
   ld   a,(hl)
   ld   (#_b + 0),a


So maybe it's just a matter of changing my coding style :D
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11824
  • Location: London
Reply with quote
Post Posted: Wed Jun 29, 2016 5:22 am
The Z80 really wants to keep things in registers, having to take everything from RAM is what's really costing time here. The 6502's zero page in place of real registers is perhaps more aligned with the memory model we see here. I can do an 8-bit aligned table lookup in 18 cycles...
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Wed Jun 29, 2016 6:02 am
Exactly. It seems that manually coding in assembly is more of a gain in a Z80 than in a 6502. It looks that the processor architecture of the 6502 is more suited for compiled C code.

You mentioned "aligned", maybe I can benefit of 256-byte aligning my arrays using SDCC - Can this be done? I will research this as soon as I can :)

Maybe it's also that I haven't mastered SDCC yet. I'm sure I can learn which C code produces better code and apply such knowledge while programming. Right away I'm porting C code which was written with the NES in mind, just replacing the library calls (and of course the assets).

In other order of things, is there a way to pause a song using psglib and then resume it from the same point it was paused, instead of having to stop it and restart it from the beginning?

*EDIT*

Nevermind, now I realize that PSGlib was updated recently with...
void PSGSilenceChannels (void);
                 /* this will silence all PSG channels */
void PSGRestoreVolumes (void);
                  /* this will restore PSG channels volume */

Which I can use (in combination with not calling PSGUpdate) for something simmilar.

This solution will also silence the effects, but I can live with that.

*EDIT 2*

About the aligning issue, is defining the arrays at a fixed address the only way?
  View user's profile Send private message
Reply to topic Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next



Back to the top of this page

Back to SMS Power!