Why creative types shouldn’t settle for anything less than ownership

Last week, I read an article by a professional game developer entitled “Making games for a living means being in constant fear of losing your job.”

The author’s solution idea is for game developers to unionize, in much the way the movie industry has unionized. I think unionization would be a great thing for the industry, but I’m not sure it goes far enough.

The videogame industry started about 40-50 years ago. The people who founded the industry worked very hard, started from nothing, and worked insane hours, pouring their life into creating the new industry. The ones who were successful ended up making a fortune.

That fortune was only made possible through ownership. It wasn’t making games that made the founders wealthy — it was making companies. In a lot of cases, the company came later. Nolan Bushnell and Ted Dabny started Atari in 1972 with $500 (about $3000 today). A kid like Richard Garriott or Jordan Mechner programmed a game in his bedroom on his home computer, sold it through mail order using a classified ad in the back of a computer magazine, and made a million dollars, and decided they should turn it into a company, using that money to hire more people to make more and bigger games.

Somehow, the expectation for the new employees was to work just as hard, just as many hours, and crank out more games that would make millions of dollars. Only, they were doing this work as a “work for hire”, and wouldn’t own their work — their employer would own it.

This means all the same hard work that the employee did that went into creating that game for his employer enriches the employer, when it could have gone to the employee’s own company that they owned and profited from. Employees enrich someone else’s empire. That’s the way capitalism works.

Because the industry now exists, it’s easier to work for pre-existing companies them than it is to start up a new company. Not only does a new company have all the struggles of just starting up, they also have to compete with already-functioning companies. But the owners who worked hundred hour weeks to found their business often expect no less of their employees.

Yet, the vast majority of employees don’t get compensated with an ownership interest the company for their hundred hour work weeks. They just get burned out and dumped when their project ships. For working for someone else, you got only a salary, not a company.

Ownership comes with things like a share of the profits. There’s also a lot of risk, but it’s balanced by the compensation package that comes with owning a company, whereas work-for-hire employees don’t get this level of compensation, yet have just as much if not more risk associated with their employment in the form of layoffs. Employees creating works-for-hire don’t even get royalties, and job security is non-existent. Once the product shipped, they were no longer needed and if there wasn’t another new project waiting for them that could exploit their talents, they were expendable.

That’s a raw deal.

Game developers who want to make money and have job security should own their work, and that means owning a piece of the company they work for.

It sounds like I’m suggesting that every game developer should be an indie game developer. I’m not. Clearly, being an indie is not easy either. In fact, it’s brutal. There’s a lot of competition. An indie has to do everything well in order to be successful, and almost no one is that talented at everything needed to be a success. Game development requires a lot of diverse skills, and a good team can cover those bases a lot better than a sole proprietor.

But what is good about being an indie developer is that you get to own your creative work. You get to create new IP, rather than toil on the sequels to someone else’s successful IP franchise. But even for workers making the next iteration of a successful known entity (let’s say Mario, for sake of example), being employed means that they should take on a share of the ownership stake in the Mario franchise, or in the company that owns Mario. That means royalties on sales, in perpetuity, of the product they worked on, and it means the right to produce new works in the Mario milieu.

This would go a long way toward padding the job insecurity that is endemic to the game development industry. Making money through royalties on existing works, and owning stocks that would pay dividends, would be a critical income stream to supplement an (ir-)regular salary.

Game developers will never get this, unless they strike out on their own and create their own companies from scratch, or if they strike together, unionize, and demand it from the companies that currently exploit them.

If an employer wants to commission creative work on a “for hire” basis, then the working conditions should be reflective of the compensation being offered: 40 hour work weeks, additional compensation for overtime, 1099 employment status rather than W-2, and salary at a higher rate to reflect the short-term nature of the work arrangement, to allow skilled professionals to earn enough to cover lean times between contracts (generally more than twice what a full-time employee would expect to be paid).

Cell phone shopping in 2019

My current phone is a Samsung Galaxy S5, purchased in 2015. I have gotten a lot of value out of the phone. Four years is a lot of time, but I think this year will be its last, for a number of reasons:

  • Screen life. For about the last year, when the screen goes to dim, it flickers. This makes the screen difficult to use with auto-brightness turned on. Also, I don’t think the max brightness is as high as it once was.
  • RAM and Storage.
    • The phone has 2GB of RAM. I find that the phone becomes very sluggish when RAM utilization exceeds 80%. I’ve taken to running a memory optimization app as needed, which when I’m actively using the phone can be as frequently as every few minutes. This has gotten to become a pain.
    • I have 16GB of internal memory, and a 32GB SD card. Android prefers to install apps and write files to the internal memory, ignoring the nice big empty space on the SD card. But when the internal memory is filled, performance is terrible. Not only can I not install updates, but the internal storage seems to be used for cache files and so on, and when there’s not enough space for the system and apps to cache data, performance becomes terrible.
  • Android updates. My carrier stopped releasing updates about 2 years ago, and I’m still on Android 6.0, which is 3 major releases behind current.

If it wasn’t for the performance issues related to RAM and cache inadequacy, this would still be a very capable phone, and I could maybe live with the screen until it finally died.

The absolute best thing about the Galaxy S5 has been the fact that it has a removable battery, and the aftermarket released some very good extended batteries. Powered by an Anker 7500mah battery, I’ve never had to worry about running out of juice, even when I’ve spent the whole day on the go, without access to a charging break. More than twice the capacity of the stock battery, it made the phone about 3/4″ of an inch thick and weigh almost a pound, but it was without question worth the added bulk.

