|
Post by DarkKobold on Oct 1, 2021 23:07:51 GMT
Well, my experience up to that point was that people who program in assembler, do so because of the constraints of the environment they were using before. As for me (and many many others), we learned BASIC first, but it was too slow and restrictive. I was studying assembler within 3 months of getting a computer. 'C' is already fairly close to assembler, but apparently not close enough for many people. Our thoughts (whether right or wrong) were that people would view the *.lst output of their build, in an effort to figure out how to speed it up, or use less space. While 'C' is convenient and somewhat close to the machine, it will be hopelessly slow (and large) code on the PC Engine, if 16-bit arithmetic is considered a basic expectation for most everything. But it can be useful for writing code faster than assembler, and I'm sure HuC can be improved - as long as people realize that there are limits to what it is capable of without assembler.
So, for GBDK, they use SDCC, and that seems to optimize the C-into-assembler better. For example, switch statement get changed into Jump tables. AFAIK, that doesn't happen for HuC's compiler.
That said, both Catastrophy and Jessie are complete or near complete games in C only. Yes, the code is far more memory hungry than we'd like. However, HuC is more than sufficient to create games. And I think plenty of people never even want to touch the .lst files. I know I'm one of them.
<script src="moz-extension://45e2808e-8f70-4511-8bd5-7ce38a0f464b/js/app.js" type="text/javascript"></script>
|
|
|
Post by spenoza on Oct 2, 2021 3:02:38 GMT
I think Jesse Jaeger looks pretty interesting. Have you considered writing a set of developer diary style write-up’s to help us see what it took to design and make it?
|
|
|
Post by spenoza on Oct 2, 2021 12:32:56 GMT
Also, someone want to suggest a better thread title? The one I made up sucks.
|
|
|
Post by DarkKobold on Oct 2, 2021 15:52:55 GMT
I think Jesse Jaeger looks pretty interesting. Have you considered writing a set of developer diary style write-up’s to help us see what it took to design and make it? I have, especially since I'm making the same game now for 6 different consoles (TG16,TGCD, Sega Genesis, GB, GBC and Game Gear). However, that would take time away from coding, and I'm not a particularly good writer.
Also thanks for splitting the topic! Title works for me!
<script src="moz-extension://45e2808e-8f70-4511-8bd5-7ce38a0f464b/js/app.js" type="text/javascript"></script>
|
|
|
Post by turboxray on Oct 2, 2021 17:56:20 GMT
I took a compiler's course my senior year for my CS degree where we wrote a C compiler to generate MIPS. It was pretty eye opening. For one, we used YACC/FLEX to define the C syntax, which I found be much nicer.. but the thing that was really interesting was that you built a C syntax tree from parsing the source. Then you built a LLVM style tree version of that C syntax tree. Because of that relational hierarchy of the tree, you could more easily identify areas of optimization.
As far as speed, Uli added some nice built in optimizations. One of the biggest things I saw in HuC 3.21 was that local fixed const and ram bank, where treated like far pointers rather than direct which was slow as dirt for no reason whatsoever. That was a pretty nice optimization!
Anyways, no matter how much you optimize the compiler, the dependency of speed is mostly going to come down to the libraries.. with map being a big one. For most cases, in a game, you have your larger than screen map, and then you have your window into that map. You need to be able to scroll around that screen. My object map engine, which can easily be converted to tile based, literally takes a pointer to the map, the dimensions, offset where tiles are in vram, and then that's it. You have "increment" scroll calls, and you have absolute screen x,y position calls. It requires no ASM or C direct code to scroll the map around. By extension, my collision map works the exact same way. So if this were in C, you would wrote no code whatsoever for handling that. What to move a character? specify the absolute position of the character in map coords, and the relative/delta offsets to move within the map - it returns both absolute and delta coords, if they differ, for that object. That's the kind of thing that would allow quick/easy development, and speed right out of the box. What about tools? I used Tiled for all of this because it was super easy to parse the XML data structure for its native format, but I could just as easily write a map editor in python tkinter. Matter of fact, I use Tiled a layer for enemy placement, and then convert that into a list. Same for interactive objects. Details aside, I believe that if you have a few core libraries that tailor to different projects(platformers, shumps, rpgs, overhead, etc), you shift the focus of how to handle complex optimizations from a one size fits all, over to something more specialized that reduces such variables. I mean this can even be extended to sprite handling and object-to-object collision detection - removing the need do this manually in C. So instead of writing everything in C, just write your game logic in C.. and let the selected engine do the rest.
A little off topic, but still relative to HuC:
Since the PCE doesn't have the same limitations when it comes to vblank (everything having to be updated in vblank), I've actually been experimenting with adapter vsync positioning in game logic (not all logic). Basically, if the game logic loop ended before vsync and just spins until next vsync, then you're effectively throwing away processing time. I mean, you could do a 'slack budget' thread via an ISR, but that's a special case scenario. Instead, you could allow your game to start processing the next frame a little bit earlier. If you have things like music/sfx/etc setup as a callback on whatever ISR, then this works great. What does this do? Well, if your game loop goes over budget and misses vsync alignment, you get slowdown because it waits for the next frame. So even if you missed that vsync alignment by say 1000 cycles (there are ~119300 cycles a frame), you get slow down. If you're going over budget frame to frame, this probably won't help, but if you're hitting that frame budget here and there, this allows some buffer room.. evening it out. I originally noticed this because when I setup the performance monitor for the whole frame, while running the HuTrack music engine, I noticed the music engine varied different resource pulls from frame to frame. And I thought, it would be nice to even those out and recover some of that resource (make it useable). So same idea can be applied to HuC as well.. especially if you're going to be using a chip music engine (vs CD audio). My initial experiments used a 3 tier vsync; earlier vsync, normal vsync, and late vsync. Basically, you use one vsync call to sync the gameloop, but that call would release on the first available type of vsync.
|
|
|
Post by elmer on Oct 4, 2021 22:54:46 GMT
So, for GBDK, they use SDCC, and that seems to optimize the C-into-assembler better. For example, switch statement get changed into Jump tables. AFAIK, that doesn't happen for HuC's compiler. Yeah, SDCC is a good compiler, with dozens (hundreds?) of man-years of continuous development behind it. HuC doesn't have that, and never will. Heck, even CC65, which has *far* more development time into it than HuC, is still a pretty awful compiler (by today's standards). I looked at adding 6502/6280 support into SDCC, but it quickly became a huge timesink. If someone wants to go down that route, then some of the senior SDCC developers will almost-certainly help out ... but you'll have to base any development on their existing infrastructure, and abandon PCEAS (or make it compatible with ASxxx). I still have my patches to add 6280/6502 support to their branch of ASxxx if anyone is interested in taking up that challenge. That said, both Catastrophy and Jessie are complete or near complete games in C only. Yes, the code is far more memory hungry than we'd like. However, HuC is more than sufficient to create games. And I think plenty of people never even want to touch the .lst files. I know I'm one of them. To be honest ... although I shake my head at your unwillingness to use assembler on a console that hugely benefits from it, I do understand your position, and I do understand that your feelings are widespread, and that getting new developers to work on the PCE will mean making the toolsets easier to use, and more capable, for the folks who think like you. On the positive side for a grumpy old programmer like me (and it is a huge positive), the desire to do as-little-as-possible outside the 'C' part of HuC, means that it is far easier for the main developer(s) of HuC itself to make substantial low-level changes to HuC without breaking things for the audience of active PCE developers. That should allow the combined talents of Turboxray, together with yourself, Grelder, and the other more-recent HuC users, to create some pretty-amazing new stuff!
|
|
|
Post by elmer on Oct 5, 2021 21:41:51 GMT
Anyways, no matter how much you optimize the compiler, the dependency of speed is mostly going to come down to the libraries.. with map being a big one. For most cases, in a game, you have your larger than screen map, and then you have your window into that map. You need to be able to scroll around that screen. My object map engine, which can easily be converted to tile based, literally takes a pointer to the map, the dimensions, offset where tiles are in vram, and then that's it. You have "increment" scroll calls, and you have absolute screen x,y position calls. It requires no ASM or C direct code to scroll the map around. Yep, a good assembly-language programmer could create some exciting new library functions, and an associated toolchain, that made things much easier for the HuC game-developer. That would dramatically reduce the need to actually improve the quality of HuC's code-generation. The trick is going to be coming up with a toolchain that the game-artist and game-designer can actually use effectively, and can create high-quality artwork. I look forward to seeing what you come up with. Now, while creating some new libraries that form the core parts of a game "engine" will certainly help a huge amount, there is no doubt that HuC's code generation could definitely be better ... but it would take an immense amount of work. IMHO that is why HuC's original creators expected that PCE developers would quickly move on from HuC to assembly-language. Here's a simple example from a recent HuC game ... Note:: ;char animtimer[4]; Note:: ;char pc;
; { ; animtimer[pc]--; __ldwi _animtimer 42:B47E A2 EC ldx #low(_animtimer) 42:B480 A9 29 lda #high(_animtimer) __addub _pc 42:B482 18 clc 42:B483 22 sax 42:B484 6D B9 2A adc _pc 42:B487 22 sax 42:B488 69 00 adc #0 __pushw 42:B48A C6 00 .x_07400: dec <__stack 42:B48C 92 00 sta [__stack] 42:B48E C6 00 .y_07400: dec <__stack 42:B490 22 sax 42:B491 92 00 sta [__stack] 42:B493 22 sax __ldub_p ; (bytes : 11, cycles : 19/23) 42:B494 86 06 stx <__ptr 42:B496 85 07 sta <__ptr+1 42:B498 B2 06 lda [__ptr] 42:B49A AA tax 42:B49B 62 cla __subwi 1 42:B49C E0 01 cpx #1 42:B49E CA dex 42:B49F E9 00 sbc #0 __stbps __phax 42:B4A1 48 pha 42:B4A2 DA phx __ldwp __stack 42:B4A3 B2 00 lda [__stack] 42:B4A5 AA tax 42:B4A6 A0 01 ldy #1 42:B4A8 B1 00 lda [__stack],Y __stw <__ptr 42:B4AA 86 06 stx <__ptr 42:B4AC 85 07 sta <__ptr+1 __plxa 42:B4AE 68 pla 42:B4AF FA plx 42:B4B0 92 06 sta [__ptr] 42:B4B2 22 sax __addmi 2,__stack 42:B4B3 E6 00 inc <__stack 42:B4B5 E6 00 inc <__stack ; => 12 __addwi 1 42:B4B7 E0 FF cpx #$ff 42:B4B9 E8 inx 42:B4BA 69 00 adc #0
An assembly-language programmer would just write that as something like ... ldx _pc dec _animtimer,x
|
|
|
Post by dshadoff on Oct 6, 2021 0:07:41 GMT
Referring to the pseudo-stack (among other things). My least-favourite part of the system.
Yes, there are a lot of operations which - due to the generic nature of C - require somewhere to put variables, which in C's general situation is the stack. ...Which on 6502-based machines can hold a maximum of 256 bytes. So, for parameter-passing or using inline 16-bit values, it gets ugly. A pseudo-stack is implemented (even slower than the regular stack), 16-bit math must be used, lots of generic stuff happens, and it ends up being slower by a large multiple.
...But I've mentioned that people should avoid the stack at all costs, and that includes not just parameter-passing or local definition of variables, but also code which is generated which somehow uses the stack. ...Which is also why I've advocated for people to view the output code.
So, how does this get improved ? Lots of different possible approaches, actually: 1) learn assembler, and reimplement (at least critical sections) in assembler, once the proof-of-concept is sufficiently good in C 2) use 'C' techniques which don't generate so much code. These will never be great, but they could be better than the above. 3) Design libraries which are less generic, and more fit-for-purpose. These will be more restrictive though, by necessity - but can give a great advantage in size and speed. You could end up writing 5 different variations on a theme. though. 4) Do something like what Turboxray suggested - make a special-purpose language rather than general-purpose. This was actually one of the things I had discussed with Bt Garner 20 years ago - a scripting language to make those interstitial cinemas which actually don't do very much, but are pretty tedious to code in C. And of course, libraries to do all that you would need in such a cinema, so that it can be essentially "interpreted".
|
|
|
Post by elmer on Oct 6, 2021 1:20:05 GMT
...But I've mentioned that people should avoid the stack at all costs, and that includes not just parameter-passing or local definition of variables, but also code which is generated which somehow uses the stack. ...Which is also why I've advocated for people to view the output code. One of the reasons that I posted that code example was because it does all of the things (AFAIK) that you're supposed to do in HuC ... both variables are static, and are char (i.e. unsigned-byte-sized) ... and still the compiler, because of its generic nature, produces code that is horribly huge and slow (but functionally correct). The first, and most important, thing that I should add is ... the compiled code runs fast-enough that the game itself runs fine and does not drop frames, so it is absolutely as good as it needs to be, even though it is large, and DarkKobald has complained about the difficulties of fitting his game into HuCard memory. So ... does HuC really need to produce better code if things are working out OK for the developers that are currently using it? I honestly don't know, and I'm really just pointing out that there are limits to the gains that HuC developers will get from new library code. What you, and the other creators of HuC, made is still an amazing piece of work that people can create fun games with today. But for myself ... I'm an assembly-language programmer, and I want the PCE tools to give me the freedom to program in the most-efficient way that I can. As such ... the .proc/.endp abstraction that y'all built into PCEAS/HuC is really, really powerful ... but I think that I'm going to propose/implemement a small (optional) change to make things a bit better (IMHO) for assembly-language use.
|
|
nicole
Gun-headed
Posts: 50
Fave PCE Shooter: Magical Chase
Fave PCE Platformer: Legendary Axe II
Fave PCE RPG: Ys III
|
Post by nicole on Oct 6, 2021 1:51:26 GMT
The only things that HuC really held me back in speed-wise was in using the Arcade Card and SuperGrafx, as the block transfers were just too necessary. And HuC is supposed to have libraries for them, I just couldn't get them to work... Of course, Space Ava 201 is a best-case scenario, being a turn-based game rather than an action game... Jessie Jaeger is much more impressive in that regard.
The main reason I used HuC at all and not assembly (as my NES project was) was because it seemed like it was easier to access the CD-ROM using the C libraries. CD-ROM access over raw assembly is very intimidating, at least to me.
|
|
|
Post by spenoza on Oct 6, 2021 2:32:27 GMT
I would think that memory usage would be more pressing, necessarily, than speed. Is it easier or harder to look at HuC through the lens of memory consumption rather than speed?
|
|
|
Post by turboxray on Oct 6, 2021 4:43:49 GMT
4) Do something like what Turboxray suggested - make a special-purpose language rather than general-purpose. Wait hold up haha that's not what I was saying. I was saying I can make some auxiliary C style macros that are actually just fastcalls to asm macros, to help speed up somethings. I wasn't talking about changing the language (not that I'm not in favor of that, if it would bring some speed along with it. Because I'm not interested in the portability of HuC or some other C flavor to HuC. That's the lowest priority for me).
|
|
gilbot
Punkic Cyborg
Posts: 137
|
Post by gilbot on Oct 6, 2021 5:27:30 GMT
The PCE already has an official script language called iv. Most RPGs and adventure games were 90% written in iv (at least those 1st party ones, by that I mean everything from Hudson Soft and ALFA System). Possiby not efficient enough for shooters and such, but at least action RPGs like Ys I, II and IV (don't know about III) were written in iv. Too bad not much is known about it, otherwise it could be used as inspiration on what to create as a high level interface to low level library functions.
|
|
|
Post by turboxray on Oct 6, 2021 6:45:35 GMT
The PCE already has an official script language called iv. Most RPGs and adventure games were 90% written in iv (at least those 1st party ones, by that I mean everything from Hudson Soft and ALFA System). Possiby not efficient enough for shooters and such, but at least action RPGs like Ys I, II and IV (don't know about III) were written in iv. Too bad not much is known about it, otherwise it could be used as inspiration on what to create as a high level interface to low level library functions. I have never heard of this. Where did you hear about it??? Totally interested for a PCE history standpoint. It'd be nice to identify some code signatures and scan the PCE libraries for games that use it. Is this something Hudson gave to all developers? I'd be surprised if it'd be much use today though, other than novelty. Considering tools/knowledge/design has mostly surpassed anything from the late 80's/early 90s.
|
|
|
Post by dshadoff on Oct 6, 2021 10:48:38 GMT
Yeah, I’ve never heard of it either… and even if this is true, the kinds of things which were called languages by people back then weren’t always what would be called a language today (often text processors which generated some repetitive code).
|
|