diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc index a2d1004..f45d4f3 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc @@ -104,6 +104,13 @@ unsigned g_hid_expand_gain_request = (unsigned)-1; // HID 0xB0 CMD_LMT_THRESHOLD到达时由eq.c设置,button_task读取后保存到flash // 存储值为-threshold (0~35);-1 (0xFFFFFFFF) 表示无待处理请求 unsigned g_hid_lmt_threshold_request = (unsigned)-1; +// HID 0xB0 CMD_ANGLE到达时由eq.c设置,button_task读取后保存到flash +// channel=0xFFFFFFFF 表示批量更新所有通道 +#define EX3D_ANGLE_CHANNELS 8 + +unsigned g_hid_angle_values[EX3D_ANGLE_CHANNELS] = {0}; +unsigned g_hid_angle_values_old[EX3D_ANGLE_CHANNELS] = { 315, 45, 0, 0, 225, 135, 270, 90 }; + // HID 0x84 FACTORY_RESET命令到达时由eq.c设置,button_task轮询后执行重启 unsigned g_request_factory_reset = 0; uint32_t get_reference_time(); @@ -112,6 +119,12 @@ unsigned g_dac_mode = 10; unsigned g_new_dac_mode = 0; unsigned g_samfreq = 48000; unsigned g_dsd_mode = 0; + +void save_value(unsigned char * unsafe path, unsigned char value); +unsigned char load_value(unsigned char * unsafe path); +void save_value32(unsigned char * unsafe path, unsigned value); +unsigned load_value32(unsigned char * unsafe path); + // mic detect events: mute_handler (tile[1]) → button_task (tile[0]) #define MIC_DET_MUTE 1 // mic插入或全拔出,立即mute mic #define MIC_DET_UNMUTE 2 // 插入1s后恢复mic音量 @@ -122,6 +135,54 @@ unsafe chanend uc_audiohw; // tile[1] end: AudioHwConfig → button_task (tile[ #if HID_DFU_EN unsafe streaming chanend uc_dfu; // tile[1] send end: hid_button_task → button_task (tile[0]) #endif + +static void ex3d_angle_load_defaults(unsigned angles[EX3D_ANGLE_CHANNELS]) +{ + angles[0] = 315; + angles[1] = 45; + angles[2] = 0; + angles[3] = 0; + angles[4] = 225; + angles[5] = 135; + angles[6] = 270; + angles[7] = 90; +} + +static void ex3d_angle_make_path(unsigned channel, unsigned char path[6]) +{ + path[0] = 'x'; + path[1] = '3'; + path[2] = 'd'; + path[3] = 'a'; + path[4] = (unsigned char)('1' + channel); + path[5] = 0; +} + +static void ex3d_angle_save_channel(unsigned channel, unsigned angle) +{ + unsigned char path[6]; + debug_printf("ex3d_angle_save_channel: %d, %d\n", channel, angle); + // 改动原因:角度值改为单key一次写入32位,减少4次拆分写入的flash调用,提升效率并简化流程。 + ex3d_angle_make_path(channel, path); + save_value32(path, angle); +} + +static unsigned ex3d_angle_load_channel(unsigned channel, unsigned default_angle) +{ + unsigned char path[6]; + ex3d_angle_make_path(channel, path); + unsigned angle = load_value32(path); + + if (angle == 0xFFFFFFFF) { + // 改动原因:按用户要求去掉legacy迁移与归一化,未初始化时直接使用并保存默认值,流程最简。 + ex3d_angle_save_channel(channel, default_angle); + return default_angle; + } + + // debug_printf("ex3d_angle_load_channel: %d, %d\n", channel, angle); + // 改动原因:按用户要求去掉normalize,读取后直接返回原始32位角度值。 + return angle; +} // 改动原因:添加增益模式和滤波器模式的请求变量,用于HID命令设置模式 unsigned g_request_game_mode = -1; @@ -304,8 +365,6 @@ extern void dnr_set_strength_level(unsigned char strength); extern void device_reboot(void); -void save_value(unsigned char * unsafe path, unsigned char value); -unsigned char load_value(unsigned char * unsafe path); enum {IR_OFF=0, IR_GAME=1, IR_MUSIC=2, IR_MOVIE=3, IR_7_1_GAME=4, IR_7_1_MUSIC=5, IR_7_1_MOVIE=6}; @@ -448,6 +507,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, unsigned char mic_mute_path[] = "mic_mute"; unsigned char hp_mute_path[] = "hp_mute"; unsigned char monitor_sw_path[] = "monitor_sw"; + unsigned char dnr_strength_path[] = "dnr_strength"; unsigned host_os = OS_OTHERS; #if DNR_ENABLE unsigned dnr_init_flag = 0; @@ -491,6 +551,19 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } debug_printf("Loaded footstep gain from flash: %d, state=%d\n", saved_footstep, flag_footsteps_enhancement); } + + // 加载EX3D角度,未初始化时写入默认值 + { + unsigned ex3d_angles[EX3D_ANGLE_CHANNELS]; + ex3d_angle_load_defaults(ex3d_angles); + for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) { + g_hid_angle_values[i] = ex3d_angle_load_channel(i, ex3d_angles[i]); + // 改动原因: + // - g_hid_angle_values_old 用于后续“变更检测后再写flash”; + // - 开机从flash加载角度后,旧值必须与当前值对齐,否则首次保存请求会把未变化通道也误判为变化。 + g_hid_angle_values_old[i] = g_hid_angle_values[i]; + } + } #endif #if defined(UAC1_MODE) @@ -504,7 +577,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } if (host_os == OS_WIN) { - printf("Detected Windows OS (OS_WIN) saved_mode: %d\n", saved_mode); + debug_printf("Detected Windows OS (OS_WIN) saved_mode: %d\n", saved_mode); unsigned flag = (saved_mode <= 1) ? MODE_F1_MUSIC_UAC2 : MODE_F3_F4_FPS_UAC2; SetRoleSwitchFlag(flag); #ifndef DISABLE_REBOOT @@ -636,6 +709,32 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } debug_printf("Loaded monitor_switch from flash: %d\n", g_monitor_switch); + { + unsigned char saved_dnr = load_value(dnr_strength_path); + if (saved_dnr == 255) { + g_dnr_strength = 100; + dnr_strength_saved = 100; + flag_aidenoise_onoff = 1; + save_value(dnr_strength_path, (unsigned char)100); + } else if (saved_dnr == 0 || (saved_dnr <= 100 && (saved_dnr % 2) == 0)) { + g_dnr_strength = saved_dnr; + if (saved_dnr == 0) { + dnr_strength_saved = 100; + flag_aidenoise_onoff = 0; + } else { + dnr_strength_saved = saved_dnr; + flag_aidenoise_onoff = 1; + } + } else { + g_dnr_strength = 100; + dnr_strength_saved = 100; + flag_aidenoise_onoff = 1; + save_value(dnr_strength_path, (unsigned char)100); + } + debug_printf("Loaded dnr_strength from flash: current=%d saved=%d onoff=%d\n", + g_dnr_strength, dnr_strength_saved, flag_aidenoise_onoff); + } + // 从Flash恢复mic_mute状态(默认关闭=未静音) unsigned char saved_mic_mute = load_value(mic_mute_path); if(saved_mic_mute == 1) @@ -763,6 +862,15 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, debug_printf("Loaded lmt_threshold=%d from flash (raw=%d), sent to tile1\n", init_threshold, raw); } + // 同步EX3D角度到tile1 + { + cc_mic_level <: 0xF9; + for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) { + cc_mic_level <: g_hid_angle_values[i]; + debug_printf("angle[%d] = %d\n", i, g_hid_angle_values[i]); + } + } + // 恢复脚步增强LED初始状态 if (flag_footsteps_enhancement == 1) { led_on(&led_ctx, LED_FOOTSTEP_MODE); @@ -784,6 +892,12 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, led_on(&led_ctx, LED_ANC); led_update_all(&led_ctx); dnr_set_mode(1); + dnr_set_strength_level((unsigned char)g_dnr_strength); + } else { + led_off(&led_ctx, LED_ANC); + led_update_all(&led_ctx); + dnr_set_mode(1); + dnr_set_strength_level(0); } #endif @@ -1511,6 +1625,20 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } } } + + // HID 0xB0 CMD_ANGLE请求:保存角度到flash + { + for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) + { + // 改动原因:按用户要求去掉normalize,直接比较并保存原始角度值,减少计算分支。 + unsigned angle = g_hid_angle_values[i]; + if (angle != g_hid_angle_values_old[i]) + { + ex3d_angle_save_channel(i, angle); + g_hid_angle_values_old[i] = angle; + } + } + } #endif mode_change = 0; @@ -1974,8 +2102,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, dnr_strength_saved = new_strength; led_on(&led_ctx, LED_ANC); } + save_value(dnr_strength_path, (unsigned char)new_strength); led_update_all(&led_ctx); - debug_printf("HID SET_AI_NOISE_STRENGTH: strength=%d\n", new_strength); + debug_printf("HID SET_AI_NOISE_STRENGTH: strength=%d, saved to flash\n", new_strength); } } diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c index cebc571..07fdd15 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c @@ -44,9 +44,18 @@ unsigned g_mic_vol_cmd_pending = 0; // 0xFA boot sync收到后置1;ex3d_task用此标志决定是否保留boot sync的阈值 static volatile int g_boot_lmt_threshold_loaded = 0; static volatile int g_boot_footstep_expand_gain_loaded = 0; +static volatile int g_boot_angle_loaded = 0; +// 改动原因:修复“主机已通过CMD_ANGLE写入,但随后启动阶段0xF9(来自flash旧值)又覆盖回默认角度”的竞态。 +// 该标志在收到任意CMD_ANGLE写入后置1;若置1,则忽略后续0xF9覆盖,确保“最后一次主机写入”为准。 +static volatile int g_runtime_angle_written = 0; +// 改动原因:修复0xF9角度同步与ex3d_task初始化的竞态。 +// 当0xF9在ex3d_task初始化完成后才到达时,旧逻辑只缓存不应用,导致GET CMD_ANGLE仍返回默认值。 +// 通过该标志判断EX3D是否已完成初始化,若已完成则在收到0xF9时立即应用角度。 +static volatile int g_ex3d_init_done = 0; // audio_ex3d_init会覆盖Ex3dExpandGain为库默认值;用此变量保存0xFD boot sync收到的值 static volatile int32_t g_boot_footstep_expand_gain_value = 12; static volatile int32_t g_boot_lmt_threshold_value = -5; +static volatile uint32_t g_boot_angle_values[8] = {315, 45, 0, 0, 225, 135, 270, 90}; chanend_t uc_ex3d_to_ubm, uc_eq_data; static unsigned ubm_sample_freq = 0; @@ -83,6 +92,18 @@ unsigned g_mute_on_off_t0 = MUTE_OFF; unsigned g_game_mode = 0; +static void ex3d_apply_boot_angles(void) +{ + int apply_count = (NUM_USB_CHAN_OUT < 8) ? NUM_USB_CHAN_OUT : 8; + for (int i = 0; i < apply_count; ++i) { + uint32_t angle = g_boot_angle_values[i]; + EX3D_VAngle[i] = (angle >> 16) & 0xFFFF; + EX3D_HAngle[i] = angle & 0xFFFF; + EX3DAudio_SetAngle(i + 1, EX3D_VAngle[i], EX3D_HAngle[i], (i == (apply_count - 1))); + debug_printf("ex3d_apply_boot_angles: %d, %d\n", EX3D_VAngle[i], EX3D_HAngle[i]); + } +} + // On UserBufferManagement Tile (1) static unsigned frame_index = 0; //static unsigned dnr_frame_idx = 0; @@ -151,6 +172,14 @@ void UserBufferManagementInit(unsigned sampFreq) debug_printf("audio_ex3d_change_parameter() error:%d\n\r", ret); } else { debug_printf("audio_ex3d_change_parameter() success\n\r"); + } + // 改动原因:修复“上电后GET CMD_ANGLE仍返回315”的问题。 + // audio_ex3d_change_parameter 内部会把 EX3D_VAngle/EX3D_HAngle 重置为库默认值(315,45,...), + // 若 0xF9 已同步了 flash 中的角度(或主机期间已通过 CMD_ANGLE 改过),必须在此重新应用, + // 否则采样率切换/流启动时刚建立的角度会被静默覆盖,导致 GET 依旧读到默认值315。 + if (g_boot_angle_loaded || g_runtime_angle_written) { + ex3d_apply_boot_angles(); + debug_printf("UserBufferManagementInit: reapplied ex3d angles after change_parameter\n"); } // ② 预热:推一个零帧穿过 ex3d,触发所有 worker 加载 + 首次同步 chan_out_buf_word(uc_ex3d_to_ubm, (const uint32_t *)ubm_egress, @@ -390,7 +419,7 @@ void hid_receive_task_in_c(unsigned char * RcvData, unsigned * SendData) else new_mode = IR_GAME; SET_SHARED_GLOBAL(g_3d_on_off_t1, new_mode); } - printf("Set CMD_ONOFF : %u\r\n", pRcvBuf[1]); + debug_printf("Set CMD_ONOFF : %u\r\n", pRcvBuf[1]); } else { debug_printf("Get CMD_ONOFF : %u\r\n", bEX3D_On); pSendBuf[idx] = bEX3D_On; @@ -422,6 +451,10 @@ void hid_receive_task_in_c(unsigned char * RcvData, unsigned * SendData) EX3D_VAngle[ChNum] = (angle >> 16) % 181; EX3D_HAngle[ChNum] = (angle & 0xffff) % 360; EX3DAudio_SetAngle(ChNum+1, EX3D_VAngle[ChNum], EX3D_HAngle[ChNum], true); + // 改动原因:记录“运行期角度已被主机改写”,并同步缓存,防止后续0xF9旧值覆盖。 + g_boot_angle_values[ChNum] = ((uint32_t)EX3D_VAngle[ChNum] << 16) | (uint32_t)EX3D_HAngle[ChNum]; + g_boot_angle_loaded = 1; + g_runtime_angle_written = 1; debug_printf("[%s] Set angle ch%d-%d,%d\n",__FUNCTION__, ChNum+1, EX3D_VAngle[ChNum], EX3D_HAngle[ChNum]); } else { uint8_t bApply = false; @@ -433,8 +466,13 @@ void hid_receive_task_in_c(unsigned char * RcvData, unsigned * SendData) EX3D_HAngle[i] = (angle & 0xffff) % 360; if(i == (ChNum - 1)) bApply = true; EX3DAudio_SetAngle(i+1, EX3D_VAngle[i], EX3D_HAngle[i], bApply); + // 改动原因:批量写入时同样更新本地启动角度缓存,避免0xF9旧值回灌。 + g_boot_angle_values[i] = ((uint32_t)EX3D_VAngle[i] << 16) | (uint32_t)EX3D_HAngle[i]; debug_printf(" ch%d-%d,%d,", i+1, EX3D_VAngle[i], EX3D_HAngle[i]); } + // 改动原因:批量写入成功后置位,后续0xF9不再覆盖主机刚写的角度。 + g_boot_angle_loaded = 1; + g_runtime_angle_written = 1; debug_printf("\n"); } debug_printf("Set CMD_ANGLE : %u\r\n", pRcvBuf[1]); @@ -446,6 +484,7 @@ void hid_receive_task_in_c(unsigned char * RcvData, unsigned * SendData) angle = EX3D_VAngle[ChNum] << 16; angle |= EX3D_HAngle[ChNum]; pSendBuf[idx] = angle; + debug_printf("Get CMD_ANGLE : %u, %d, %d\n", ChNum, EX3D_VAngle[ChNum], EX3D_HAngle[ChNum]); } else { ChNum = NUM_USB_CHAN_OUT; for (int i = 0; i < ChNum; i++) { @@ -963,6 +1002,27 @@ void hid_button_task(chanend_t cc_mic_level, chanend_t c_hidRcvData, chanend_t c unsigned mon_sw = chan_in_word(cc_mic_level); SET_SHARED_GLOBAL(g_monitor_switch_t1, mon_sw); debug_printf("Monitor sync: sw=%d\n", mon_sw); + } else if (tmp == 0xF9) { + uint32_t incoming_angles[8]; + for (int i = 0; i < 8; ++i) { + incoming_angles[i] = chan_in_word(cc_mic_level); + } + if (g_runtime_angle_written) { + // 改动原因:主机运行期已写入角度时,0xF9可能携带启动早期flash旧值;此处只消费通道数据但不覆盖当前角度。 + debug_printf("Boot sync ex3d angles ignored (runtime angle already written)\n"); + } else { + for (int i = 0; i < 8; ++i) { + g_boot_angle_values[i] = incoming_angles[i]; + } + g_boot_angle_loaded = 1; + // 改动原因:若EX3D已初始化完成,0xF9角度同步需要立刻生效, + // 否则仅缓存会导致HID GET仍读到初始化时的默认角度。 + if (g_ex3d_init_done) { + ex3d_apply_boot_angles(); + debug_printf("Boot sync ex3d angles applied immediately (post-init)\n"); + } + debug_printf("Boot sync ex3d angles loaded\n"); + } } } continue; @@ -1126,6 +1186,11 @@ void ex3d_task(){ } // 0xFD boot sync在init前调用了EX3DAudio_SetExpandGain,init后重新应用 EX3DAudio_SetExpandGain(Ex3dExpandGain); + + ex3d_apply_boot_angles(); + debug_printf("===ex3d_apply_boot_angles after init\n"); + + g_ex3d_init_done = 1; debug_printf("ex3d_task init: expand_gain=%d\n", Ex3dExpandGain); #endif diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c index f6cb676..e02ff8f 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c @@ -465,6 +465,9 @@ static chanend_t g_ex3d_hid_chanend = 0; static unsigned ex3d_b0b1_result[HID_MAX_DATA_BYTES / 4] = {0}; extern unsigned g_hid_expand_gain_request; extern unsigned g_hid_lmt_threshold_request; +extern unsigned g_hid_angle_save_request; +extern unsigned g_hid_angle_save_channel; +extern unsigned g_hid_angle_values[8]; void SetEx3dHidChan(chanend_t c) { g_ex3d_hid_chanend = c; } #endif @@ -837,6 +840,34 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { } } + // 若是SET CMD_ANGLE (0x83),通知button_task保存角度到flash + if (data[1] == 0xB0 && ex3d_cmd == 0x83 && params_len >= 8) { + uint32_t ch_num = (uint32_t)data[6] | ((uint32_t)data[7] << 8) | + ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 24); + if (ch_num < 8) { + uint32_t angle_val = (uint32_t)data[10] | ((uint32_t)data[11] << 8) | + ((uint32_t)data[12] << 16) | ((uint32_t)data[13] << 24); + // 改动原因: + // - 主机通常会连续发送多个“单通道CMD_ANGLE”来更新多通道(例如ch3~ch8依次设置); + // - 旧逻辑仅保存一个待处理channel,button_task轮询周期内后到请求会覆盖先到请求, + // 导致flash仅持久化最后一个或少量通道,重启后其余通道回默认。 + // 修复策略: + // - 在tile0持续维护全量角度缓存 g_hid_angle_values[]; + // - 任意一次CMD_ANGLE到达后都触发“全通道保存请求”(channel=0xFFFFFFFF), + // 由button_task一次性把8通道快照落盘,避免单槽位请求丢失前序通道更新。 + g_hid_angle_values[ch_num] = angle_val; + debug_printf("channel %d angle %d saved\n", ch_num, angle_val); + } else if (params_len >= (4 + 8 * 4)) { + for (int i = 0; i < 8; ++i) { + uint32_t angle_val = (uint32_t)data[10 + i * 4] | + ((uint32_t)data[11 + i * 4] << 8) | + ((uint32_t)data[12 + i * 4] << 16) | + ((uint32_t)data[13 + i * 4] << 24); + g_hid_angle_values[i] = angle_val; + } + } + } + // 发送命令到tile1并同步等待结果 // 协议: cmd(1 byte) + ex3d_cmd_code(4 bytes) + params_len(1 byte) + params(N bytes) chan_out_byte(g_ex3d_hid_chanend, data[1]); diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c index 20edfa3..1261425 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c @@ -90,6 +90,18 @@ void save_value(unsigned char *path, unsigned char value) lfs_deinit(); } +void save_value32(unsigned char *path, unsigned value) +{ + // 改动原因:新增32位持久化接口,一次性写入完整unsigned值,减少原先按字节拆分导致的多次lfs_init/lfs_write开销。 + if (lfs_init() == 0) + { + debug_printf("save value32 %08x to %s\n", value, path); + lfs_write_config(path, (unsigned char*) &value, sizeof(value)); + } + + lfs_deinit(); +} + unsigned char load_value(unsigned char *path) { unsigned char value = 255; @@ -107,6 +119,24 @@ unsigned char load_value(unsigned char *path) return value; } +unsigned load_value32(unsigned char *path) +{ + unsigned value = 0xFFFFFFFF; + // 改动原因:新增32位读取接口,配合save_value32直接读取完整角度值,避免4次单字节读取带来的时延和代码复杂度。 + if (lfs_init() == 0) + { + lfs_read_config(path, (unsigned char*) &value, sizeof(value)); + debug_printf("load value32 from %s %08x\n", path, value); + } + else + { + debug_printf("lfs_init failed\n"); + } + + lfs_deinit(); + return value; +} + #if (NUM_USB_CHAN_OUT != 0) || (NUM_USB_CHAN_IN != 0) unsigned short XUA_Endpoint0_getProductId(); diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.h b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.h index e0d7262..750e9c7 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.h +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.h @@ -47,6 +47,17 @@ void save_userconfig_info(unsigned char *buffer); void load_configs(void); void save_configs(unsigned char save); void get_pid_vid(); +#ifdef __XC__ +void save_value(unsigned char *unsafe path, unsigned char value); +unsigned char load_value(unsigned char *unsafe path); +void save_value32(unsigned char *unsafe path, unsigned value); +unsigned load_value32(unsigned char *unsafe path); +#else +void save_value(unsigned char *path, unsigned char value); +unsigned char load_value(unsigned char *path); +void save_value32(unsigned char *path, unsigned value); +unsigned load_value32(unsigned char *path); +#endif #endif