Tiny-FPGA-BX-Game-SoC Pacman


#1

My Pacman game is coming along - here are the intro screens:

https://www.youtube.com/watch?v=cQ5IzM8N2UQ


#2

:heart_eyes: Looking great there Lawrie!!! Fantastic work!! :smiley:


#3

Are you doing anything that might help me add sound effects to it?


#4

Are you doing anything that might help me add sound effects to it?

Sadly, the short answer is I don’t have anything ready to go at the moment. I’ve thought about it, and I started down the path of looking into what would be required to generate some of the sound effects from pacman, and I also started out scaffolding up a ReactJS web app that I was going to turn into a tracker/fx editor, but quite quickly realised that this was going to be quite a big undertaking.

My idea for adding “SFX” support into the current player routine was simply to provide a way of injecting a “bar” of music into a specific channel, outside of the normal player routine. That bar of music could constitute a sound effect.

I thought we could use channels 1-3 for music, and 4 for playing the sound effects for example. With a simple call to song player like “trigger_soundeffect(effect_number)” to use it.

In order to get the proper “pacman” style sounds though, the player is also going to have to support “effect” processing on the notes. For example, take the “pacman death” sound effect:

It’s made up of 6 separate notes that each have a portamento (pitch-slide) down effect followed by a portamento-up effect. You could probably achieve something similar with a single cycle of vibrato. Those notes are followed by a couple of notes that rapidly slide up in frequency; the “whup whup” at the end.

These portamento/slide effects will need to be added in to the player if we want to get useful sound effects working.

The up-shot of all of this? I’ve thought lots about it, but haven’t done much. I think I’ll probably work up updating the player routine first, to support some simple musical effects like vibrato, portamento, tremolo, arpeggio etc, and then put in some hooks for triggering specific bars as “sound effects”.

That’ll be enough to allow “manual/painful” editing of things, and I’ll think about the ease-of-use / tracker software a little later. :/.


#5

That sounds like a plan :grinning:


#6

Okay, so I’ve had a go at adding the bare minimum sound effect processing code to the play routine, and have added a couple of effects; one for pacman’s death, and one for when he eats a big pill. The code is in my repo, and I’ve attached some samples of the sound-fx below.

gateman_sounds.zip (29.4 KB)

So far it’s come together pretty much as I said above; channel 4 is now used for effects, while channels 1-3 are kept free for background music.

I’ve modified your code so that the sound effects are triggered at the appropriate times. I’ve also added some extra functions to the music player so that the music can be started/stopped as well (I now stop the music when the game is in action).

Regarding the sounds; It took a bit of time trying to reverse engineer what the pacman sounds were doing. I was using the snippets from here as a kind of reference: https://github.com/luciopanepinto/pacman/tree/master/sound and I was then using audacity to plot a spectrogram so I could figure out which notes were being played.

Like I said, I’ve only converted the two sound-fx so far because it’s a bit of a painful process.

The next week or so is going to be pretty hectic for me, so I’m not sure how much other stuff I’ll be able to do for a little while.

D.


#7

Thanks for that. I will try it out :grinning:


#8

I love the sound effects :grinning:

I have merged it back into my version as I had made some more changes.

The game is fairly complete now. It is not quite the same as Pacman as the joystick control is a bit different, the graphics aren’t quite as good because of the fewer colours and because I have fewer sprite images and bigger steps between drawing the sprites. And sprites are a single colour. Also the maze layout is different and a bit smaller and does not yet have the left-right wraparound. I am using 16x16 squares for the “board”, whereas the real Pacman uses 8x8 squares and the sprites overlap the edges a bit.

I probably need to improve the gameplay by making the ghosts faster, and changing more things as the stage increases. I have fewer fruit items than the real version. I don’t support 2-player mode.

I still have a few bugs but not the same ones as the original version.

I could get it much closer to the original apart from the constraints due to your video implementation, i.e 8 rather than 16 colurs and monochrome sprites.


#9

Here is is in auto-play mode, with sound effects.


#10

Hot off the press - I just added a waka-waka eating sound to my version too… :smiley:

Time for bed now :slight_smile:

Dave.


#11

I could get it much closer to the original apart from the constraints due to your video implementation, i.e 8 rather than 16 colurs and monochrome sprites.

I’ve been thinking about that a lot too. I think we can fit sprites with 2-bit colour and palettes like the original arcade machine in, even within the memory constraints we have. Funnily enough, I was looking into how the sprite RAM was being synthesized, and it seems to use the same amount of RAM if I choose 2bpp instead of 1 - I guess there’s some limitation with how the RAM’s are laid out or something.

I’d also love to have more colours available, and extending the texture map to have 256 8x8 textures would be awesome too. For VGA output, the hardware becomes a bit more complex. If we’re using the LCD driver maybe that doesn’t matter.

