Scoring

The routine that updates and displays the score is at address 2D4D2. This function is called from address 28402 during game initialisation, and is the last subroutine to be called in the MainUpdate routine. The score is held in $5CC (as a long).

The score only increases when you shoot a guardian (+3 pts – address 2ADAE), send the guardian to pandaemonium ( +175 pts – at address 29D30), complete the star (variable points – address 2ADF6), win the constellation (depends on the data stored in the constellation data table, and written at address 2ADF6) or collect an additional life past the maximum 5 allowed (+3000 pts – address 2996A).

Constellation WonScore addedReference location in code
Scorpio15002E7D2 ($05DC)
Libra45002E7D4 ($1194)
Virgo75002E7D6 ($1D4C)
Leo105002E7D8 ($2904)
Cancer135002E7DA ($34BC)
Gemini180002E7DC ($4650)
Taurus225002E7DE ($57E4)
Aries270002E7E0 ($6978)
Pisces330002E7E2 ($80E8)
Aquarius390002E7E4 ($9858)
Capricorn460002E7E6 ($B3B0)
Sagittarius655352E7E8 ($FFFF)

To explain how the SUB_UpdateScoreAndDisplay_2D4D2 and SUB_RenderToScreen_2E4F0 subroutines render the score “123456” on the screen in Wicked , let’s look at the step-by-step process of the digit-by-digit conversion, screen position calculation, and bitplane rendering.

Overview of the Rendering Process

The score “123456” is stored as a 32-bit long-word at $5CC (score). The SUB_UpdateScoreAndDisplay_2D4D2 subroutine updates this value, loading the contents of $48A (pointstoadd) into D0 (the points) and converts it into individual digits, rendering each of them via SUB_RenderToScreen_2E4F0. The process involves:

  1. Score Update: Adding a value to the score (e.g., from a collision event).
  2. Digit Extraction: Converting the score to decimal digits using division by 10.
  3. Positioning: Calculating screen positions starting from a bottom-up offset (0x33E0), adjusted upward.
  4. Rendering: Using bitplane writes to display each digit, leveraging a lookup table (GraphicsLookupTable_3402A).

Step-by-Step Rendering of “123456”

1. Initial Setup in SUB_UpdateScoreAndDisplay_2D4D2

Assume the score at 0x5CC is updated to 123,456 (hex 0x0001E240) via a call to SUB_UpdateScoreAndDisplay_2D4D2 with D0 containing the points to be added. The subroutine executes as follows:

  • Save Register:
    MOVE.L A5,-(A7) ;2d4d2: Save A5 to stack Preserves A5 for later restoration.
  • Update Score:
    ADD.L D0,Score ;2d4d4: Add D0 to Score (0x5CC)
    MOVE.L Score,D6 ;2d4da: Load updated Score (0x0001E240) into D6

    D6 now holds 0x1E240 (123,456).
  • Boundary Check:
    CMPI.L #$0009ffff,D6 ;2d4e0: Compare with 655,359
    BHI.W LAB_SkipDisplayUpdate_2D528 ;2d4e6: Skip if > 655,359

    123,456 < 655,359, so proceed.
  • Game Mode Check:
    TST.W GameControlMode ;2d4ea: Test GameControlMode (0x5B2)
    BNE.W LAB_SkipDisplayUpdate_2D528 ;2d4f0: Skip if not in-game

    Assume GameControlMode = 0 (in-game), so proceed.
  • Initialize Rendering:
    MOVE.W #$33e0,D5 ;2d4f4: Set D5 to 0x33E0 (bottommost position)
    LEA EXT_59E,A5 ;2d4f8: Load digit buffer address into A5

    D5 = 0x33E0 is the starting screen offset, likely a bitplane address for the bottom-right of the score area. EXT_59E stores previous digits for comparison.

2. Digit Extraction and Rendering Loop

The loop (LAB_ProcessNextDigit_2D4FE) extracts and renders each digit:

  • Digit Extraction:
    DIVU #$000a,D6 ;2d4fe: Divide D6 by 10 SWAP D6 ;2d502: Swap to get remainder (digit) in low word
  • Digit Comparison and Update:
    CMP.B (A5)+,D6 ;2d504: Compare digit with stored value, increment A5
    BEQ.W LAB_DigitUnchanged_2D51C ;2d506: Skip if unchanged
    MOVE.B D6,-1(A5) ;2d50a: Store new digit
    ADD.W #$000a,D6 ;2d50e: Add 10 (adjust for lookup index)
    MOVE.W D6,D0 ;2d512: Move to D0 for rendering
    MOVE.W D5,D3 ;2d514: Move position to D3
    JSR DrawToScreen_2E4F0 ;2d516: Render digit

    • First digit: D6 = 6. If EXT_59E previously held a different value (e.g., 0), store 6, set D0 = 16 (6 + 10), and D3 = 0x33E0.
    • Loop continues for 5, 4, 3, 2, 1, with D5 decremented each time.
  • Position Adjustment:
    SUB.W #$0a00,D5 ;2d51c: Move to next position
    CLR.W D6 ;2d520: Clear low word
    SWAP D6 ;2d522: Move quotient to low word
    TST.W D6 ;2d524: Test if quotient is zero
    BNE.S LAB_ProcessNextDigit_2D4FE ;2d526: Loop if more digits

    • D5 starts at 0x33E0, decrements to 0x29E0, 0x1FE0, 0x15E0, 0x0BE0, 0x01E0 for 6 digits.
    • 0x0A00 (2560 decimal) is a large offset, likely a bitplane address step (e.g., 320 pixels * 8 bitplanes, adjusted for Amiga memory layout).