So what do I want in a new smartphone? It doesn’t seem that the US market understands me. Here’s what’s important to me:

Pocketable

If I can’t fit it in a pants pocket — without it looking like I’m happy to see you — I don’t want it. But phones are still growing bigger and bigger. Now 6 inch screens seem to be the norm. It’s hard to use the phone with one hand when it’s so big. The Galaxy S5 is close to the maximum size that I would want to consider, and nearly everything in the 2019 market is larger.

Direct OS updates from Google

Carriers do not prioritize software updates, and tend to roll them out lagging their actual release by many months, sometimes as much as a year, and that’s if they bother to release the update at all. This is terrible.

Running out of date versions of Android can leave you vulnerable through security holes that have been patched in newer versions, and leave you out unable to install and run apps that require a higher version than is available on your handset.

Google has made a few Android handsets over the years — the Nexus line, the Pixel series, that they release updates for directly. Why can’t the rest of the world get behind that? Well, if they supported the product, then you’d be able to continue using it, and you wouldn’t have to buy the new product every 1-2 years.

Bare Android OS; No bundled apps

Carriers like to customize their phone as a way to differentiate themselves from the competition, and one of the ways they do so is by bundling apps. Unfortunately, much like with Windows 95 computers sold by OEMs, I have no interest in using many of these apps. It’s stupid to waste space on the internal memory by including these apps that I have no use for, and because they are baked into the system, they can’t be removed to free up the space.

Just provide the core operating system and the bare minimum apps needed to function as a phone: a phone app, a SMS app, a Contacts app, and the Play Store app. Let me decide what else I need to install.

If you really must bundle, then maybe offer a “Carrier Bundle” app manifest that you can use to bulk-install all the recommended default apps from the Play Store. Allow users to customize the bundle, giving us a line-item veto to opt out of installing whatever parts of the bundle we don’t want.

Big, big removable battery

My first Samsung Galaxy, the S2, was an OK phone until the battery wore out and wouldn’t hold a charge anymore. I spent a year with battery anxiety. Off charger, the battery charge dropped about 1%/minute, and so I basically spent a year walking from power outlet to power outlet, umbilical to the wall and unable to go out for more than 2-3 hours without freaking out over my dying battery. I didn’t realize at the time that the battery was bad and needed to be replaced, I just thought that the phone had some app that was power hungry and that no matter what I tried to do I couldn’t figure out how to make the phone sleep and save battery.

This taught me just how important battery life is, and when I bought the S5, I immediately went out and found the biggest battery I could for it.

But most phones these days have non-removable batteries in them, meaning that when they wear out, you either have to take the phone somewhere to be repaired with a replacement battery, or you have to buy a whole new phone.

A Li-ion battery will probably be good for 2, maybe 3 years of daily charge cycling, and if the handset is built as ruggedly as I’d like, it should be able to last longer than that. A removable battery makes this simple as buying a new battery and replacing it.

Durable

I want a phone that I can drop onto concrete and immerse in water without fear of damaging it. Usually this is solved by buying a ruggedized case for it, and this is fine, but it does add to the bulk of the phone. So why have two cases — a slim case that the phone is built inside of, and a rugged outer case? Why not just have one rugged case? The space saved by not having an inner casing could be given over to more battery, or cut down on the overall size of the device.

There are a lot of models on the market these days that are water resistant and durable enough not to take damage when dropped, especially when you factor in the afermarket armor. I don’t have a problem finding phones that meet my needs in this area, but this is probably the only area where I don’t see a lot of room for improvment needed.

Performance

I need to explain myself. I do not need blazing fast, cutting edge processor. My Galaxy S5 is a 4 year old design and when it’s not hampered by cache and memory limits, it’s absolutely fine. But the amount of system maintenance that I need to do on a daily basis anymore has gotten ridiculous. Freshly wiped, this is still a fast phone, and that’s enough for me. So Android should build into itself features that keep a healthy amount of free memory and cache storage at all times. I don’t know why this is such a problem, or why it’s gotten worse as time has gone by. During the first year or so that I had the phone, I never had such problems. About every year since then, I’ve eventually had to wipe it and start over, and am shocked at how fast the phone really is. After my last wipe, though, I didn’t want to spend an evening doing this every time the phone started feeling slow, and it felt slow within a week of my last wipe. So I started looking into performance optimization apps, and have been limping along with the help of those. But Android really needs to get its act together and handle its own maintenance and performance optimization, better than it does. Like, at all.

“Features”

Every other neat thing a smartphone does, is, I guess, nice, but I don’t care that much about it for it to sell me on a must-have device. I guess I’m in the minority here. I don’t need to be impressed by magic. I mostly am impressed by stuff that works well, and simply.

A decent camera is of course very handy, but it doesn’t have to be groundbreaking. A GPS radio that works well and doesn’t lose signal when I actually need it would be great.

I dunno, what else is there? Stuff like fingerprint readers, heartrate monitors, and so on, I don’t really use, or care about.

New “Link’s Awakening” triggers debate on remakes

It seems a lot of forum activity has been generated by yesterday’s announcement by Nintendo about the remake of Link’s Awakening on the Nintendo Switch.

In short, it seems that a significant number of fans are not in favor of the remake for one reason or another. Mostly this can be summed up as: “It’s not the exact same game as the original.”

Which, is true. The remake completely changes the graphics style, from the old 2-D look of the Game Boy original to something almost claymation-like, using a fixed 3/4 perspective, but with 3D models done in a cartoonish style. It remains to be seen what other changes are in store, and whether they are good or bad. It’s rather likely that the game will play differently in some respects, whether due to differences in the game engine, or changes in the design of the game.

