Log In  


Cart #djclem_helimenu-8 | 2022-08-10 | Code ▽ | Embed ▽ | No License
2

Things you may find interesting about this cart set:

Sound Effects

The helicopter rotor sound consists of these four notes:

They play in a loop, and as helicopter throttle and rotor "pitch" change, poke commands are used to alter the speed and tone of the notes:

 if heli_sound==10 then  -- SFX 10 is the continuous rotor sound
  -- deltax is used to determine how much
  -- rotor 'slap' to add
  local deltax=heli_xspdtgt-heli.xspd

  -- rotor slap changes the volume
  -- of the two notes (noise)
  -- the more tilt the heli has,
  -- the more pronounced the 'slap' is
  local rotorslap=({[0]=0x53,0x53,0x55,0x57,0x59})[abs(heli.tilt)]

  -- if the helicopter is trying to reverse,
  -- then make the rotor slap the most pronounced
  if sgn(heli_xspdtgt) != sgn(heli.xspd) then
    rotorslap=0x5b
  end

  sfxo=stat(50)
  if sfxo==0 or sfxo==2 then
    chgit=true
    -- i only want to change the 
    -- volume of the two noise
    -- notes only if the "silent"
    -- notes are being played.
    -- otherwise it sounds glitchy
  end

  if chgit and peek(0x34a9)!=rotorslap then
    poke(0x34a9,rotorslap)
    poke(0x34ad,rotorslap)
    -- these poke addresses are
    -- presently hard-coded to
    -- work on sfx(10)
  end

  if peek(0x34e9)!=rotorspd then
    sfxo=stat(50)
    if sfxo==0 then
      poke(0x34e9,flr(rotorspd))
      -- this changes the playback
      -- speed of the sfx on ch 0
      -- only change the speed at 
      -- first note, to help reduce
      -- glitchy sounds

      -- this poke address is
      -- presently hard-coded to
      -- work on sfx(10)
    end
  end
end  

Multi-Cart

This game makes use of two carts: A menu cart, and the gameplay cart. If you aren't familiar with cart-chaining, here is a simple demo along with the .P8 source code.

Anyway, the two carts call each other back-and-forth, and communicate using CARTDATA. The Cartdata is located at memory location 0x5E00 - 0x5EFF. Note that you may access this memory area using PEEK and POKE, in addition to DGET and DSET, respectively. I use a mix of both methods... I use DGET/DSET to store about 10 numbers (using indices 0-9), and then I also store byte-data, justified at the top of the Cartdata memory region, starting at the highest location of 0x5EFF and works downwards. Memory Map

Another thing the menu cart does is draw two graphic assets, and passes them via memory to the gameplay cart. Below is an example of the dashboard when you crash:

This was generated using code, but the token count was a little high, and I was looking to remove tokens from the gameplay cart. So I moved the code to draw this broken dashboard into the menu cart. When the menu cart starts, it draws the broken dashboard (but does not FLIP(), so you don't see this part), then copies it to memory location 0x8000. When the menu cart launches the gameplay cart, a formally-undocumented but known feature is that this region of memory stays intact when loading other cartridges. So the gameplay cart now has this graphic asset located at the same 0x8000 memory location. To draw this broken dash during gameplay I just perform a memory copy:
memcpy(30976,0x8000,1792).

Image Compression

I use the PX9 Data Compression Utility to store more graphic assets than would normally fit into a Pico-8 cartridge. The menu cart has the largest image storage requirements, so the discussion below refers to the menu cart:

I have about 4 carts worth of sprite/image data used in the menu cartridge. I wrote a utility cart that contains the PX9 compression routine, and one-by-one, RELOADs the spritesheet from each of these carts, compresses the individual images in turn, and stores them in memory starting at 0x2000 (the non-shared map region - see memory layout below). The compressed images take up more space than is available in the map area, and it actually spills over into the Sprite Flags, Music and into the Sound effects memory regions. I do not use any Sprite Flags, and do not have any Music scores, so giving up these locations for compressed image storage is a good tradeoff. I do use sound effects, so what I did is moved all my sound effects to the top of the SFX memory area [SFX(63)] and worked downwards in memory. My sound effects use locations 52-63. The compressed data goes up to about SFX slot #8, so there is room for me to add more SFX or more compressed images, and still have room.

Start   End     Purpose
0x0     0x0fff	Sprite sheet (0-127)*
0x1000  0x1fff	Sprite sheet (128-255)* / Map (rows 32-63) (shared)
0x2000  0x2fff	Map (rows 0-31)
0x3000  0x30ff	Sprite flags
0x3100  0x31ff	Music
0x3200  0x42ff	Sound effects

The compressed image data uses 5,127 bytes. Therefore the compressed image data is contained in the memory region 0x2000-0x3407

2



[Please log in to post a comment]