Skip to content

Commit 5732f70

Browse files
committed
Merge 'Add a setting to lock starting the game behind a password' (#2240)
2 parents 7346bc3 + 9763c06 commit 5732f70

24 files changed

Lines changed: 38782 additions & 37722 deletions

ASM/build/asm_symbols.txt

Lines changed: 1340 additions & 1321 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ASM/build/bundle.o

3.91 KB
Binary file not shown.

ASM/build/c_symbols.txt

Lines changed: 589 additions & 576 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ASM/c/file_select.c

Lines changed: 192 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
#include "file_select.h"
22

3+
#include "audio.h"
34
#include "file_icons.h"
45
#include "file_message.h"
56
#include "gfx.h"
67
#include "music.h"
78
#include "text.h"
89
#include "util.h"
9-
#include "z64.h"
10-
10+
#include "save.h"
1111

1212
sprite_t* hash_sprites[2] = {
1313
&items_sprite,
@@ -56,6 +56,192 @@ hash_symbol_t hash_symbols[32] = {
5656

5757
extern uint8_t CFG_FILE_SELECT_HASH[5];
5858

59+
int8_t password_index = -1;
60+
uint16_t tentatives = 0;
61+
uint16_t cooldown = 0;
62+
static const uint8_t TEXT_WIDTH = 8;
63+
static const uint8_t TEXT_HEIGHT = 9;
64+
static const uint8_t BUTTON_WIDTH = 12;
65+
static const uint8_t BUTTON_HEIGHT = 12;
66+
extern uint8_t PASSWORD[PASSWORD_LENGTH];
67+
uint8_t buffer_password[PASSWORD_LENGTH] = {0, 0, 0, 0, 0, 0};
68+
69+
bool is_saved_password_clear(z64_menudata_t* menu_data) {
70+
// Player can save in file 1 and use file 2 later, so we look at both of them.
71+
bool fileOkPassword[2] = {true, true};
72+
for (uint8_t slotFile = 0; slotFile < 2; slotFile++) {
73+
z64_file_t* file = &menu_data->sram_buffer->primary_saves[slotFile].original_save;
74+
extended_savecontext_static_t* extended = &(((extended_sram_file_t*)file)->additional_save_data.extended);
75+
for (uint8_t i = 0 ; i < PASSWORD_LENGTH; i++) {
76+
if (extended->password[i] != PASSWORD[i]) {
77+
fileOkPassword[slotFile] = false;
78+
break;
79+
}
80+
}
81+
}
82+
return fileOkPassword[0] || fileOkPassword[1];
83+
}
84+
85+
bool is_buffer_password_clear() {
86+
for (uint8_t i = 0 ; i < PASSWORD_LENGTH; i++) {
87+
if (buffer_password[i] != PASSWORD[i]) {
88+
return false;
89+
}
90+
}
91+
return true;
92+
}
93+
94+
void reset_buffer() {
95+
// Don't reset if it's already the right one.
96+
if (is_buffer_password_clear()) {
97+
return;
98+
}
99+
password_index = -1;
100+
for (uint8_t i = 0 ; i < PASSWORD_LENGTH; i++) {
101+
buffer_password[i] = 0;
102+
}
103+
}
104+
105+
void manage_password(z64_disp_buf_t* db, z64_menudata_t* menu_data) {
106+
if (cooldown > 0) {
107+
cooldown--;
108+
}
109+
// Draw "Password locked" at the place of the Controls texture, and a key on the OK button, to display the lock.
110+
if (!is_saved_password_clear(menu_data) && !is_buffer_password_clear()) {
111+
int left = 90;
112+
int top = 204;
113+
int padding = 8;
114+
115+
gDPPipeSync(db->p++);
116+
if (cooldown > 0) {
117+
colorRGBA8_t color = {0xFF, 0xFF, 0xFF, 0xFF};
118+
draw_int_size(db, 1 + cooldown / 60, left - 2 * padding, top, color, 6, 12);
119+
}
120+
gDPPipeSync(db->p++);
121+
gDPSetCombineMode(db->p++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
122+
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF);
123+
sprite_load(db, &quest_items_sprite, 17, 1);
124+
sprite_draw(db, &quest_items_sprite, 0, left, top - 2, BUTTON_WIDTH, BUTTON_HEIGHT);
125+
text_print_size("Password locked", left + TEXT_HEIGHT + padding, top, TEXT_WIDTH);
126+
sprite_draw(db, &quest_items_sprite, 0, left + TEXT_WIDTH + 2 * padding + 15 * font_sprite.tile_w, top - 2, BUTTON_WIDTH, BUTTON_HEIGHT);
127+
text_flush_size(db, TEXT_WIDTH, TEXT_HEIGHT, 0, 0);
128+
}
129+
if (menu_data->menu_transition == SM_CONFIRM_FILE) {
130+
if (password_index < 0) {
131+
if (menu_data->selected_sub_item == FS_BTN_CONFIRM_YES) {
132+
if (z64_game.common.input[0].pad_pressed.a || z64_game.common.input[0].pad_pressed.s) {
133+
if (is_saved_password_clear(menu_data) || is_buffer_password_clear()) {
134+
// Load the game.
135+
z64_PlaySFXID(NA_SE_SY_FSEL_DECIDE_L);
136+
menu_data->menu_transition = SM_FADE_OUT;
137+
Audio_StopCurrentMusic(0xF);
138+
} else {
139+
if (cooldown == 0) {
140+
// Go to password screen.
141+
password_index++;
142+
return;
143+
} else {
144+
// Play an error sound until cooldown is finished.
145+
z64_PlaySFXID(NA_SE_SY_ERROR);
146+
}
147+
}
148+
}
149+
// Go back one screen.
150+
if (z64_game.common.input[0].pad_pressed.b) {
151+
z64_PlaySFXID(NA_SE_SY_FSEL_CLOSE);
152+
menu_data->menu_transition++;
153+
}
154+
}
155+
}
156+
if (menu_data->selected_sub_item == FS_BTN_CONFIRM_QUIT) { // On the Cancel option, reproduce vanilla behaviour and reset the buffer password.
157+
if (z64_game.common.input[0].pad_pressed.a || z64_game.common.input[0].pad_pressed.s || z64_game.common.input[0].pad_pressed.b) {
158+
z64_PlaySFXID(NA_SE_SY_FSEL_CLOSE);
159+
menu_data->menu_transition++;
160+
reset_buffer();
161+
}
162+
}
163+
// Password screen.
164+
if (password_index > -1) {
165+
uint8_t left_password = 0x37;
166+
uint8_t top_password = 0x5C;
167+
168+
gDPPipeSync(db->p++);
169+
gDPSetCombineMode(db->p++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
170+
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF);
171+
text_print_size("Enter Password", left_password, top_password, TEXT_WIDTH);
172+
text_flush_size(db, TEXT_WIDTH, TEXT_HEIGHT, 0, 0);
173+
174+
if (is_buffer_password_clear()) {
175+
password_index = -1;
176+
z64_PlaySFXID(NA_SE_SY_CORRECT_CHIME);
177+
// Write the password in save context.
178+
extended_sram_file_t* file = &(menu_data->sram_buffer->primary_saves[menu_data->selected_file]);
179+
extended_savecontext_static_t* extended = &(file->additional_save_data.extended);
180+
for (uint8_t i = 0 ; i < PASSWORD_LENGTH; i++) {
181+
extended->password[i] = buffer_password[i];
182+
}
183+
Sram_WriteSave(NULL, file);
184+
return;
185+
} else {
186+
if (z64_game.common.input[0].pad_pressed.a) {
187+
if (menu_data->selected_sub_item == FS_BTN_CONFIRM_YES) {
188+
buffer_password[password_index] = 1;
189+
password_index++;
190+
} else {
191+
z64_PlaySFXID(NA_SE_SY_FSEL_CLOSE);
192+
menu_data->menu_transition++;
193+
}
194+
}
195+
if (z64_game.common.input[0].pad_pressed.cd) {
196+
buffer_password[password_index] = 2;
197+
password_index++;
198+
}
199+
if (z64_game.common.input[0].pad_pressed.cr) {
200+
buffer_password[password_index] = 3;
201+
password_index++;
202+
}
203+
if (z64_game.common.input[0].pad_pressed.cl) {
204+
buffer_password[password_index] = 4;
205+
password_index++;
206+
}
207+
if (z64_game.common.input[0].pad_pressed.cu) {
208+
buffer_password[password_index] = 5;
209+
password_index++;
210+
}
211+
if (z64_game.common.input[0].pad_pressed.b) {
212+
password_index--;
213+
if (password_index < 0) {
214+
z64_PlaySFXID(NA_SE_SY_FSEL_CLOSE);
215+
reset_buffer();
216+
} else {
217+
buffer_password[password_index] = 0;
218+
}
219+
}
220+
if (password_index > 5 && !is_buffer_password_clear()) {
221+
tentatives++;
222+
// Penalty cooldown every 3 tries, starting from the 6th one.
223+
// File select is 60 fps, so 10sec.
224+
if (tentatives > 5 && (tentatives % 3) == 0) {
225+
cooldown = 600;
226+
}
227+
z64_PlaySFXID(NA_SE_SY_ERROR);
228+
reset_buffer();
229+
}
230+
}
231+
// Draw the password buttons.
232+
sprite_load(db, &ocarina_button_sprite, 0, 5);
233+
for (uint8_t i = 0 ; i < password_index + 1; i++) {
234+
gDPSetPrimColor(db->p++, 0, 0, 0xF4, 0xEC, 0x30, 0xFF); // Yellow C buttons
235+
if (buffer_password[i] - 1 == 0) { // A is blue
236+
gDPSetPrimColor(db->p++, 0, 0, 0x00, 0x00, 0xFF, 0xFF);
237+
}
238+
sprite_draw(db, &ocarina_button_sprite, buffer_password[i] - 1,
239+
left_password + i * (BUTTON_WIDTH + 5), top_password + 0x0C, BUTTON_WIDTH, BUTTON_HEIGHT);
240+
}
241+
}
242+
}
243+
}
244+
59245
void draw_file_select_hash(uint32_t fade_out_alpha, z64_menudata_t* menu_data) {
60246
z64_disp_buf_t* db = &(z64_ctxt.gfx->poly_opa);
61247

@@ -85,9 +271,11 @@ void draw_file_select_hash(uint32_t fade_out_alpha, z64_menudata_t* menu_data) {
85271
}
86272

87273
draw_file_message(db, menu_data);
88-
draw_file_icons(db, menu_data);
274+
if (password_index < 0) {
275+
draw_file_icons(db, menu_data);
276+
}
89277
display_song_name_on_file_select(db);
90-
278+
manage_password(db, menu_data);
91279
// Fade out once a file is selected
92280

93281
gDPPipeSync(db->p++);

ASM/c/file_select.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,26 @@
22
#define FILE_SELECT_H
33

44
#include "z64.h"
5+
#define PASSWORD_LENGTH 6
6+
7+
typedef enum {
8+
/* 0 */ SM_FADE_MAIN_TO_SELECT,
9+
/* 1 */ SM_MOVE_FILE_TO_TOP,
10+
/* 2 */ SM_FADE_IN_FILE_INFO,
11+
/* 3 */ SM_CONFIRM_FILE,
12+
/* 4 */ SM_FADE_OUT_FILE_INFO,
13+
/* 5 */ SM_MOVE_FILE_TO_SLOT,
14+
/* 6 */ SM_FADE_OUT,
15+
/* 7 */ SM_LOAD_GAME,
16+
} SelectMode;
17+
18+
typedef enum {
19+
/* 0 */ FS_BTN_CONFIRM_YES,
20+
/* 1 */ FS_BTN_CONFIRM_QUIT,
21+
} ConfirmButtonIndex;
522

623
void draw_file_select_hash(uint32_t fade_out_alpha, z64_menudata_t* menu_data);
724

25+
void Audio_StopCurrentMusic(uint16_t arg0);
26+
827
#endif

0 commit comments

Comments
 (0)