Hi, thank you everyone for the input.
Just to confirm: Yes, the top line is intentional. It doesnt renderI do this in my games for two reasons.
First is
just like tokumaru has statedSecond is to actually incentivize emulator developers to improve their emulation.
You can read a bit of discussion regarding this in
Cowlitz 2 topic.
Did anyone beat the game yet? Im happy with how the ending turned out, Mtee and Chip Jockey surpassed my expectations
As Mtee mentioned, we spend last days compressing stuff.
At some point, we run out of space to both finish Ending and Polish text translation. We decided compress the maps.
At first, I considered going from 2x2 MetaTiles to 4x4(2x2) MetaTiles, but quickly dismissed it give how many different ones would be introduceds in later stages.
Next, I turned my attention towards a method I used waaay back in
Inversion, the
Object based compression.
After assessing some later lavels, though, I gave up on it as it wouldnt be as effective as I hoped for.
Finally, I decided to use variable bit compression.
Quote:
Map starts with 8bit RAM offset for starting location.
The stream starts with a 2 "control" bits.
0-move with bits. Read bits to move in given direction. Next 3 bits for tile ID, more 5 bits is amount of moves.
1-small move with bits. 3 for tile and 3 for amount of moves
2-Sets Exit MT on player position. Proceeds to literal draw.
3-Carrot mode. EOR a carrot flag. This flag always starts as 0. Code fetches next control bits.
Once game finishes command 0 or 1, game will start asking for movement. Each move is 2 bits.
0-up
1-down
2-left
3-right
Once all move bits are processed, another 2 "control" bits will be given.
If code lands on tile 1F, it will replace it with currently selected MT.
If code lands on tile 0x1,0x2,0x4,0x5,0x7,0x8 it will be upgraded to higher level.
If Stair MT is selected, the MT id to be placed will include direction offset, allowing for some bit savings.
This will continue until amount of movement ends.
If Conveyor tile is selected, It makes a mini loop similiar to mode 0\1.
After amount of moves in given mode, game also expects 2 extra bits for direction in which place first Tile.
Later on the order of moving pointer and placing tile on map is reversed in the code.
The code still fetches directions as normal.
If Teleporter is selected, the amount of moves is not asked for. Instead a 8bit offset is asked.
After which, selected mode restarts.
if 8bit ofset is equal to 255, extra 4 bits will be asked.
These 4 bits will be interpreted as delay. 64 frames for single value.
These are for playing the solution and will indicate a number of frames to wait in between the moves.
This 255 offset will also *not* place a teleporter on the map.
Note: Carrot mode is turned off when control bits are fetched.
Note: Mixing 1, Explosive and Regen tiles is possible(no need to change type is tile was already placed)
Meaning, crossing regen tile while with 1 tile will upgrade regen instead of replacing.
;literal draw;
In this mode, game assumes you finished placing tiles normally.
All left are tiles that Grunio cant reach. Like ones destroyed by explosions.
Code intereprets bit stream in following manner:
6 bits - tile to place
3 bits - how many of them put on the map
8*repetition bits - map offset to put selected tile on.
Once all tiles of given id are placed, code rolls back to 6 bits for tile.
If tile ID is 0x3F, map loading is finished.
Some maps would ask too many Bytes to pathc in literal mode.
If tile ID is 0x3E, code shall ask for 8bit value for map offset and then jump to control code interpretation.
;Saving on bits;
Our MT table has 0x42 MTs. This means we need 7 bits to access all of them.
-To cut on this, we can limit our selection by MTs that are used for welldone screen.
Doing so saves us 1 bit.
-On entire 0x1X line is not required. If we create an ID list in ROM, with which we can reference
our true MT IDs,we can limit our selection to 0x1F MTs max.
Doing so saves us another 1 bit.
-If we use only 0x0F as exit, we are only 6 tiles shy of saving another bit.
If we make the code to actually upgrade tiles(when possible) instead of just placing them,
we can cut lv2 and lv3 versions of upgradeable tiles.
This allows us to place remaining 6 tiles in their place.
And so, another 1 bit was saved.
You could also remove Exit and Start points, but it has no benefit....or does it?
The ROM table should look like this:
0x01,0x04,0x07 ;These are upgradeable. Normal, Explosion and Regen
0x00,0x28,0x29 ;Stool, Start point and Carrot box
0x24,0x25,0x26,0x27 ;Stairs. Up down left right
0x0a,0x0b,0x0c,0x0d ;conveyors. up down left right
0x0e,0x0f ;teleporter and exit
-Now, we have 16 Tiles to choose from. At first, cutting down to 7 seems impossible but let us try...
We can remove Start tile(0x28) for free since its placed only at start of the level.
We can also remove (0x0F) tile as it is placed only once at end of the map.
This cuts us to 14 tiles...which doesnt saves us a 1 bit yet.
-By observing Stair tiles, we can notice that they always have to be placed in same direction to where player is moving.
If we make a control MT for Stairs instead of having all 4, we can offset correct MT by using the movement direction.
That shaves off 3 MT from our table....and shortens map bit stream a little.
-Same logic as above can be applied to Conveyor belts(with small exception, see above).
That saves another 3 MT from table.
With that, our table can be 8 MTs long, and thus can be adressed with 3 bits only.
The ROM table looks like this:
0x01,0x04,0x07 ;Its important to have upgradeables first, to make code bit easier and faster.
0x00,0x29 ;cant be upgraded, are not "special" cases.
0x24,0x0a ;special numbers for Stairs and Conveyors
0x0e ;teleporter
The great thing about this is that we also got "free" map solution reading(which would not be in game otherwise!)....so when Dzidzia is giving you a solution to the map, it reads back actual map data.
But later on we run out of space. Again.
Text was compressed with
dictionary compression.
I decided to combine it with bit stream.
This one was much simpler...and I did go for bit stream compression again.
While our font is less than 64 symbols, we still have to use 6 bits to represent a single symbol. That is good, but it could be better.
First, I created two sets of symbol tables. One with very common symbols and other with less common ones. This allowed us to reduce symbol size to 5 bits.
Then, when a symbol is pulled from bit stream, it is compared to one of special cases:
Quote:
0x1F End of stream
0x1E Newline
0x1D Swap symbol table
0x1C Pull a word from dictionary
Up to 64 words. Pulls next 6bits from bitstream as ID of the word in dictionary.
This saved a good chunk of ROM too.