Skip to content

Commit

Permalink
Change CityCenter semaphore combination to 10 digits
Browse files Browse the repository at this point in the history
  • Loading branch information
mdsteele committed Aug 22, 2024
1 parent c9f1031 commit 0a7f6ba
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 95 deletions.
2 changes: 1 addition & 1 deletion src/chr.asm
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
.INCLUDE "rooms/boss_mine.inc"
.INCLUDE "rooms/boss_shadow.inc"
.INCLUDE "rooms/boss_temple.inc"
.INCLUDE "rooms/city_building2.inc"
.INCLUDE "rooms/city_center.inc"
.INCLUDE "rooms/garden_tower.inc"
.INCLUDE "rooms/mine_west.inc"
.INCLUDE "upgrade.inc"
Expand Down
4 changes: 0 additions & 4 deletions src/machines/semaphore.inc
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
;;; * State3: The current upward vertical offset of the movable actuator, in
;;; pixels (0-16).

;;; The number of digits in the combination key that must be transferred by
;;; semaphore.
.DEFINE kNumSemaphoreKeyDigits 5

;;; The CHR bank numbers containing the diagrams for semaphore machines.
kChrBankDiagramSemaphoreComm = $0a
kChrBankDiagramSemaphoreKey = $0b
Expand Down
47 changes: 23 additions & 24 deletions src/rooms/city_building2.asm
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@
.INCLUDE "../device.inc"
.INCLUDE "../dialog.inc"
.INCLUDE "../flag.inc"
.INCLUDE "../machines/semaphore.inc"
.INCLUDE "../macros.inc"
.INCLUDE "../platform.inc"
.INCLUDE "../ppu.inc"
.INCLUDE "../room.inc"
.INCLUDE "city_building2.inc"
.INCLUDE "city_center.inc"

.IMPORT DataA_Room_Building_sTileset
.IMPORT Data_Empty_sActor_arr
.IMPORT FuncA_Objects_Draw1x1Shape
.IMPORT FuncA_Objects_MoveShapeLeftByA
.IMPORT FuncA_Objects_MoveShapeRightByA
.IMPORT FuncA_Objects_MoveShapeUpByA
.IMPORT FuncA_Objects_SetShapePosToPlatformTopLeft
.IMPORT Func_GetRandomByte
.IMPORT Func_Noop
Expand All @@ -57,18 +58,7 @@ kPerDigitSpinFrames = 10
;;; The OBJ palette number for drawing key combination digits.
kPaletteObjComboDigit = 1

;;;=========================================================================;;;

;;; Defines room-specific state data for this particular room.
.STRUCT sState
;; The combination that appears on the monitors.
Key_u8_arr .res kNumSemaphoreKeyDigits
;; The number of digits that have stopped spinning so far.
NumDigitsSet_u8 .byte
;; How many more frames until the next digit stops spinning.
SpinTimer_u8 .byte
.ENDSTRUCT
.ASSERT .sizeof(sState) <= kRoomStateSize, error
.ASSERT .sizeof(sCityCenterState) <= kRoomStateSize, error

;;;=========================================================================;;;

Expand All @@ -79,7 +69,7 @@ kPaletteObjComboDigit = 1
D_STRUCT sRoom
d_byte MinScrollX_u8, $0
d_word MaxScrollX_u16, $0
d_byte Flags_bRoom, eArea::City
d_byte Flags_bRoom, bRoom::ShareState | eArea::City
d_byte MinimapStartRow_u8, 1
d_byte MinimapStartCol_u8, 19
d_addr TerrainData_ptr, _TerrainData
Expand Down Expand Up @@ -110,7 +100,7 @@ _Platforms_sPlatform_arr:
d_word WidthPx_u16, $08
d_byte HeightPx_u8, $08
d_word Left_i16, $00a4
d_word Top_i16, $0058
d_word Top_i16, $0068
D_END
.assert * - :- <= kMaxPlatforms * .sizeof(sPlatform), error
.byte ePlatform::None
Expand Down Expand Up @@ -138,9 +128,9 @@ _Devices_sDevice_arr:
jsr FuncA_Objects_SetShapePosToPlatformTopLeft
ldx #kNumSemaphoreKeyDigits - 1
@loop:
cpx Zp_RoomState + sState::NumDigitsSet_u8
cpx Zp_RoomState + sCityCenterState::NumDigitsSet_u8
bge @spinning
lda Zp_RoomState + sState::Key_u8_arr, x
lda Zp_RoomState + sCityCenterState::Key_u8_arr, x
sbc #0 ; carry is clear
bpl @draw ; unconditional
@spinning:
Expand All @@ -154,6 +144,13 @@ _Devices_sDevice_arr:
jsr FuncA_Objects_Draw1x1Shape ; preserves X
lda #kBlockWidthPx ; param: offset
jsr FuncA_Objects_MoveShapeLeftByA ; preserves X
cpx #5
bne @continue
lda #kBlockHeightPx ; param: offset
jsr FuncA_Objects_MoveShapeUpByA ; preserves X
lda #kBlockWidthPx * 5 ; param: offset
jsr FuncA_Objects_MoveShapeRightByA ; preserves X
@continue:
dex
bpl @loop
@done:
Expand All @@ -169,29 +166,31 @@ _Devices_sDevice_arr:
bne @done
;; TODO: Play a sound for random key generation.
lda #kInitialSpinFrames
sta Zp_RoomState + sState::SpinTimer_u8
sta Zp_RoomState + sCityCenterState::SpinTimer_u8
;; Generate a random key combination, with each digit between 1 and 4.
ldx #kNumSemaphoreKeyDigits - 1
@loop:
jsr Func_GetRandomByte ; preserves X, returns A
and #$03
add #1
sta Zp_RoomState + sState::Key_u8_arr, x
sta Zp_RoomState + sCityCenterState::Key_u8_arr, x
dex
bpl @loop
inx ; now X is zero
stx Zp_RoomState + sCityCenterState::NumDigitsSet_u8
@done:
rts
.ENDPROC