In any case, I didn’t want to go making any radical changes and breaking things while gateman was/is under active development!! :slight_smile:


#12

I have started looking at how good the Game SoC is for implementing side-scrolling platform games like Super Mario Bros.

Some thoughts:

  • It really needs the multi-colour sprites.
  • The tile memory would be better as 128 x 32 for these games.
  • A part of the screen at the top that does not scroll would be useful.
  • The 64 textures is a severe limitation for this type of game, particularly as quite a few of them need to be used as a font for the character data, score, etc.

A wonder is @gundy has any ideas.

Here is the current code:


#13

Cool! :slight_smile: Again, that looks great!

I’ve started down the path of adding multi-colour sprite support, but at the moment I’m having trouble getting things to route.

The approach I’ve taken is similar to the pacman arcade machine:

  • A global 16-colour palette that maps each entry to an 8-bit RRRGGGBB value.
  • A global 32-entry sub-palette that maps each of it’s 32-entries to 4 values from the palette above (each sprite or tile can contain 4 colours as defined by one of the sub-palette entries).
  • Modification of the per-sprite control register to use a palette selector rather than a direct colour number
  • Modification of sprite data to be 2-bits in width rather than 1
  • I’ve also added flipx and flipy bits to the sprite control registers to allow x/y flipping of sprites
  • Update to allow 256 8x8 textures
  • Modification of texture data to be 2-bits as well
  • Modify tile map size to 40x25 so it fits in 1000 bytes (2 BRAMS)
  • Addition of a “tile colour RAM” - so each tile location also has a corresponding sub-palette selector to choose the 4-colours that apply to the tile.

I’ve been thinking that with the scrolling, it might be better to do something similar to what the C64 does, and essentially allow pixel-by-pixel scrolling in a 0-7 range, but then also support double buffering… so you scroll from 0-7 and then flip to another off-screen buffer for the next pixel along. Hopefully the CPU/flash will be able to handle the 1,000 required writes to fill the double buffer fast enough before the flip is required.

I haven’t implemented the multiple buffers yet, so I haven’t had a chance to test these theories.

Like I said, I’m running into gate count issues, so I think I may need to figure out other ways of reducing the gate count to get things to fit. Or maybe get better at writing sympathetic verilog. :slight_smile:

If anyone has any ideas for things that we can do to shave off some gates or make things more efficient (preferably without losing too much functionality) I’m all ears :slight_smile:

D.


#14

Awesome results!

Maybe this could be a compile choice. Depending on the game that one wants to implement it could be:

  • 32x128 for vertical scroller
  • 128x32 for horizontal scroller
  • 64x64 for other types of games

Is the background wrapping around? I didn’t check. This is a must for scrolling.

I don’t know if I shared those videos yet, but these are great overviews of how this kind of hardware was designed:


#15

The problem with using wide or tall maps with higher colour bit-depth is running out of BRAM…

For example, here’s roughly how BRAM is allocated:

Usage # BRAMS Breakdown
CPU Registers 1 32-bits x 64 registers
CPU RAM 8 32-bits x 1024 words (32,768 bits)
Sprites 8 64 sprite definitions @ 16x16 resolution @ 2bpp (32,768 bits)
Texture memory 8 256 textures @ 8x8 resolution @ 2bpp (32,768 bits)

… so before we even get to tile (and tile colour) memory, we’ve already used 25/32 BRAMS, leaving at most 7 free.

Since tile memory needs to store an 8-bit value per position (we have 256 individual textures to choose from for each tile), it makes it easier to fit things in if we use a resolution like 40x25 (that fits cleanly in 8000 bits, or 2 BRAMS).

Tile colour memory needs to hold a palette index per tile position - the pac-man game allows for 64-palletes - so 6-bits per tile position, but ideally I’d like to trim this back to 16 so we can use exactly half the RAM for tile colour data that we do for the tiles themselves. Or 1 BRAM.

So, in theory, we could make 80x25 fit. Or 40x50. Or a simple 40x25. But pushing for much more than that is going to involve trade-offs in other areas. :confused:

D.


#16

Super interesting talks there! Thanks! :slight_smile:


#17

I think some work is needed on the screen mode. It seems to be upside down, horizontally mirrored and vertically stretched. I don’t have button input yet. It is in hardware.bin - I just need to solder wires to my buttons and write the C code.


#18

Yes, the videos were very informative.


#19

Yes, those are what hooked me to this kind of project. I made a software render engine afterwards: https://github.com/Fabien-Chouteau/GESTE :slight_smile:

The pixel pipeline of the gameboy is actually quite complex, and the tricks during h-blank mind-blowing.


#20

Hi @Fabien, I see you are in Hackaday today. As an Ada advocate, I hope you are celebrating Ada Lovelace day.