I happen to love the way the new graphics look, so this doesn’t bother me. I liked the original graphics, too. And if I want to play the original game, I still can, and so can anyone with a the original hardware or a decent emulator.
But it seems that, among Zelda fans, there’s a certain segment who prefer the graphics to look “serious” — like Ocarina of Time, Skyward Sword, Breath of the Wild, etc., and not “cartoony” like Wind Waker or Four Swords Adventures. Somehow, original LoZ pleases both camps, and Link’s Awakening is in the vein of LoZ and Zelda 3: A Link to the Past. And I guess the new look for Link’s Awakening is too cartoony for them. This does not bother me. I like good art direction, and that can be “serious” or “cartoony” or something else.

It’s certainly true that many attempts at re-making some original classic game fail to capture what was special about the original game. It’s tempting to try to re-imagine something that was very, very good, thinking that adding something more will make it even better. Often that’s not the case.

Certainly, there’s a built-in expectation that a remake has to live up to, which a fresh new game doesn’t, and this can offset whatever advantage the remake had in being based off of a familiar, known, successful game. It can be very easy to mess up by deviating from the original in the wrong way. For example, updating the graphics in a style that fans don’t like, or likewise with the music. But worse would be a major change in the story, something that violates canon or continuity, or is just a change that upsets fans by breaking an unwritten contract to keep the game authentic to the characters and world that Fandom has already accepted. And perhaps the gravest mistake would be failing to ensure that the controls feel tight and responsive and give the game a good feel, ideally something virtually identical to the original. There’s nothing like tasting someone else’s attempt at your favorite recipe that your mom made when you were a kid, and no matter what they do it’s always just slightly off in a way that, even if it’s not bad, it prevents you from accepting it. I think that’s ultimately what makes fans of the original all but impossible to please when it comes to embracing a remake.

But that’s not to say that remaking a game is always a bad thing. I don’t view a remake as an attempt to replace or supplant the original. Rather, I look at it like in the way I look at theater: A playwright can write a play, and it can be performed by an original troupe of actors. And other theater companies can put on productions of the same play. Some may try to do it exactly the way the original was done, following a tradition, while others may stray and experiment. Some will be good, some will not. But it’s not like people shouldn’t continue to put on performances of Shakespeare just because purists who were fans of the original will find something not to like about it. And of course people should continue to write new, original scripts. The entertainment industry is large enough, and the audience is large enough, to sustain both.

Ultimately, it will come down to how the game plays. It’s only fair to judge the remake based on what it is, and not what it’s not. And to be clear, it will not be:

  • The same as the original.
  • A brand new, original game.
  • Different from the original in exactly the way everyone would like it to be.

Will it be worthy? That remains to be seen, and will be a matter of opinion and consensus. But I’m excited about it.

I’m buying a Switch, and other reasons I’ll be a happy gamer in 2019

So a bunch of great announcements from Nintendo came earlier today. For me, the highlights are:

Link’s Awakening Remake

Yeah, Breath of the Wild blew everyone away at launch and sold a few million systems, and I’ll admit I was very tempted to rush out and buy a Switch when it was released.

But I’m not an early adopter and I wanted to wait and see if the system would be a success, particularly after seeing how Nintendo struggled with making the Wii U realize its potential. So I held off.

I like 2-D Zelda more than 3-D Zelda, because 2D > 3D, as far as I’m concerned. And this Link’s Awakening remake looks fantastic.

I’m actually maybe more excited about this than I am about finally getting to play BotW soon.

Super Mario Maker 2

I told myself at the time, I would buy a Switch if they had Super Mario Maker for it. For a while I debated getting a Wii U so I could play both Breath of the Wild and Super Mario Maker, but I decided I wanted the real, full BotW experience with the improved controls made possible by the Switch’s joycon technology.

I’m glad I waited, now. I didn’t have to wait, I could have predicted even then that we’d see a SMM at some point on the system; it was just too popular not to be a thing. But now that it’s announced and official, I can’t wait. Really looking forward to designing some Mario levels in June.

Tetris 99

Battle Royale Tetris, awww yeah!!!!

Non-Nintendo news

Well, actually I’m not quite done with Nintendo news, but these next two are NES homebrew releases.

Full Quiet

First, Full Quiet has got me all hot and bothered to put some more hours on my AVS console. I backed the Kickstarter, and got to play it and talk to creator Tim Hartman at Portland Retro Gaming Expo back in October of last year. I’m pleased to say that this game is already looking incredible, and it should be out later this year. Even if it’s not, and release slips another year, it will be worth the wait. This is not one to miss.

Without exaggerating, I will say that this may end up going down as one of the greatest releases on the NES. And considering the greatness of the NES library, that’s a truly staggering accomplishment.

From talking to Tim, I’m aware that his game will also be released on Steam, playable on PC though emulation of the NES hardware, which means that even if you don’t own a working NES for some reason, you can play this game. And you should.

MicroMages

MicroMages should also be shipping sometime in 2019. This game bears a resemblance to Towerfall, the 4-player archery arena battle indie sensation from a few years ago, but runs on NES hardware, and is pretty fantastic in its own right.

FPGA retro consoles

If that’s not enough, I’m also looking forward to the delivery of the Analogue Mega SG, a FPGA-based, HDMI-output implementation of the Sega Genesis, and the Collectorvision Phoenix, a FGPA-based, upgraded ColecoVision plus.