.PROC FuncA_Room_CityBuilding2_TickRoom
dec Zp_RoomState + sState::SpinTimer_u8
dec Zp_RoomState + sCityCenterState::SpinTimer_u8
bne @done
lda Zp_RoomState + sState::NumDigitsSet_u8
lda Zp_RoomState + sCityCenterState::NumDigitsSet_u8
cmp #kNumSemaphoreKeyDigits
bge @done
inc Zp_RoomState + sState::NumDigitsSet_u8
inc Zp_RoomState + sCityCenterState::NumDigitsSet_u8
lda #kPerDigitSpinFrames
sta Zp_RoomState + sState::SpinTimer_u8
sta Zp_RoomState + sCityCenterState::SpinTimer_u8
@done:
rts
.ENDPROC
Expand Down
4 changes: 2 additions & 2 deletions src/rooms/city_building2.bg
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

DODCDCDDDCDCDCDCDDDP
ED AGAGAGAGAG EC
DF AIAIAIAIAI DE
DF AH EC
DF BHBHBHBHBH DE
DF AIAFAIAIAI EC
EDBC AJ BAABANDE
DFEIDJEIEIDIEIEIEIEIEIEJEIDE
ED EC
Expand Down
121 changes: 61 additions & 60 deletions src/rooms/city_center.asm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
.INCLUDE "../ppu.inc"
.INCLUDE "../program.inc"
.INCLUDE "../room.inc"
.INCLUDE "../spawn.inc"
.INCLUDE "city_center.inc"

.IMPORT DataA_Room_City_sTileset
.IMPORT FuncA_Machine_SemaphoreTick
Expand Down Expand Up @@ -82,6 +84,9 @@ kGrontaActorIndex = 1
;;; The actor index for the eastern orc in this room.
kEastOrcActorIndex = 2

;;; The device index for the door that leads to/from CityBuilding2.
kCityBuilding2DoorDeviceIndex = 7

;;; The device index for the locked door in this room.
kLockedDoorDeviceIndex = 1

Expand All @@ -97,16 +102,7 @@ kSemaphore2PlatformIndex = 1
kSemaphore3PlatformIndex = 2
kSemaphore4PlatformIndex = 3

;;;=========================================================================;;;

;;; Defines room-specific state data for this particular room.
.STRUCT sState
;; The combination that must be entered into the lock to unlock the door.
Key_u8_arr .res kNumSemaphoreKeyDigits
;; The combination currently entered into the door.
Lock_u8_arr .res kNumSemaphoreKeyDigits
.ENDSTRUCT
.ASSERT .sizeof(sState) <= kRoomStateSize, error
.ASSERT .sizeof(sCityCenterState) <= kRoomStateSize, error

;;;=========================================================================;;;

