Skip to content

Reduce cycles and byte usage #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

zohassadar
Copy link
Collaborator

see commit notes

1. Orientation table split & reduced

    Previously the orientation table consisted of 12 byte runs, 1 for
    each orientation.  The 12 bytes consisted of the pattern Y offset,
    Tile index, Y offset. This group of 3 was repeated for each of the 4
    minos in a piece.

    The X/Y offsets have been changed to each have their own table
    consisting of 4 byte runs, 1 run for each orientation.  The 4 bytes
    are for each of the 4 minos in a piece.  This means the
    multiplication by 12 that was previously needed in
    tileModifierForCurrentPiece, isPositionValid and
    playState_lockTetrimino has been reduced to a multiplication by 4, a
    much simpler operation.

    The tiles are also in their own table but the data has been reduced
    by 1/4. The currentPiece value is used as-is for lookup into this
    table and stored in an aliased temp variable generalCounter5.

2.  Use table for Y * 10

    Previously the tetriminoY value (and its offsets) would be
    multiplied by 10 with shifting/adding.  Using multBy10Table was not
    an option as the Y value could be either -1 or -2.  By pinning
    multBy10Table to the beginning of a page and the two negative values
    at the end of the page, the table can be used for all potential
    values of Y (-2..=20).  Assert statements have been added to ensure
    that the tables remain where they should be.  The orientation tables
    and multiplication tables have been placed in between to make use of
    nearly the entire page.  The page alignment has the additional
    benefit of reducing cycle count due to no page boundary crossing.

3.  Recycle harddrop's ghost piece sprite staging

    The game checks for hard drop prior to the normal shift/rotate/drop.
    If the inputs are present for either a hard or sonic drop, the piece
    will end up where the ghost piece was staged in the previous frame.
    Saving this calculated Y value and reusing it in harddrop_tetrimino
    eliminates the redundant repeated calls to isPositionValid.

4.  Take advantage of negative bit in Tiles

    The minos in use by the game are all positive (7B,7C,7D,7E) while an
    empty tile is negative (EF).  The negative flag can be used to
    quickly determine if there's a mino or not in the playfield.

5.  Count down instead of up

    A few operations in the hard drop routine handle one row at a time,
    either moving it or checking all values.  Whether the row is read
    left to right or right to left does not matter.  By counting down
    instead of up, the negative flag can be used to signal the end of
    the loop instead of a comparison.

These changes reduce the maximum measured hard drop cycles from 21,876
to 12,877, and the maximum measured ghost piece staging cycles from
9,653 to 7,456.   Unused ROM space has been increased from 9,148 bytes
to 9,216.
@kirjavascript
Copy link
Owner

holy shit

will have to pull this one and play with it

Reduces the hard drop maximum cycle count by 39, saves 2 bytes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants