Shop OBEX P1 Docs P2 Docs Learn Events
Best Language for Game Development — Parallax Forums

Best Language for Game Development

I'm currently working on a custom JAMMA arcade game PCB, with the Propeller 1 as the driving microcontroller due to its high power and built-in video generation ability.

I'm trying to choose between C and Spin for development. I'd rather not have to learn a new language for this project, as I already know C, but I understand that Spin gives you more control over the board.

What's the verdict on this one? Thank you!

Comments

  • You should use C. I'm not sure one gets any more control with SPIN.

    The important parts, video driver, sound, sprites, etc... are frequently done in PASM. Assembly language. Typically, these run on one or more of the COGS, with the main game loop running as a larger program on one COG.

    All of that can happen In either language.


  • The language choice should consider the game complexity in both computation and code size terms. Compact code size comes at the price of slower speed, Spin is the most compact but also the slowest, C with the LMM model is the fastest but with the most large code size, C with the CMM model is in the middle with a compact code size and resonable speed. There are threads with a code size/speed comparison between the available languages, can't remember the link right now.

    Since you already know C there is no reason to learn Spin for your project (well, you need to learn at least PASM for the drivers), start with LMM then if the code size is too large and don't need speed, change to CMM. The C language has other advantages like the possibility to use code overlays if your code can't fit, see my post http://forums.parallax.com/discussion/163970/overlay-code-with-gcc

    About the control over the board, both languages can control the hardware in the same way, but as potatohead says, your core drivers (video and audio mainly) should be coded in PASM and run in one or more cores as needed. For some examples, see my P8X Game console https://dev.maccasoft.com/propgame/
  • JonnyMacJonnyMac Posts: 9,104
    edited 2017-05-14 14:37
    FWIW, I think it is a good idea to learn Spin, even if you don't use it, as it is tied right to the Propeller architecture and gives you a quick tool for experimenting. At the risk of sounding grouchy, any person who claims to know C can learn Spin in under an hour. This doesn't apply, of course, to the multitude of Arduino copy-and-paste warriors. :)

    I do all of my development in Spin (presently working on a 6000-line program for a laser tag controller), but am looking at C as well -- especially the CMM option which might give me a bit more speed with about the same code density as I have now. And then there's Forth. Peter Jackaki keeps showing off amazing things with his Tachyon and I've long been interested in Forth, I just haven't yet wrapped my head around it.
  • A lot of great info, thanks everyone! Looks like I'll be going with C/CMM. I haven't gotten into the development process yet, but if there's already a hardware VGA generator builtin to the cores, is there not already a PASM driver built for it? Either from Parallax or in the object exchange?
  • There are no built-in generators. It's all done in software (PASM). TV output (NTSC/PAL) can be done using a single cog (core). VGA has higher resolution therefore higher data rate and is usually done using 2 or 3 cogs dividing up the work (fetching data then serializing it). There's a variety of drivers in the object exchange. The interfaces are in Spin, but the "guts" of the drivers are all in PASM.
  • JRetSapDoogJRetSapDoog Posts: 954
    edited 2017-05-14 20:54
    Not that it really matters to your main point, escher, but the "built-in video generation ability" to which you refer--one for each of the eight cogs--is a circuit known as a "serializer" that spews out data quickly at a steady pace, faster than what could be done by simply big-banging (twiddling the pins directly with assembly). That serializer has mostly been used for generating video signals, though it's technically not limited thereto. Chip (big 'C'), the designer, obviously had video (NTSC/PAL and VGA) in mind when he designed the serializer into the chip (small 'c'). But it always takes at least a cog of user-supplied code to configure/control the serializer and regularly feed data to it fast enough that it never "runs dry." I guess you could think of video generation being one-fourth hardware and three-fourths software, as even with the serializer, the actual vertical and horizontal sync timing is all done in software (the serializer not knowing the difference between sync data and video/pixel data). So, you're partially right in saying that there's video hardware, but the whole picture includes a lot of software, and it is that software that allows the serializer circuitry to be so flexible, as it can be configured and fed in so many different ways, and maybe even reconfigured on the fly.

    As to which language you should use for game development, I don't think anyone can say with absolute certainty (at best, you're going to get a hung jury and a mistrial in terms of a "verdict"). It depends on your experience, preferences and needs, so I wouldn't write off any language. You might even use one language for one game and another language for another game. Now, there's no question that your existing familiarity with C is a plus for choosing C, and it is faster than SPIN. But it still amazes me how code dense SPIN is; I'm still often pleasantly surprised at how much functionality one can pack in using it. When I code, I often check the number of longs left, and it's clear that the SPIN byte codes are quite efficient space-wise (sorry, I can't give you a percentage compared to C offhand). Having said that, if you were doing a game with a lot of text, then the compactness that SPIN usually provides wouldn't be such an advantage because, as far as I know, a letter/character takes a byte and there's basically nothing SPIN can do about that to optimize storage (and there isn't any compression of text strings or any thing like that, which would slow things down anyway). Nevertheless, general code "boils down" quite nicely in SPIN, maximizing/stretching the precious HUB ram. As far as the readability of high-level languages, I'd much rather write SPINS's "repeat i from 0 to 9" than C's "for (i=0; i<10; i++)", as the latter just seems like glorified assembly language to me, even though one can get used to it quickly. Then again, C offers libraries and stuff to make life easier. Anyway, don't dismiss SPIN completely. As Jon says, at least become familiar with SPIN because, at the very least, it's a useful/necessary "glue" language since PASM drivers generally use SPIN to provide interfaces to the high level code. And most of SPIN is straightforward (though there are "gotchas" to be aware of, such as needing to use "=>" instead of ">=" in a comparison, which Chip will likely change in the P2 chip that's under development). Anyway, overall, I like using SPIN because I'm always bumping up against memory limitations, even though it's slower, as I don't need so much raw speed (BTW, SPIN2 on the P2 currently in design will likely run, on average, at least 20X to 30X faster than SPIN on the P1 (and that's without taking into consideration any possibly speed-up that could be provided by streaming data from the "lazy-Susan" hub memory if SPIN2 is fast enough to keep up with it, which it might not be), if that's a long-term consideration for you). Hey, I'm kind of surprised someone hasn't mentioned a flavor of BASIC yet. I haven't used BASIC on the Prop yet, but I think that there's a version of it with similar code-density to SPIN. I have wondered if it might be more applicable to certain kinds of programs in terms of readability and so on. But like I said, I'm pretty happy with SPIN. --Jim
  • For the sake of the Propeller community, if your project is going to be open source then I would ask you to program it in C or C++. There are far fewer examples of video generation in C/C++ apps than there are for Spin, so it'd be great to expand that. Of course, like others said, the bulk of that is all assembly anyway so it doesn't make too big of a difference, but it would still be nice to get more examples out there.

    Cheers,
    A C++ guy
  • I agree! The OP knows C. We can translate some SPIN for them, if need be.

  • Wow thanks for the excellent response JRetSapDoog.

    I've taken a look at some VGA PASM code, and it's definitely some dense stuff.

    I have a somewhat specific implementation in mind, which involves multiplexing between a standard 31kHz VGA signal and 15kHz CGA signal.

    Jury's still out on whether I'll go with Spin or not... I don't see any particular reason why any PASM driver I would write wouldn't be just as easy to call from C code as Spin.
  • Also, follow up question: is this serializer able to output an analogue signal or do I need an external DAC?
  • We haven't done a CGA signal yet. A TV driver timing should work. Nobody had a test monitor. I've got one now, MGA too.

  • Interesting, but even calling the output "CGA" is disingenuous; there's no explicit color limitation like with CGA. The only similarities are the refresh rate and resulting resolutions.

    I need the "CGA" output for JAMMA boards which are too old to have VGA output, and to develop game boards specifically for "CGA".

  • potatoheadpotatohead Posts: 10,261
    edited 2017-05-14 22:56
    Oh, you mean CGA timing, but with CHA display otherwise?

    Yeah, that's been done.

    The lowest, will still display on modern CHA capable displays is 640x480 interlaced. The standard Parallax driver does it non interlaced.

    CGA uses the even slower TV sweep frequencies, like you say. (15khz) Should be able to take either a TV driver, or one of the slowest VGA drivers and adjust timing and or signal output.

  • JRetSapDoogJRetSapDoog Posts: 954
    edited 2017-05-15 00:28
    escher wrote: »
    Also, follow up question: is this serializer able to output an analogue signal or do I need an external DAC?
    With the Prop, you need an external DAC for both composite, component, or VGA (i.e., anything analog), generally a resistor network. The number of resistors and their configuration depends on the type of signal and the number of colors (of course). For example, a simple 8-color VGA display can be had with a single resistor in series for each of the RGB channels (as well as limiting resistors on H&V), or a 64-color VGA display can be had with as few as two resistors in parallel per channel (for a total of 1+1+2+2+2=8 for VHRGB), though such a configuration may not give the maximum "separation" between colors or a perfect impedance match for the monitor (but it works pretty well and was used on the DemoBoard for a long time).

    For old-school analog video, potatohead is the go-to-guy. I think he's committed to preserving NTSC/PAL and component video for generations to come. His circuits/code will likely be powering the media readers of the Third Millennium Archive that's planned for 3080 AD, in Deverapolis, USA 2.0, if I'm not mistaken.

    BTW, I wonder how you will "multiplex" between VGA and CGA (assuming a CGA driver/circuit can be built). That is, I wonder if that just entails mechanical or electronic switching between them, or if some kind of overlay is implied. Anyway, that's all beyond my experience. Gee, I even had to google what a "JAMMA arcade game PCB" could refer to.
  • CMM C is about 2x faster than Spin, and slightly larger. That said, the optimizer means that as your project grows in size, CMM code actually ends up smaller than the same project in Spin.

    It's completely false that Spin gives you more control than C - both have access to everything in the Prop. PASM is the only language that gives you full and direct access to everything, and you can use PASM with both Spin and C.

    The Elev8-FC firmware is written in C. I was maintaining both Spin and C versions, but the Spin version became too difficult because there are things that Spin simply can't do as well as C (structs, classes, inline functions are examples).

    If you're comfortable with C/C++ you should use it. You may have to port some PASM objects across if you want to use them, but if your plan is to write everything from scratch you should use what you know.
  • potatoheadpotatohead Posts: 10,261
    edited 2017-05-15 02:09
    :D

    I think they just want to be able to change timings.

    Heh, I got a broadcast, pro grade CRT for a song. The Prop looks beautiful on it.
  • Yes, by multiplex I meant being able to switch between the two outputs, however at the moment I'm overwhelmed as it is with the complexities of simply implementing a 640x480 (a nice standard target resolution), 8-bit VGA signal. Some napkin math:

    640x480 resolution @ 8 bpp = 300K per frame.

    Meaning I would need over a quarter megabyte of dual-port SRAM to implement a frame buffer, and over a half a megabyte (600K) to implement the inevitably necessary dual frame buffer. This all of course ignores how expensive a properly sized SRAM IC would be, and the fact that there aren't even enough pins on the Prop1 to be able to interface with the SRAM in addition to all of the arcade controls and video and audio signals necessary.

    Am I over or undercomplicating this problem?
  • MJB wrote: »

    Outstanding. How did this not come up in my Googling of literally "vga game propeller".

    Giving this a read now. Looks likely that its output will be lower resolution, in terms of both pixel count and bpp as mine, but could give me some tangible restrictions.

    Thank you!
  • potatoheadpotatohead Posts: 10,261
    edited 2017-05-16 01:58
    Many Propeller games are actually single buffer and or tile / sprite based. Dynamic display.

    Full on bitmaps can work at 256x200 or so pixels, and can allow for double buffer, partial, and 4 colors per tile.

    Most things are dynamically displayed. Single buffer. Having a few sprite COGS, and a tile / display COG makes this possible.

    For VGA, a 64 color screen works nicely. Baggers and I put together a 256x200 64 color VGA driver that would do tiles and quite a few 4x8 sprites per display line. 50 to well over 100, using 2 to 5 COGS. That's an idea of where it can go. More than that can be done.

    Lots of tricks are possible too. It's a software driven display. An example might be to do some of a display with 4 colors, other parts more colors.

    IMHO working at 640x480 is entirely possible using dynamic display techniques. No full screen bitmaps. Just tiles and sprites. Your color depth is tied to resolution. 2 and 4 color can do 640 pixels easy. Larger depths top out at 320 or fewer pixels without very advanced code..

    But, the basic drivers do a lot. Starting there will get you going. External RAM is tough to do fast. It's all about dynamically generating scanlines.

    Have fun! You can likely pick up enough SPIN from the many games done so far.
  • @potatohead Just stumbled across your 2010 thread explaining the graphics demo, small world haha: http://forums.parallax.com/discussion/123709
  • Cool!

    Yes, that driver can be VGA, and it does a lot more than it appears.

  • escherescher Posts: 138
    edited 2017-05-17 18:20
    @potatohead, can you foresee any issue with using two cogs and their serializers to output 8-bit video in such a way that:

    Cog 1's serializer outputs the signals for RRRGGGBB, and Cog 2's serializer outputs xxxxxxVH?

    As long as the counters driving the two serializers are in sync, such that V and H (vertical and horizontal sync lines) are correctly timed with the RGB video signal, this should be practical?
  • potatoheadpotatohead Posts: 10,261
    edited 2017-05-17 18:36
    You probably can get one to do that. A small error won't hurt anything. Just perform the sync operations with an explicit bit operation. If you do this right after a waitvid completes, you are timing locked to the signal for free, just delayed by an instruction.

    Set the right sync value ahead of time, while a waitvid is running so the sync instruction does the right thing at the right time. Size your waitvid so one ends right when sync needs to happen.

    But two works too. It's fine. Just sync off the counter, and they will run together all day long.

    The sync COG can probably do tiles or something as it's largely idle.

    ALL you need do is the math for a slightly deeper DAC resistor ladder.


  • potatoheadpotatohead Posts: 10,261
    edited 2017-05-17 18:54
    Oh, I forgot. There is a VGA version of the TV.spin. The graphics.spin will work with either one. Forgot that in the above.

    As you are looking for 8bpp, you probably won't need it, but I thought I would clear that up.

    There are several tile and sprite drivers out there. The important thing you need to know is the sprite list gets sorted during ot ahead of vblank. You mask in all the sprites ahead of drawing the scanline. Tiles first, then sprites.

    Super easy parallel operation happens when you assign one graphics COG to a line. More cogs is more lines ahead of the current line equals more time for them to do their work, equals a lot of sprites. You can get a couple hundred per line that way. Per screen doesn't matter. The only real constraint is your sprite list size.

    Sync them all up at end of a scanline with a flag value written to the HUB.

    Also, take a hard look at 4 pixel sprites. At 8bpp, these fit into a single long. Super easy to handle.

    For your right, left screen masking, just make your buffer area larger than the displayed area. Masking comes for free as the masked data overspills into non displayed regions. This is faster than a boundary check and mask operation per sprite. 0 is beginning of buffer. Screen 0 is begin of buffer + 4, or sprite size.

    One layer up, in your sprite lists, bundle them in pairs or groups to make larger objects that move on a single variable update. No need to put that mess in the display kernel. I made that mistake a few times. Keep that dumb and fast.

    Because the display code will run independent of game code, the game COG has basically the whole frame for processing. It just needs to have it all done at the start of VBLANK so the display, sprites, position, order are all ready to go. Double buffering this data is an option.

    With those things, or most of them happening, you never need a bitmap, nor second buffer. It's all drawing on the fly. Tiles can be stacked to make bitmaps in regions of the screen that may need them, same for sprites.

    Your sprite COGS will shift and mask, based on modulo X position. No need for more than one copy of sprite data.

    Result is max HUB RAM for display assets.


  • escher wrote: »
    Cog 1's serializer outputs the signals for RRRGGGBB, and Cog 2's serializer outputs xxxxxxVH?

    As long as the counters driving the two serializers are in sync, such that V and H (vertical and horizontal sync lines) are correctly timed with the RGB video signal, this should be practical?

    You can do 8 bit + sync in a single cog, take a look at this invaluable collection of video drivers:

    https://github.com/konimaru/waitvid.2048

    The drivers under the scanline folder all allows to set the video and sync signals on two different pin groups, allowing 8 bit colors.
Sign In or Register to comment.