Expand All @@ -117,7 +113,7 @@ kSemaphore4PlatformIndex = 3
D_STRUCT sRoom
d_byte MinScrollX_u8, $10
d_word MaxScrollX_u16, $310
d_byte Flags_bRoom, bRoom::Tall | eArea::City
d_byte Flags_bRoom, bRoom::Tall | bRoom::ShareState | eArea::City
d_byte MinimapStartRow_u8, 1
d_byte MinimapStartCol_u8, 19
d_addr TerrainData_ptr, _TerrainData
Expand Down Expand Up @@ -155,7 +151,7 @@ _Machines_sMachine_arr:
d_byte MainPlatform_u8, kSemaphore1PlatformIndex
d_addr Init_func_ptr, Func_Noop
d_addr ReadReg_func_ptr, FuncC_City_CenterSemaphore_ReadReg
d_addr WriteReg_func_ptr, FuncC_City_CenterSemaphore_WriteReg
d_addr WriteReg_func_ptr, FuncA_Machine_CityCenterSemaphore_WriteReg
d_addr TryMove_func_ptr, FuncA_Machine_SemaphoreTryMove
d_addr TryAct_func_ptr, FuncA_Machine_SemaphoreTryAct
d_addr Tick_func_ptr, FuncA_Machine_SemaphoreTick
Expand All @@ -174,7 +170,7 @@ _Machines_sMachine_arr:
d_byte MainPlatform_u8, kSemaphore2PlatformIndex
d_addr Init_func_ptr, Func_Noop
d_addr ReadReg_func_ptr, FuncC_City_CenterSemaphore_ReadReg
d_addr WriteReg_func_ptr, FuncC_City_CenterSemaphore_WriteReg
d_addr WriteReg_func_ptr, Func_Noop
d_addr TryMove_func_ptr, FuncA_Machine_SemaphoreTryMove
d_addr TryAct_func_ptr, FuncA_Machine_SemaphoreTryAct
d_addr Tick_func_ptr, FuncA_Machine_SemaphoreTick
Expand All @@ -193,7 +189,7 @@ _Machines_sMachine_arr:
d_byte MainPlatform_u8, kSemaphore3PlatformIndex
d_addr Init_func_ptr, Func_Noop
d_addr ReadReg_func_ptr, FuncC_City_CenterSemaphore_ReadReg
d_addr WriteReg_func_ptr, FuncC_City_CenterSemaphore_WriteReg
d_addr WriteReg_func_ptr, Func_Noop
d_addr TryMove_func_ptr, FuncA_Machine_SemaphoreTryMove
d_addr TryAct_func_ptr, FuncA_Machine_SemaphoreTryAct
d_addr Tick_func_ptr, FuncA_Machine_SemaphoreTick
Expand All @@ -210,14 +206,14 @@ _Machines_sMachine_arr:
d_byte ScrollGoalY_u8, $0d
d_byte RegNames_u8_arr4, "J", "K", "S", "Y"
d_byte MainPlatform_u8, kSemaphore4PlatformIndex
d_addr Init_func_ptr, Func_Noop
d_addr Init_func_ptr, FuncA_Room_CityCenterSemaphore4_InitReset
d_addr ReadReg_func_ptr, FuncC_City_CenterSemaphore_ReadReg
d_addr WriteReg_func_ptr, FuncC_City_CenterSemaphore_WriteReg
d_addr WriteReg_func_ptr, FuncA_Machine_CityCenterSemaphore_WriteReg
d_addr TryMove_func_ptr, FuncA_Machine_SemaphoreTryMove
d_addr TryAct_func_ptr, FuncA_Machine_SemaphoreTryAct
d_addr Tick_func_ptr, FuncA_Machine_SemaphoreTick
d_addr Draw_func_ptr, FuncA_Objects_DrawSemaphoreLockMachine
d_addr Reset_func_ptr, FuncA_Room_MachineSemaphoreReset
d_addr Reset_func_ptr, FuncA_Room_CityCenterSemaphore4_InitReset
D_END
.assert * - :- <= kMaxMachines * .sizeof(sMachine), error
_Platforms_sPlatform_arr:
Expand Down Expand Up @@ -357,6 +353,7 @@ _Devices_sDevice_arr:
d_byte BlockCol_u8, 57
d_byte Target_byte, kSemaphore4MachineIndex
D_END
.assert * - :- = kCityBuilding2DoorDeviceIndex * .sizeof(sDevice), error
D_STRUCT sDevice
d_byte Type_eDevice, eDevice::Door1Open
d_byte BlockRow_u8, 8
Expand Down Expand Up @@ -481,13 +478,13 @@ _ReadRegJ:
_ReadRegKey:
flag_bit Sram_ProgressFlags_arr, eFlag::CityCenterKeygenConnected
beq @done
jsr FuncC_City_GetSemaphoreArrayIndex ; returns X
lda Zp_RoomState + sState::Key_u8_arr, x
ldx Ram_MachineGoalHorz_u8_arr, y ; combination array index
lda Zp_RoomState + sCityCenterState::Key_u8_arr, x
@done:
rts
_ReadRegLock:
jsr FuncC_City_GetSemaphoreArrayIndex ; returns X
lda Zp_RoomState + sState::Lock_u8_arr, x
ldx Ram_MachineGoalHorz_u8_arr, y ; combination array index
lda Zp_RoomState + sCityCenterState::Lock_u8_arr, x
rts
_ReadRegY:
lda Ram_MachineState3_byte_arr, y ; vertical offset
Expand All @@ -496,46 +493,14 @@ _ReadRegY:
rts
.ENDPROC

