Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/17/2014 in all areas

  1. Tanks now launch Homing Missiles changeable wall color menu is back lots of ROM savings Menu's back in place. All options should be functional, so let me know if something doesn't work as expected. A couple Tanks launched Homing Missiles. They're shaped differently than the normal shots. The menu option sets the number of redirects each Homing Missile can make. Values range from 0-3 (0=no redirect). The "remove brick" routine needs to be updated to cope with the homing missiles. If it lines up with 2 bricks it only takes 1 out. If the tank keeps shooting, the same brick is taken out so the tank won't be able to create an opening it can shoot thru. The wall color used to be hard coded. I've seen purple and red walls in Frenzy, so I've added the ability for the C code to control the wall color. At the moment it only uses blue for Berzerk and purple for Frenzy. Found over 800 bytes worth of savings! First savings was 172 bytes by changing how I divide by 5 for dealing with the playfield pixels (each "brick" is 5 scanlines tall). The ARM supports multiplication, but not division, so I had been using a 185 byte table. const unsigned char div_5[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,... 35, 35, 35, 35, 35, 36, 36, 36, 36, 36 }; if (y < 36*5) y5 = div_5[y]; else y5 = 36; Omegamatrix's first(!) blog entry referenced reciprocal multiplication which is basically using x * 0.2 to get the result. We only have integers, so we use an implied decimal point like when doing subpixel positioning. #define DIV_BY_5 0xCCCD #define DIV_BY_5_SHIFT 18 y5 = (y * DIV_BY_5) >> DIV_BY_5_SHIFT; My next find was spotting this in the "player shoots" routine: switch (direction) { case 0: gMissileX[0] = gSpriteX[0] + 7; gMissileY[0] = gSpriteY[0] + 3; gMissileControl[0] |= 0; break; case 1: gMissileX[0] = gSpriteX[0] + 6; gMissileY[0] = gSpriteY[0] + 9; gMissileControl[0] |= 1; break; case 2: gMissileX[0] = gSpriteX[0] + 3; gMissileY[0] = gSpriteY[0] + 16; gMissileControl[0] |= 2; break; case 3: gMissileX[0] = gSpriteX[0] - 3; gMissileY[0] = gSpriteY[0] + 9; gMissileControl[0] |= 1; break; case 4: gMissileX[0] = gSpriteX[0] - 4; gMissileY[0] = gSpriteY[0] + 3; gMissileControl[0] |= 0; break; case 5: gMissileX[0] = gSpriteX[0] - 4; gMissileY[0] = gSpriteY[0] + 1; gMissileControl[0] |= 1; break; case 6: gMissileX[0] = gSpriteX[0] + 3; gMissileY[0] = gSpriteY[0] - 5; gMissileControl[0] |= 2; break; case 7: gMissileX[0] = gSpriteX[0] + 7; gMissileY[0] = gSpriteY[0] + 1; gMissileControl[0] |= 1; break; default: break; } and realizing I could change it (and the corresponding "robot/tank shoots") to use a few tables: const signed char missile_x_offset[] = { 7, 6, 3,-1,-4,-2, 3, 7, // humanoid 7, 6, 3, 0,-4, 0, 3, 7 // robot and tank }; const signed char missile_y_offset[] = { 3, 9,16, 9, 3, 1,-5, 1, // humanoid 6,13,13,13, 6,-3,-4,-3, // robot and tank }; const char missile_shape[] = { 0, 1, 2, 1, 0, 1, 2, 1 // humanoid and robot (tank is always 3) }; ... gMissileX[i] = gSpriteX[0] + missile_x_offset[direction]; gMissileY[i] = gSpriteY[0] + missile_y_offset[direction]; gMissileControl[i] |= missile_shape[direction]; That saved 188 bytes. I bet it's also faster. The next was realizing I had similar switch/case logic for the humanoid movement: switch (direction) { case 0: gSpriteX[0]++; break; case 1: gSpriteX[0]++; gSpriteY[0]++; break; case 2: gSpriteY[0]++; break; case 3: gSpriteX[0]--; gSpriteY[0]++; break; case 4: gSpriteX[0]--; break; case 5: gSpriteX[0]--; gSpriteY[0]--; break; case 6: gSpriteY[0]--; break; case 7: gSpriteX[0]++; gSpriteY[0]--; break; default: break; } And changed it to this: const signed char dir_x[] = { 1, 1, 0,-1,-1,-1, 0, 1 }; const signed char dir_y[] = { 0, 1, 1, 1, 0,-1,-1,-1 }; ... gSpriteX[0] += dir_x[direction]; gSpriteY[0] += dir_y[direction]; The same logic was used for moving Otto, the robots, shots, and doing tests of "can the robot safely move here". I changed all of those to use the tables for 376 bytes of savings. Finally, when I added back the menu I decided to make the Continue feature always enabled. Removing the menu logic saved another 68 bytes. Note: the continue feature has not been added back yet. Controls RESET = start game SELECT = return to menu Right Difficulty, Test Mode*: B = Off, A = On * Test Mode is infinite lives and max robots. Score will be red when active. ROM frantic20140215.bin Source Frantic20140215.zip
    1 point
  2. Daniel Everett, a linguist who studied the Piraha - a small tribe of hunter-gatherers in Brazil - reported that while the Piraha know of food preservation techniques, they don't actually preserve any food for their own use. Instead, tribe members immediately share and consume their catch with the rest of the tribe, as a sort of gift economy. Preserved food isn't needed because at any one time, one of the tribe is sharing their bounty. As one of them explained, "I store meat in the belly of my brother". You're probably wondering what the heck all of this has to do with 7800basic. I've been recently reminded that our retro development community has a similar economy of good will. Instead of hoarding some new technique or tool, developers openly share their discovery. Help received is paid forward in the forums. Those that can't code, test builds, create art, and offer advice. 7800basic hasn't been released yet, but already I've been receiving help. batari gifted his source code to the project. Eric Ball loaned me his irreplaceable CC2 so I could test 7800basic on real hardware. Bruce Tomlin gifted his sign7800 program. CPUWIZ assisted with bankswitching questions. None of these guys benefit directly from 7800basic being created, but they've openly shared what they can to make it a reality. I can't help but reflect on how cool it is to be a part of this tribe. -- The title of the entry says "update", so I guess I should give a quick update on 7800basic progress. This week I finished the first pass of documentation, added a built-in (optional) pause-button handler, and wrote the bankswitch code. The elephant in the room that I've been ignoring until now is graphical ROM layout. I'm using DMA holes to avoid having to pad graphics with a bunch of zero bytes. This works great, but any time there are two or more graphic blocks in a ROM it makes it tricky to fill the hole between them in a useful and easy way. (keep the jokes clean, folks) My first pass at a solution for using this space will probably be to take any "alphadata" character display data and throw it into any holes. This is low-hanging fruit because it can easily be measured before the resulting assembly code is sent to dasm, so I don't have to worry about overflowing the hole. The downside is, unless your game has a ton of character data the holes probably won't be 100% used. I'm kicking around some ideas that would allow the basic coder to stick routines and regular data in holes, but none of them are likely to make it into the code before the beta release. Which is a nice segue for the next bit of info. At the current rate of progress the beta release should be ready in weeks, not months, and I'm already looking forward to seeing what you guys do with it.
    1 point
  3. The good news is that I don't want to make any bullet hell games. Here's two of the things on my mind: I'd like to make an adventure game that uses controlled randomness to create semi-random terrain and a platform adventure game that will use controlled randomness to create semi-randomly placed platforms.
    1 point
  4. Bob's games are like the Platonic solids. We will try to strive for our programs to be in the perfect form like Bob's games but never quite getting there exactly. Allan
    1 point
  5. I kept hitting the like button but it only let me 'like' once which is me saying I like this very much. A thousand thumbs up. Allan
    1 point
×
×
  • Create New...