I can’t imagine that I’ll have enough free time to play all of these nearly as much as I’d like to, but I still can’t wait, and I can’t believe all the good stuff that’s happening in the world of gaming, so much of it the product of cottage industry efforts devoted to keeping older systems relevant. 2019 is going to be a fantastic year.

Patriots and nationalists: the real truth

French President Emmanuel Macron tried to make some point over the weekend about Nationalism vs. Patriotism, in a rebuke of Donald Trump’s nationalistic ways.

It’s bullshit.

Not the rebuke of Trump; that was much needed. But the idea that we can distinguish between nationalism and patriotism.

They’re synonyms. They more or less mean the same thing. Yeah, there are maybe some slight differences of connotation, of usage, but they’re pretty close to interchangeable.

English is a highly overloaded language and there’s a lot of redundant words, and we use them to reflect nuance, but sometimes that nuance isn’t really there, or isn’t really as big as we make it. But for one reason or another, we end up deciding we like one word over another, like we have better taste for having a more refined vocabulary.

But I digress.

There’s good things and bad things about countries, and therefore there’s good things and bad things about loving your country. You can’t take all the good things, shove them to one side, and say “we’re going to label that ‘patriotism'” and then take all the bad things, shove them over to the other side, and say “that’s nationalism”.

We have to come to grips with the fact that whatever label you use, there’s good and bad wrapped up in humanity, and therefore, irreducibly, in any human collective.

What we need to do is use our brains, our reason and judgment, our ability to perceive, to fix the problems that the bad causes, and amplify the good. We can do this. We have had a good, long run of doing it. The overwhelming trend over the last 10,000-50,000 years has been that we do it. It seems like as we’ve scaled up our numbers, the challenges have gotten greater, and that lately maybe we’re coming up short more than not. Those glaciers are melting. We need to get back to doing smart things, and fixing problems. Less petty fights, and definitely way less concentrating wealth and power into the hands of a tiny fraction of a percent of all people.

Back to Macron: If your takeaway from his speech was that there’s bad nationalists and good patriots and hey I’m a patriot, and that sounds good and makes me feel good to say it, and now I’m better than these bad nationalists, you’ve completely missed the real truth.

The real truth is this: There’s plenty of fucking bullshit wrapped up in patriotism. Plenty. There’s plenty of bad carried out in the name of patriotism. Patriotic sentiment can and has at times netted a positive good for human civilization. But it nearly as often carries with it that bad stuff that you can’t just scrape off and shed onto the word “nationalism” and then say “our country is so good, it’s the best! I’m a patriot!” and feel like all is right with the world. It doesn’t work that way.

A lot of the good stuff about patriotism could be applied just as well, just as easily to a larger collective of people inside an even larger border.

We could draw the border as the edge of our solar system, and feel all the good things that we currently ascribe to how we feel about our country.

We could say “We are the people of Earth! A good people! The only people, in fact, anywhere! We’re all here trying to make shit work, keep each other alive, and comfortable, and maybe laugh a bit, before we die.”

We could say that. There’s no reason we couldn’t. But most of us won’t, won’t even consider it. Why? Because countries. Because invisible lines agreed to by the ancestors of powerful men, and paid for in blood. Because we’re too afraid of each other to forgive and to forge trust. Because we’re too concerned with our small concerns, and trying to fuck over someone else just to get a leg up on everyone else.

In the mythical past when we were great, which existed even then as an imperfect, incomplete fiction, we dreamed of global unification, of reaching out into the cosmos and taming the void. We dreamed about mega scale engineering projects to transform dead worlds and branch out, extending our civilization. Because we thought that it was worth something, and worth preserving, spreading, and sharing.

No one much talks about those dreams any more. We talk about oil and natural gas reserves. We talk about garbage patches, turning the oceans into a plastic soup. We talk about fresh water, and sometimes about glaciers. We talk about the Kardashians, and not very much about the disappearing animals and the vanishing rainforests. We talk about our skin color and who we like to have sex with, like it’s some big deal that overshadows the great extinction event we’ve triggered. And we talk about wars that were fought a century ago, having learned nothing from them, even as we ignore the wars happening in poor places encircling the planet, the direct heritage of the War to End All Wars, which we so foolishly perceive to have “ended”.

We needed to discard patriotism a long time ago, and embrace humanism. We are a tremendous disappointment in so many ways. And a good third of us, at least, are mindlessly tugging the whole lot of us backwards, while another third of us passively do nothing, and another third express some reservations — politely, as though “how you play the game” matters more than winning or losing.

Well, I don’t have a tidy wrap-up. No happy ending. No hopeful message. No plan. Just some observations and some judgments. You can hammer the Like button if you want to, you can share this far and wide, you can copy and paste it, you can mail it and email it, you can print it on billboards, and you can carve it into mountains, but it won’t make a bit of difference, it won’t change a thing.

What will make a difference is what you do with your life.

Enjoy your time here, while you can. Try to fix some problems. Try to learn from some mistakes.

Stan Lee, Mighty Marvel Magnate: R.I.P. and Thanks

Stan Lee, the Homer of American 20th century culture, maker of myth and monsters, died today at the age of 95. 

You almost certainly don’t need me to tell you who he was. His fame was universal, assured by his two superpowers: story telling and self promotion.

Stan wasn’t the only person who made Marvel Comics and later Marvel Entertainment the force in popular culture that it was, but he was probably the most recognizable name among a pantheon of legends that included Jack “King” Kirby, John Romita, Steve Ditko, and many others.

He created, co-created, or promoted amazing fantasies, a multiverse of heroes and villains, mutants and mundanes, celestials and sub-humans, terrestrials, extra-terrestrials, and extra-dimensionals, and even a sub-mariner. 

