[WIP] Ardu Valley - Harvest Moon / SDV clone


(Josh Goebel) #21

It really helps to know the assembler and disassemble the compiled code and see what the C compiled did. Once you know assembler and think in terms of that it’s really easy to see if there might be something faster or if the compiler is doing the smartest thing possible.

This is basically:

LOOP:
  Fetch
  Compare
  Condition jump

With some counter code for the for loop, etc… so pretty simple and hard to imagine a way of writing it much smaller (without dropping to assembly). With assembly you could probably optimize the fetch pipeline and make sure your loop counter is in a register (vs RAM). But first would be interesting to see the disassembly of what C is already doing. If you posted that that’d be interesting to look at.


(Gavin Atkin) #22

You wouldn’t need to store all of the data stored in EEPROM in RAM as well for a lot of those. Just use the EEPROM put and get functions.

How are you planning on storing your farm? What is it’s size?


#23

I posted a breakdown up higher there. But this is the synopsis of the farm. If I can get away with having the whole thing in RAM then I will because I can isolate read/write to one particular event in the game, which is nicer on the EEPROM.


(Gavin Atkin) #24

Oh I gotcha. Yeah, definitely a large EEPROM game. For variables not updated as frequently, like maybe affection or animal names, you could still store those purely in EEPROM. The saves could be a little out of sync, but since you’re going to be getting so close to the RAM cap it might be worth it.


#25

Actually it’s not a bad idea at all! EEPROM reads are not a problem right? I am sure there are people who can educate fully on this but i believe reads are fine. So storing names in EEPROM is a massive space saver (the dang things are 8 bytes!) and they rarely change.


#26

Adventures in coding smaller functions

So, I wanted to write a function that can generate random names. I’m not sure if this will make it into the final game (It will definitely be on the chopping block if things get tough) but anyway, here are some fun results.

Cut one. This is a simple unrolled loop, it generates a word that looks like ‘Devosuc’ or ‘Xibanem’.
This one gives me a total progmem usage of 12696. fair enough.

void randomiseInbuffer() {
  const char vowels [] = "aeiou";

  text_input->inbuffer[0] = 65 + (rand()%26); 
    text_input->inbuffer[1] = vowels[rand()%5]; 
    text_input->inbuffer[2] = 97 + (rand()%26); 
    text_input->inbuffer[3] = vowels[rand()%5]; 
    text_input->inbuffer[4] = 97 + (rand()%26); 
    text_input->inbuffer[5] = vowels[rand()%5];
    text_input->inbuffer[6] = 97 + (rand()%26);
  }

I thought loop unrolling was normally more efficient (well, faster, maybe not more efficient), however I think the amount of code for the loop is eclipsed by the extra calls to rand, array dereferences etc. This seems to be born out by the following optimisation. This clocks in at 12600 (note, the function is called a bunch of times, so don’t try to work out the exact opcodes, its for fun and testing only).

void randomiseInbuffer() {
  const char vowels [] = "aeiou";

  for(uint8_t iter=0; iter<7; iter++) {
      text_input->inbuffer[iter] = iter==0 ? 65 + (rand()%26) : iter%2==0 ? vowels[rand()%5] : 97 + (rand()%26); 
  }

}  

Not bad, thats a decent saving. 96 bytes, thats a lot of sprites!

Now for the tricky bit. I would have thought the compiler would have sorted this one out for me anyway. Hopefully some of the more learned players here can explain this. The following clocks in at 12538.

void randomiseInbuffer() {
  
  for(uint8_t iter=0; iter<7; iter++) {
      text_input->inbuffer[iter] = iter==0 ? 65 + (rand()%26) : iter%2==0 ? "aeiou"[rand()%5] : 97 + (rand()%26); 
  }
  
}

The only difference being I have replaced the reference to the const string “aeiou” with it directly in the code. Yet this saves 72 bytes on the previous one, and puts it at nearly 150 bytes saved on the first attempt. Truly, I have much to learn about writing lean and mean code on the Arduboy.

For now though, the results are fun. I shall forge on with the following random details.
Player: Zhakife
Farm: Iwiianu
Horse: Dieqave
Dog: Churobe (This looks like a japanese word, I checked my dictionary though and I don’t think it is)