3. Rendering in SUB_RenderToScreen_2E4F0

For each digit call (e.g., digit 6 at D0 = 16, D3 = 0x33E0):

  • Input Processing:
    SWAP D3 ;2e4f0: Clear upper word of D3
    CLR.W D3 ;2e4f2: Clear lower word
    SWAP D3 ;2e4f4: Reset
    MOVE.W D3,D1 ;2e4f6: D1 = 0x33E0
    SR.W #2,D3 ;2e4f8: D3 = 0x08F8 (0x33E0 / 4)
    AND.W #$0001,D1 ;2e4fa: D1 = 0 (even)
    ADD.W D1,D3 ;2e4fe: D3 = 0x08F8
    ADD.W D0,D0 ;2e500: D0 = 32
    MOVE.W D0,D1 ;2e502: D1 = 32
    ADD.W D1,D1 ;2e504: D1 = 64
    ADD.W D1,D1 ;2e506: D1 = 128
    ADD.W D1,D0 ;2e508: D0 = 160 (16 * 10)


    D0 = 160 indexes GraphicsLookupTable_3402A for digit 6’s data
  • Lookup Table Access:
    LEA GraphicsLookupTable_3402A,A0 ;2e50a: Load table
    MOVE.W 2(A0,D0.W),D2 ;2e510: Load height (e.g., 10) into D2
    MOVEA.L 6(A0,D0.W),A1 ;2e514: Load bitplane data address into A1
    TST.W 4(A0,D0.W) ;2e518: Test mode flag


    Assume mode flag = 0 (masked write).
  • Screen Buffer Selection:
    MOVEA.L D3,A2 ;2e53e: A2 = 0x08F8
    MOVE.W D1,D3 ;2e540: D3 = width (e.g., 10)
    CMPI.W #Mode_StarChartScreen,GameControlMode ;2e542: Not Star Chart
    MOVEA.L #$00010000,A3 ;2e558: A3 = ScreenBufferA
    MOVE.L A1,-(A7) ;2e55e: Push A1
    MOVE.W D2,-(A7) ;2e560: Push D2
    BSR.W BitplaneMaskedWrite_2E5EC ;2e562: Render to ScreenBufferA
    • A3 is set to 0x10000 + 0x08F8 (adjusted address).
  • Masked Write:
    ADDA.L A2,A3 ;2e5ec: A3 = 0x108F8
    CMPI.W #$0006,4(A0,D0.W) ;2e5ee: Not mode 6
    MOVEM.L A4-A6,-(A7) ;2e5f6: Save registers
    BSR.W SUB_2E658 ;2e5fa: Process bitplanes
    MOVEQ #$13,D4 ;2e608: D4 = 19
    SUB.W D3,D4 ;2e60a: D4 = 9
    ADD.W D4,D4 ;2e60c: D4 = 18
    MOVE.W D0,-(A7) ;2e618: Push D0
    • Iterates over bitplanes, rendering digit 6 downward.
  • Loop for Each Digit:
    • Repeats for digits 5 (D5 = 0x29E0), 4 (0x1FE0), 3 (0x15E0), 2 (0x0BE0), 1 (0x01E0), with D0 set to 15, 14, 13, 12, 11 respectively.

4. Screen Layout Inference

  • Position: 0x33E0 is likely the bottom-left pixel address (e.g., Y = 192). 0x0A00 (2560) steps upward by ~8 scanlines (320 * 8 = 2560 bits, adjusted for bitplane stride).
  • Order: Digits render as:
    • 6 at 0x33E0 (bottom).
    • 5 at 0x29E0.
    • 4 at 0x1FE0.
    • 3 at 0x15E0.
    • 2 at 0x0BE0.
    • 1 at 0x01E0 (top).
  • Bitplane Write: ADDA.L #$28,A3 (40 pixels) writes downward, but the upward D5 adjustment places each digit’s top above the previous, rendering the digits from the bottom upward in the score column.
  • Render Optimization: EXT_59E ensures only changed digits (e.g. the 6, from 123455 to 123456) are re-rendered.

Conclusion

The score “123456” is rendered by SUB_UpdateScoreAndDisplay_2D4D2 extracting digits (6, 5, 4, 3, 2, 1) and SUB_RenderToScreen_2E4F0 writing them bottom-up from 0x33E0 upward, using masked bitplane updates.

Create a website or blog at WordPress.com

Up ↑