His energy and enthusiasm were infinite.  His corporeal form, alas, was not.  Yet his legend is assured immortality.

You held great power, and you wielded it with sublime responsibility.  You touched the lives of billions of people, and set fire to our imaginations.

Today through the news of his passing, he is making a cameo appearance on every social media feed on the planet.  We feel a collective earth quake as our hearts break upon learning that today the inevitable has finally come.

Thank you, Stan Lee.

R.I.P.

Excelsior!

Atari 2600 games with noteworthy audio

The Atari VCS was not known for its audio capabilities, yet it had a distinctive sound all its own, thanks to the chip known as the TIA, or Television Interface Adaptor. The sounds it was capable of making were pretty primitive, and mostly harsh. Buzzes, rumbles, and static dominate its sound palette, adequate for crudely simulating the sound of explosions, gunshots, running machinery, and things like wind and crashing waves. It was capable of making some bleeps and pew-pew laser sounds, too.

The majority of the games released for the Atari 2600 did not have proper background music. BGM didn’t come into its own until Nintendo released the NES in the US, about 8 years later. Most games were so limited in their ROM size that they simply could not include proper background music, although many games included at least a short looping audio background, or introductory music. Later cartridges sometimes overcame these limitations by including additional sound chips, such as the POKEY sound chip.

Pitfall II: Lost Caverns

Perhaps the best audio of any Atari 2600 game, and certainly the best at the time of its release. Pitfall II contained a full soundtrack, with dynamic changes to the background music, which changed in response to in-game events such as finding a treasure or touching an enemy. This was a true innovation and seemed years ahead of its time.

Mountain King

Music is a key mechanic in this early platform adventure game. During the search for the Flame Spirit — a mostly-invisible, flickering entity that you must find in order to appease the Skull Spirit who guards the Crown that is the object of your quest — a musical score plays, and its volume is a key to finding the Flame Spirit. The song gets louder as you get closer to it.

Later, when you obtain the crown, a chiptune arrangement of Grieg’s In the Hall of the Mountain King plays, which creates tension and excitement as you now have to race to the top of the mountain with the Crown.

Moon Patrol

Moon Patrol featured a full background music track, one of the earliest games to do so.

Blueprint

Has a background music track.

Journey: Escape

Contained a musical interlude between levels that was based on the bass line from the band’s hit single, Don’t Stop Believing.

Crystal Castles

Features musical interludes between levels and during certain game events. The musical pieces are digital arrangements of classical music pieces.

Dig Dug

Another game which had one of the earliest background music tracks. The music responds to the events in-game, in a few ways: if you stop moving, the music will sortof pause and play a somewhat annoying tone that is intended to get you to move again; if you die, the music interrupts and plays a death music; when the level is down to the last enemy, the music speeds up. The Atari 2600 port does a reasonably good job of re-creating the music on the Atari’s much more limited audio hardware.

Raiders of the Lost Ark

Adapted the theme music by John Williams from the movie.

E.T.: The Extra-Terrestrial

The title screen features a tune adapted from the movie theme.

Popeye

The song Popeye the Sailor Man is played when you grab the spinach power-up, and signifies the length of time that the power-up is in effect, giving you the strength to beat Bluto.

Gyruss

JS Bach’s Tocatta and Fugue in D Minor made this arcade tunnel shooter especially memorable. The Atari 2600 port adapts this music for the more-limited console hardware, but does a surprisingly good job with it, considering these limitations.

Ms. Pac-Man

A musical introduction kicks off the game.

California Games

An adaptation of the Kingsmen’s Louie, Louie is featured on the title screen and throughout the game.

Frogger

Frogger uses 3 or 4 different tunes for its background music, and they are catchy.

Pressure Cooker

Star Wars: The Empire Strikes Back

If you avoid getting hit for a length of time, the Star Wars theme music plays, signifying that the Force is with you, and that you are temporarily invulnerable.

Stargate

Stargate uses audio for cues to alert the player of off-screen actions. When a Lander (enemy) captures a human, a “yelping” sound is heard to alert the player that they are in need of rescue. The player can use the radar scope at the top of the screen to spot the Lander who has a human, and fly to their location to attempt the rescue. If the player is nearby the Stargate and flies into it, they will be teleported to the location of a human in danger, if there is one.

Star Trek: Strategic Operations Simulator

ST:SOS plays a few notes that will be familiar to viewers of the TV series.

Yar’s Revenge

Yar’s Revenge doesn’t feature a background music track, but does have a throbbing, pulsating hum, and a great explosion sound effect, both of which contribute significantly to the mood.

Homebrews

Thrust+

Features a full chip tune for the title screen.

Star Castle Arcade

Features a full chip tune for the title screen.

Further reading

2600 music guide

Collectorvision Phoenix demoed at Portland Retro Gaming Expo

I attended the Portland Retro Gaming Expo this past weekend, and enjoyed myself very much.

One of the many highlights of the show was getting to try out the new Phoenix console from Collectorvision.

Having seen it in person and tried it firsthand, I can say that it is the real deal, and is absolutely worth the money they’re asking for it on kickstarter.

The campaign is a bit behind the pace with their funding goal, and they need and deserve support. Just 1000 pre-orders are all that’s needed to successfully fund the project and make the system a reality.

You can back the project here:

https://www.kickstarter.com/projects/1408938247/collectorvision-phoenix-an-fpga-colecovision-conso/description