(Scott) #27

Correct, you can read from EEPROM as often and a many times as you like, without any problems. Only the number of times that EEPROM can be written is limited.

With writes, each location can be written a minimum of 100000 times. How many times you can write past that limit, without failure, is not guaranteed.


(Kevin) #28

The data sheet says don’t do more than 10,000 writes but in practice it takes more than a million to kill EEPROM. So really as long as you aren’t using it in any loop, you’re probably fine with using the memory.

The mapping and how to make it play nice with other games begins to be an issue.


#29

I will post an update video shortly. I have got the mechanics for walking around and entering/leaving buildings done. Also programmed up a nice little farm house. Up to 50% PROGMEM usage, but a bunch of that is re-usable drawing commands for common objects like windows, doors, beds, etc. Which I can also improve vastly using my procedural generation routines I am making.


#30

Never did post that Video,

Here are some slightly out of date shots to keep your appetites strong.

And here is the launch screen with animated intro.

Currently I have the house, barn, coop and farm navigable, with collision sorted out. Now adding in drawing the farmland. Still aggressively trying to keep below 60% PROGMEM usage to give myself plenty of margin. I’ve found a few neat tricks to this end. I will have to release my little procedural sprite generator for others to use, it can create some really nifty works of art for very little PROGMEM.


#31

I’ve found a good balance between procedurally generated structures and bitmaps. the procgen structures can be more complicated and detailed for the space they use, but they require rendering at runtime which uses up cycles. Too many on the screen and it slows down.

bitmaps I am using for anything relatively compact.

So far sitting at just under 60% usage still. Made plenty of progress. Does anyone know how to do screenshots using a mac?


#32

So, I always assumed floating point would be more intense on the arduboys program memory, but i didn’t realise just how bad it would be. The problem i faced was have a range of 0 to [5-15] (so it could be 0-5, 0-7, 0-12, 0-15, etc) and mapping an integer on that range to the value 0,1,2,3 depending on how far along the range it was. So 3 in the range 0-8 would map to 1.

I coded this up using floating point to get the percentage along the range then multiply by 3, which worked fine, but holy heck if it didn’t take up almost 3% of the PROGMEM for just a simple bit of work. I get there has to be conversions and switching and all that but damn!

So i rewrote it into a simple if/else using half and quarter sizes of the range and uint8 operands and boom, about 100 bytes all up. Now that i think about it i can probably use a reducing while loop to get it in less, but it’s fine for now.


#34

(Ash) #35

Absolutely awesome!

I can’t wait to give this a try, seriously impressive work!


#36

Feature update.

  • Backpack inventory (6 slots, upgradeable to 10)
  • Can open inventories and swap items between them and backpack.
  • can cycle through items to use.
  • Can till farmland.
  • Can water farmland.
  • Can plant crops in farmland.
  • If a plant is watered, it will grow each day.
  • Can sleep in bed to advance to next day.
  • icons for all basic items (Axe, Hoe, Water bucket, pail, shears, scythe, rod, shovel)
  • Icon for seeds.
  • Icons for 13 of the 15 crop items.

Up next - Harvesting items from mature crops and being able to eat/sell those items. I am hopeful I can sneak those operations in in under the 70% progmem usage. Then hopefully I can budget 5% for farm animals, 5% for misc farm stuff, 15% for map areas with NPC’s and 5% for dialogues. It’s going to be tight tight tight. Maybe a bit too tight.


(Kevin) #37

This is just off the charts


#38

I tweeted another update video, watch it, unless you are chicken :wink:

Currently hitting 72% progmemory.

Since last time

  • You can now harvest crops
  • Items now have names that show up in the inv screen.
  • Chickens, cows and sheep with associated animations now appear in their respective places.
  • Animals now move around and are bounded

(Boti Kis) #39

This is beautiful. Wonder how you guys manage to get your code so small… couldn’t even get a battleship clone under 28k :'D


(Mike McRoberts) #40

Battleship would easily fit in 2.5k


#41

One of the first games I ever tried to program was battleship, on an old radio shack BASIC interpreter that you had to plug into the television. Nostalgia