;;; @prereq Zp_MachineIndex_u8 and Zp_Current_sMachine_ptr are initialized.
;;; @prereq PRGA_Machine is loaded.
;;; @param A The value to write (0-9).
;;; @param X The register to write to ($c-$f).
.PROC FuncC_City_CenterSemaphore_WriteReg
ldy Zp_MachineIndex_u8
cpx #$c
bne _WriteRegLock
_WriteRegJ:
sta Ram_MachineGoalHorz_u8_arr, y ; combination array index
rts
_WriteRegLock:
pha ; value to write
jsr FuncC_City_GetSemaphoreArrayIndex ; returns X
pla ; value to write
sta Zp_RoomState + sState::Lock_u8_arr, x
rts
.ENDPROC

;;; Returns the combination array index for the specified semaphore machine,
;;; modulo kNumSemaphoreKeyDigits.
;;; @param Y The machine index.
;;; @return X The array index.
;;; @preserve Y, T0+
.PROC FuncC_City_GetSemaphoreArrayIndex
lda Ram_MachineGoalHorz_u8_arr, y ; combination array index
.assert kNumSemaphoreKeyDigits >= 5, error
cmp #kNumSemaphoreKeyDigits
blt @setIndex
sbc #kNumSemaphoreKeyDigits ; carry is already set
@setIndex:
tax
rts
.ENDPROC

;;;=========================================================================;;;

.SEGMENT "PRGA_Room"

;;; Called when the player avatar enters the CityCenter room.
;;; @param A The bSpawn value for where the avatar is entering the room.
.PROC FuncA_Room_CityCenter_EnterRoom
sta T0 ; bSpawn value
_RemoveEastOrc:
;; The eastern orc leaves once the B-remote has been collected (including
;; during the city breaker cutscene).
Expand Down Expand Up @@ -587,16 +552,22 @@ _UnlockDoor:
sta Ram_DeviceType_eDevice_arr + kLockedDoorDeviceIndex
@done:
_GenerateKey:
;; If the player avatar entered from CityBuilding2 (with which this room
;; shares state), don't re-randomize the key.
lda T0 ; bSpawn value
cmp #bSpawn::Device | kCityBuilding2DoorDeviceIndex
beq @done
;; TODO: Play a sound for random key generation.
;; Generate a random key combination, with each digit between 1 and 4.
ldx #kNumSemaphoreKeyDigits - 1
@loop:
jsr Func_GetRandomByte ; preserves X, returns A
jsr Func_GetRandomByte ; preserves X and Y, returns A
and #$03
add #1
sta Zp_RoomState + sState::Key_u8_arr, x
sta Zp_RoomState + sCityCenterState::Key_u8_arr, x
dex
bpl @loop
@done:
_SetFlag:
ldx #eFlag::CityCenterEnteredCity ; param: flag
jmp Func_SetFlag
Expand All @@ -606,8 +577,8 @@ _SetFlag:
;; Check the lock combination against the key.
ldx #kNumSemaphoreKeyDigits - 1
@loop:
lda Zp_RoomState + sState::Lock_u8_arr, x
cmp Zp_RoomState + sState::Key_u8_arr, x
lda Zp_RoomState + sCityCenterState::Lock_u8_arr, x
cmp Zp_RoomState + sCityCenterState::Key_u8_arr, x
bne @done ; combination is incorrect
dex
bpl @loop
Expand All @@ -621,6 +592,36 @@ _SetFlag:
rts
.ENDPROC

.PROC FuncA_Room_CityCenterSemaphore4_InitReset
lda #0
ldx #kNumSemaphoreKeyDigits - 1
@loop:
sta Zp_RoomState + sCityCenterState::Lock_u8_arr, x
dex
bpl @loop
jmp FuncA_Room_MachineSemaphoreReset
.ENDPROC

;;;=========================================================================;;;

.SEGMENT "PRGA_Machine"

;;; @prereq Zp_MachineIndex_u8 and Zp_Current_sMachine_ptr are initialized.
;;; @param A The value to write (0-9).
;;; @param X The register to write to ($c-$f).
.PROC FuncA_Machine_CityCenterSemaphore_WriteReg
ldy Zp_MachineIndex_u8
cpx #$c
bne _WriteRegLock
_WriteRegJ:
sta Ram_MachineGoalHorz_u8_arr, y ; combination array index
rts
_WriteRegLock:
ldx Ram_MachineGoalHorz_u8_arr, y ; combination array index
sta Zp_RoomState + sCityCenterState::Lock_u8_arr, x
rts
.ENDPROC

;;;=========================================================================;;;

.SEGMENT "PRGA_Cutscene"
Expand Down
Loading

0 comments on commit 0a7f6ba

Please sign in to comment.