For just $200, you get an enhanced, 100% compatible, 100% accurate ColecoVision with HDMI output, built in Super Game Module and FA-18 mods, cartridge slot and SD card slot, original and SNES controller ports, and a ps2 keyboard port. Collectorvision announced Atari 2600 compatibility, and plans for supporting other vintage game systems such as the Adam and MSX.

ColecoVision is an underrated and underappreciated console, both in its heyday and today. With graphics capabilities between the Atari 2600 and the NES, it has a small but very loyal following, and a decent library of original games and an active homebrew community releasing new games. It’s a great time to get into the system if you are vintage gamer.

CollectorVision Phoenix: A modern, premium FPGA-based ColecoVision compatible retro console

Help CollectorVision reach their crowdfunding goal and make the Phoenix a reality!

Earlier this week, CollectorVision announced the crowdfunding campaign launch for their Phoenix console on Kickstarter. CollectorVision has in the past developed modern homebrew games for the 1982 ColecoVision videogame console, and in addition to that have partnered with OpCode games, developers of the ColecoVision Super Game Module expansion, which augments the system with more RAM and improved graphics capability.

I’m very excited about this system. ColecoVision was a great system, which died too young due to the videogame industry crash of 1983. It offered graphics nearly on par with the NES, a full year before the Famicom was released in Japan, and delivered home ports of early 80s arcade games that offered greater fidelity to the originals than was possible on the Atari 2600.

The Phoenix’s feature list is amazing: FPGA hardware implementation for 100% compatibility and fidelity with the original system, HDMI-out video, SD card slot, built-in Super Game Module and F18A enhancement hardware, 10 built-in ROMs of modern ColecoVision homebrew games, DB9 controller ports for original ColecoVision controllers, as well as SNES controller ports for compatibility with more common/comfortable SNES gamepads, and even a PS/2 keyboard connector. There’s even been talk of including an FPGA core for support of Atari 2600 games, much like the original ColecoVision’s Expansion Module 1 adapter for Atari 2600 games.

This is a dream system, and considering that, its price tag of $200 is very reasonable. Compared to the RetroUSB AVS system and the Analog Super NT, the Phoenix will fill a nice in retrogame preservation and it deserves to make its crowdfunding goal of $230,000.

To hit this goal, CollectorVision will need about 1000 backers to sign up. The kickstarter campaign is off to a somewhat slow start, however — three days into the campaign, they’ve only managed to secure $28,000 in pledges. Usually, a system like this would be fully funded in the first day, or even the first hour of the crowdfunding campaign going live. If the campaign received steady contributions every day at the level they have for the first 3 days, they would make goal, but it’s most typical for kickstarters to get most of their funding on the first few days, and the last few days. So I’m worried that they will not hit their goal. 

Perhaps retro gamers are wary of crowdfunding for yet another modern retro game console. People enthusiastically backed Ouya to the tune of $8 million dollars several years ago, and the recent AtariBox/Atari VCS crowdfunding was also successful in reaching goal, but only made $3 million dollars amid serious doubts about the current company calling itself Atari’s capabilities to deliver on what it has promised, and alleged mis-representation of their prototype hardware.

I don’t have any insider knowledge of CollectorVision, but everything I have seen from them about the Phoenix looks good, and I have faith that they care capable of delivering on their promises, if they can make their fundraising goal. Their hardware really exists, and all they need is capital for manufacturing. If you have fond memories of the ColecoVision and the early-80’s era of videogames, definitely check out the project, and consider becoming a backer.

GameMaker Tutorial: Configuration system

Many games have options or settings that are configurable.  The specifics can vary widely, from graphics options to music and sound effects volume to to input configuration to in-game options such as difficulty level and which rules are enabled/disabled.

This article will cover how to create a basic configuration system, using external file i/o, ds_map, and json.

Define your configuration requirements

First, before you develop it, design the system. Things to consider:

  • What variables does your game have?
  • What variables would you like the user to be able to modify?
  • What are the upper and lower bounds that make sense, or are reasonable for an enjoyable game? What values will break the game?

A little planning, and you can quickly list out all the variables you’ll want to manage with the configuration system.

Not every variable in your project needs to be subject to customization. Decide what configuration options you want, and define the variables that will be needed to control them, and decide on your default values. 

That said, having an editable, external configuration file can be very valuable for testing and tweaking the game, as well as convenient for the player. By having an external config file, you can modify game constants and variables without having to re-build the project each time. Since building the project takes time, being able to avoid building the game each time you want to test a variable can potentially save you time — for larger projects, potentially minutes per build.

Storing the config externally will also enable a tester to play around with the game variables without the need for the tester to be a programmer, or have GameMaker Studio installed. They can simply edit the config file, save it, and run the game again.

Nobody said that you must create a UI in the game program that can access every variable that you store in the config file. So, your testers can play around with configuration in a text editor, while your will eventually include a configuration UI for the game, to be used by players, and accessed through a title screen menu or a pause menu. This UI only needs to expose those configurable options that you think it should, or can have a secret mode that exposes more (or all) of them.

The default configuration should be safe to run on all devices the game is intended to run on, and should have the “standard” or “recommended” settings for the best or recommended game experience. 

Having defaults is important in case the external config file is missing or corrupted, and needs to be regenerated.  Create a ds_map called defaults, and use it to store all the default values.

Coding the config system

Coding a simple config system is actually very easy.

First, define variables to store the default configuration and the actual configuration, and create ds_maps for them.  The best time to create these ds_maps is immediately on launch, as soon as the program starts.  You may want to make these global variables, so that they will be accessible anywhere and will persist for the entire runtime.

