|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Goto page Previous 1, 2, 3, 4, 5, 6, 7, 8 ... 15, 16, 17 Next |
Author | Message |
---|---|
|
Posted: Thu Mar 31, 2016 3:15 pm |
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 |
|
|
Posted: Thu Mar 31, 2016 3:24 pm |
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 :| |
|
|
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. |
|
|
Posted: Thu Mar 31, 2016 4:04 pm |
Awesome! That works... warnings gone after replacing the '&0xFF' in the macro with '%256'... thanks! |
|
|
Posted: Fri Apr 01, 2016 11:01 am |
Pushing this small update. Thanks for letting me know about the warning :) | |
|
Posted: Sat Apr 02, 2016 10:51 am |
Awesome! No problem... |
|
|
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 . |
|
|
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!) | |
|
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... | |
|
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... |
|
|
Posted: Mon Apr 04, 2016 7:57 am |
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. |
|
|
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. |
|
|
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! :) | |
|
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:
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. |
|
|
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. | |
|
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. |
|
|
Posted: Tue Apr 19, 2016 6:20 am |
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. |
|
|
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. |
|
|
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...) |
|
|
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 |
|
|
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. | |
|
Posted: Wed Apr 20, 2016 3:57 pm |
It was that, All my problems are solved now, thank you :) |
|
|
Posted: Thu Apr 21, 2016 8:35 am |
Waiting to see your work, FeRcHuLes!! :-D | |
|
Posted: Sat Apr 23, 2016 2:13 pm |
Let's see what comes from this homebrew, thanks kusfo!!. |
|
|
Posted: Wed May 04, 2016 7:22 am |
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. |
|
|
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++. |
|
|
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. | |
|
Posted: Fri May 06, 2016 7:49 am |
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! |
|
|
Posted: Fri May 06, 2016 8:52 am |
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 |
|
|
Posted: Fri May 06, 2016 9:16 am |
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. |
|
|
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) {
becomes return a + b; } 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. |
|
|
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. |
|
|
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. |
|
|
Posted: Sat May 07, 2016 3:31 pm |
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 ;) |
|
|
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. | |
|
Posted: Mon May 09, 2016 11:09 am |
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... |
|
|
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? | |
|
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. |
|
|
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. |
|
|
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 |
|
|
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. :) | |
|
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. |
|
|
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. |
|
|
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). |
|
|
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. |
|
|
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. |
|
|
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? |
|
|
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 |
|
|
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... | |
|
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? |
|
Goto page Previous 1, 2, 3, 4, 5, 6, 7, 8 ... 15, 16, 17 Next |