global.defaults = ds_map_create();
global.config  = ds_map_create();

Of course, when we are about to exit the game, we will need to remember to destroy these data structures, to properly free up the RAM:

ds_map_destroy(global.defaults);
ds_map_destroy(global.config);

Next, initialize the defaults ds_map with all the variables that are part of the configuration, and their default values. It’s easiest to learn the shortcode for accessing ds_map values:

defaults[? "key"] = value;

In the code above, “key” is the name of your variable, in quotes, as a string. The value is the literal value of the variable.

So you can do this:

global.defaults[? "starting_lives"] = 3;

or

global.defaults[? "starting_lives"] = default_starting_lives;

As you can see, the ds_map’s key indexing allows you to choose meaningful names for the keys, which makes it easy to recall them later.

When you apply the configuration to the variables in your project, assign the value from the ds_map, like this:

variable = config[? "key"];
starting_lives = config[? "starting_lives"];

Once you have your ds_map populated with your configuration data, it’s time to write it to disk.  This is will save the file so that the configuration state can be read and applied to the game state the next time the program runs.

The gml function json_encode() makes it very easy to write the ds_map to a file, by converting the ds_map into json, or JavaScript Object Notation, which is just a commonly used data format, and can be thought of as a specially formatted string. You don’t need to know anything about the syntax of json in order to use the encoding/decoding functions — GML handles this for you.

Create a json-encoded string version of the config ds_map:

config_string = json_encode(global.config);

Check to see if an external config file exists already, and if not, create it and fill it with the default configuration:

if !file_exists(working_directory + "config.json")
{
config_file = file_text_open_write(working_directory + "config.json");
file_text_write(config_file, defaults_string);
file_text_close(config_file);
}

If the config file already exists:

  1. read the content of the file into a string variable,
  2. decode the json string to convert it back into a ds_map,
  3. validate the data in the ds_map, and,
  4. if valid, apply the configuration data to the game variables.
//First read the json data out of the config file
config_file = file_text_open_read(working_directory + "config.json");
config_json = file_text_read_string(config_file);
file_text_close(config_file);

//Next, decode the json, converting it to a ds_map
global.config = json_decode(config_json);

//Now, validate the configuration data to verify the settings are good
if !config_validate(global.config) //config_validate is a script that you wrote to validate your custom configuration data.
{
   //if we failed validation, destroy the config and create a good copy using defaults. 
   ds_map_destroy(global.config);
   config = ds_map_copy(global.default);

   //(Or, alternately, just correct the specific variables that were invalid, leaving any valid non-default values intact. This is more work for the programmer, but more convenient for the user.)
}

[...]

//apply data stored in global.config to the variables in your project as needed, where and when appropriate.
configurable_game_variable = config[? "key"];

The exact details will vary depending on your project, but the above is a good example to follow to get  you started.

Implementation: Data and File I/O

It might help to explain the above, in plain English, without the code examples getting in the way.

When the game runs, the very first thing the program should do is check to see if a configuration file exists.   If it exists, we read the data out of the file using file_text_string_read(fileid) and convert the string to Javascript Object Notation (JSON) with json_decode(string).  This returns a ds_map of key:value pairs that contain all the configuration data. If the config file does not exist, then we create it, populating it with our default data values.

If the config file exists, but contains invalid data, then we restore the invalid data using defaults.

Once we’ve successfully read data out of our config file, we need to validate the configuration data that we read from the file in order to ensure that the game is being run with sensible values that won’t result in the game crashing or glitching. If the configuration data is invalid, depending on the setting and the value, the game not work properly, and may crash, or may perform unexpectedly, or break. 

How the invalid data got into the configuration, you’ll want to investigate and fix, if the program was at fault. Your program may have written the data incorrectly, or it might have a bug that results in a corrupted file, or you may have read the wrong value out of the file, and those are all errors that you would need to debug and fix.

But it’s also possible that the user may find the file and manually edit it, make a mistake, and thereby introduce errors.  So check each value in the configuration ds_map, and verify that it is valid by checking to see if the key was found in the configuration file, that its value is of the correct data type (string, number, or boolean), and that it is within the range of acceptable values for that variable. However the bad data got there, your program will need to handle it and correct it.  Write a script that does this, according to the particular needs of your game.

If validation fails, whether because the file is missing, or because one of the values found within it is incorrect, we can handle this in several ways.  One way is to reset all values back to their default values. Another way is to correct just the bad value, on a per-setting basis, restoring the invalid value back to the default value.  Or we can simply display an error message to the player and exit the program. Decide what is best for your project, and implement it that way.

Usually, I recommend checking whether the file exists, and if not, regenerate it using defaults, and if it exists, restore individual settings to default one by one if there is an invalid value, rather than resetting the entire configuration back to the defaults if any of the values is invalid.  This way, a small error in the config file doesn’t blow out all the settings, and program will leave any valid customized settings alone, so that the user will only need to correct the values that were reset to default.

If we have a valid configuration, the next step is to apply those values to the game variables. We do this by assigning values to variables in the objects that use them, and the values we assign are copied out of the config ds_map, so that they are local to the owning object, and can be modified during the lifetime of the object without altering the configuration data.

Once the game variables have been set, the game is now ready to run.

Where did that file get written to?

While you’re developing the game, you might want to know where GameMaker is writing the files, in case you want to open them with a text editor and double-check that they’re being written correctly, or if you want to edit them. If you’re running the game through the IDE, the location may be trickier to find than if you built an executable and installed it. For help in finding the location of the writeable directory for your project, see this article.

Editing the configuration

One great thing about storing the configuration data in an external file is, we no longer need to re-compile the game every time we wish to tweak the settings.  This can greatly speed up testing, as compilation can take a minute or more each time, and this rapidly adds up when  you’re quitting, coding, re-launching again and again as you develop. So use the configuration system as  you test your game design.

We can edit the configuration in various ways.

The simplest to develop is to develop nothing; just rely on the user to find the configuration file on disk, open it up with a text editor, and change values, save the file, and run the game again.  You’ll find the writeable working directory for your game somewhere inside of %appdata% in a Windows build, but if you’re building the project for other platforms, you’ll need to find it.

While this is the easiest approach, this isn’t the most user friendly solution. A better user experience would be to put a GUI in the game to change the settings, and let the game program edit the config file.  This will be safer for the user, as you can constrain the input and check it for valid values before saving the config file.

The downside is that this can take a lot of extra work to build the user interface. Sadly, GameMaker does not provide a library of user input controls, such as buttons, checkboxes, text boxes, sliders, and so on. So to build the UI, we first have to build these controls.

This is a great opportunity for beginner programmers to get some experience designing and programming their own controls.  But it’s also a time-consuming task, and can be a frustrating challenge for a newbie programmer to figure out how to make a collection of robust, bug-free UI controls that are easy to use, work together, and behave in a way that the user expects based on their experience using other software. And doing this takes time away from developing the game part of the project.

It’s a lot of work, so having an easy way out is a good thing. There are assets available through GameMaker marketplace, which can be purchased for a few dollars, and provide the needed functionality. Either way, it’s good to have a set of reusable controls that you can put into any project, so whether you buy some, or you decide to make your own, you can get a lot of value out of them.

Advanced concerns

Storing arrays, ds_structures inside json

Up until now, the examples I’ve given have all been simple data types.  If you want to store something else, like an array, or a data structure, or graphics data, it gets more complicated.  This article is just an intro level tutorial, so it won’t cover these advanced topics.  But I expect I may cover them in the future, at some point.  Many games will not need the advanced techniques to store the basic configuration data.

Applying config to application state

Certain configuration changes, such as display size settings, will require the room or game to be restarted before they take effect.  In such case, you may need to use game_restart() or room_restart(). If you are confident that the data is being applied correctly to update the game variables, but you’re not seeing the change, try a room restart and see if the changes take effect.

But any room or game restart will restart the game in progress, and that may not be what you want to happen at all!  If you have a game where you can change the configuration from the Pause screen, for example, you will not want to disrupt the running game.  In that case, you’ll need to go further and handle this in some way, such as:

  1. Display a message to the user saying that the changes will take effect after they quit and relaunch the game.
  2. Give the play the option save the present game-state and then restore it with the new configuration in effect.

Details on exactly how to do this will vary considerably depending on your game’s design, but if you need to do this, you’ll essentially be building a save state feature for your game, and then calling it to save and then restore the game after the restart.

The basic logical flow of this process is as follows:

If <config change will require restart> and <game is in progress>{ save game-state to external file; restart;}

On re-start, check for existence of a game-state file, and if it exists, clear the room of default starting instances; restore room from game-state; then delete the game-state file.

This sounds fairly straightforward and simple, and, in concept at least, it is.  The difficulty is with storing all of the instances and their state data. Depending on the game, you may have hundreds of instances, and each instance may have a lot of data, and all of it needs to be written to file, then read back out of file, in order to reconstruct the game in the state where it left off.

Making it tamper resistant

You may welcome the user tinkering with the config file, or you may want to protect the config file against unwanted tampering. Usually this isn’t critical for a config file, but for a save file or a high scores file, it might be important to prevent cheating. If your game uses password-protected user accounts, or stores any kind of financial data or purchase records, you should be storing that data securely.

This should be all you need. I won’t get into technical detail here, but will outline a few tools you can make use of.

  1. Use ds_map_secure_save() and ds_map_secure_load() to securely store the configuration data in an encrypted file. The encrypted file will not be editable by a curious user. The manual doesn’t give detail about what encryption is used.  Depending on how serious you are about protecting the data, you will want to research encryption and use an algorithm that hasn’t been broken. Don’t attempt to invent your own encryption.
  2. Create a cryptographic hash of the configuration data string, and store the hash with the file.  When you read the file, re-hash the data you read out of the file, and verify that the hashes match.  If they don’t, something has changed, and you know the file has been tampered with or corrupted.  In this case, you should re-generate the entire config file from defaults. 

    Look at GML’s md5 functions to get started.  GML also provides sha1 hashing for this purpose. MD5 hashes are no longer considered secure, and sha1 is also no longer considered secure, but may be “good enough” for non-critical needs. While not “hacker proof” they will prevent casual tinkerers from being able to modify the data.

Saving external data for other purposes

Now that we know how to store data in an external file, retrieve it, validate it, and use it at runtime, there are other applications we can use these techniques for. 

The most obvious one that comes to mind is save states.  I’ve already touched on this above, in brief.  Other ideas include:

  1. High score, leaderboard, and achievement data.
  2. Telemetry data for debugging or analytics.
  3. User profiles (to allow multiple users of the same machine to each have their own configuration and save file preference).
  4. Level Editors.
  5. Mod packs, to allow a community of players to make custom modifications to your game, such as level data, or other external resources like sprites and sound effects, etc.

As these features become more and more advanced and complicated, they’re really best left to professionals working on commercial projects.  But by following the approach described in this article to do a simple configuration system, you’ll have taken the first steps toward getting your skills up to that level.