From 697ed5f58dc4c791cdda68df4496ef699e199047 Mon Sep 17 00:00:00 2001 From: Tau Date: Fri, 12 Apr 2019 13:35:07 -0400 Subject: [PATCH] Fully implement settings persistence --- src/idz/decoder/saveProfile.ts | 6 ++++++ src/idz/decoder/saveSettings.ts | 15 ++++----------- src/idz/encoder/loadGhost.ts | 22 ++++++++++++++++++++++ src/idz/encoder/loadProfile2.ts | 16 ++++------------ src/idz/encoder/loadTopTen.ts | 4 ++++ src/idz/handler/createProfile.ts | 21 ++------------------- src/idz/handler/saveProfile.ts | 1 + src/idz/handler/saveTimeAttack.ts | 24 +++++++++++++----------- src/idz/model/settings.ts | 13 ++++--------- src/idz/request/saveProfile.ts | 2 ++ src/idz/request/saveSettings.ts | 2 -- 11 files changed, 62 insertions(+), 64 deletions(-) diff --git a/src/idz/decoder/saveProfile.ts b/src/idz/decoder/saveProfile.ts index c0dd46a..cd92484 100644 --- a/src/idz/decoder/saveProfile.ts +++ b/src/idz/decoder/saveProfile.ts @@ -61,5 +61,11 @@ export function saveProfile(buf: Buffer): SaveProfileRequest { gauges: buf.readUInt16LE(0x0114), music: buf.readUInt16LE(0x0140), }, + settings: { + music: buf.readUInt16LE(0x045a), + pack: buf.readUInt32LE(0x0034), + paperCup: buf.readUInt8(0x00f6), + gauges: buf.readUInt8(0x00f7), + }, }; } diff --git a/src/idz/decoder/saveSettings.ts b/src/idz/decoder/saveSettings.ts index 6d6c932..b3b3122 100644 --- a/src/idz/decoder/saveSettings.ts +++ b/src/idz/decoder/saveSettings.ts @@ -16,19 +16,12 @@ export function saveSettings(buf: Buffer): SaveSettingsRequest { profileId: buf.readUInt32LE(0x0004) as Id, dpoint: buf.readUInt32LE(0x0008), settings: { - bgMusic: buf.readUInt16LE(0x0002), - forceQuitEn: ((pack >> 0) & 1) !== 0, - steeringForce: (pack >> 1) & 15, - bgVolume: (pack >> 5) & 15, - seVolume: (pack >> 9) & 15, - cornerGuide: ((pack >> 13) & 1) !== 0, - lineGuide: ((pack >> 14) & 1) !== 0, - ghostEn: ((pack >> 15) & 1) !== 0, - taResultSkip: ((pack >> 16) & 1) !== 0, + music: buf.readUInt16LE(0x0002), + pack: buf.readUInt32LE(0x000c), + paperCup: buf.readUInt8(0x0011), + gauges: buf.readUInt8(0x0012), }, field_0010: buf.readUInt8(0x0010), - field_0011: buf.readUInt8(0x0011), - field_0012: buf.readUInt8(0x0012), // always 5 for some reason field_0013: buf.readUInt8(0x0013), }; } diff --git a/src/idz/encoder/loadGhost.ts b/src/idz/encoder/loadGhost.ts index 30f398b..035f73d 100644 --- a/src/idz/encoder/loadGhost.ts +++ b/src/idz/encoder/loadGhost.ts @@ -3,7 +3,29 @@ import { LoadGhostResponse } from "../response/loadGhost"; export function loadGhost(res: LoadGhostResponse): Buffer { const buf = Buffer.alloc(0x0070); + // No idea what any of this even does. + buf.writeUInt16LE(0x00a1, 0x0000); + buf.writeUInt16LE(0x0005, 0x0002); // Chunk presence flags: 4 | 1 + + for (let i = 0; i < 2; i++) { + const base = 0x04 + i * 0x34; + + buf.writeUInt32LE(0, base + 0x00); + buf.writeUInt32LE(0xffffffff, base + 0x04); + + for (let j = 0; j < 3; j++) { + buf.writeUInt32LE(120000, base + 0x08 + j * 0x04); + } + + buf.writeUInt32LE(0, base + 0x14); + buf.writeUInt16LE(0xffff, base + 0x18); + buf.writeUInt8(0, base + 0x1a); + buf.writeUInt8(0, base + 0x1b); + buf.writeUInt8(0, base + 0x1c); + buf.writeUInt8(0, base + 0x1d); + buf.write("\0", base + 0x20); + } return buf; } diff --git a/src/idz/encoder/loadProfile2.ts b/src/idz/encoder/loadProfile2.ts index 5120ae1..ddfbfe4 100644 --- a/src/idz/encoder/loadProfile2.ts +++ b/src/idz/encoder/loadProfile2.ts @@ -7,16 +7,6 @@ import { mission } from "./_mission"; import { LoadProfileResponse2 } from "../response/loadProfile2"; export function loadProfile2(res: LoadProfileResponse2) { - const settingsPack = - ((res.settings.forceQuitEn ? 1 : 0) << 0) | - (res.settings.steeringForce << 1) | - (res.settings.bgVolume << 5) | - (res.settings.seVolume << 9) | - ((res.settings.cornerGuide ? 1 : 0) << 13) | - ((res.settings.lineGuide ? 1 : 0) << 14) | - ((res.settings.ghostEn ? 1 : 0) << 15) | - ((res.settings.taResultSkip ? 1 : 0) << 16); - const buf = Buffer.alloc(0x0d30); // FLAMETHROWER ANALYSIS (watch out for C strings) @@ -89,10 +79,10 @@ export function loadProfile2(res: LoadProfileResponse2) { buf.writeUInt16LE(res.unlocks.music, 0x01ec); mission(res.missions.team).copy(buf, 0x038a); buf.writeUInt32LE(res.profileId, 0x03b8); - buf.writeUInt16LE(res.settings.bgMusic, 0x03c8); + buf.writeUInt16LE(res.settings.music, 0x03c8); buf.writeUInt16LE(res.lv, 0x03cc); buf.writeUInt32LE(res.exp, 0x03d0); - buf.writeUInt32LE(settingsPack, 0x3d8); + buf.writeUInt32LE(res.settings.pack, 0x3d8); buf.writeUInt32LE(res.dpoint, 0x03e8); buf.writeUInt32LE(res.fame, 0x0404); iconv.encode(res.name + "\0", "shift_jis").copy(buf, 0x03ee); @@ -101,6 +91,8 @@ export function loadProfile2(res: LoadProfileResponse2) { mission(res.missions.solo).copy(buf, 0x06e4); chara(res.chara).copy(buf, 0x070c); bitmap(res.titles, 0xb4).copy(buf, 0x720); + buf.writeUInt8(res.settings.paperCup, 0x07d9); + buf.writeUInt8(res.settings.gauges, 0x07da); buf.writeInt32LE(res.teamId || 0, 0x07e0); car(res.car).copy(buf, 0x0c5c); diff --git a/src/idz/encoder/loadTopTen.ts b/src/idz/encoder/loadTopTen.ts index a13b35e..8ae0172 100644 --- a/src/idz/encoder/loadTopTen.ts +++ b/src/idz/encoder/loadTopTen.ts @@ -6,5 +6,9 @@ export function loadTopTen(res: LoadTopTenResponse): Buffer { buf.writeUInt16LE(0x00b6, 0x0000); // in awe of the size of this lad too + for (let i = 0x0002; i < 0x1720; i += 2) { + buf.writeUInt16LE(i & 0xff, i); + } + return buf; } diff --git a/src/idz/handler/createProfile.ts b/src/idz/handler/createProfile.ts index 973d368..a71d221 100644 --- a/src/idz/handler/createProfile.ts +++ b/src/idz/handler/createProfile.ts @@ -24,27 +24,10 @@ export async function createProfile( dpoint: 0, }; - const missions: MissionState = { - team: [], - solo: [], - }; - - const settings: Settings = { - bgMusic: 0, - forceQuitEn: false, - steeringForce: 4, - bgVolume: 10, - seVolume: 10, - cornerGuide: true, - lineGuide: false, - ghostEn: false, - taResultSkip: false, - }; - + const missions: MissionState = { team: [], solo: [] }; + const settings: Settings = { music: 0, pack: 13640, paperCup: 0, gauges: 5 }; const story: Story = { x: 0, y: 0, rows: [] }; - const timeAttack: TimeAttackState = { courses: [] }; - const unlocks: Unlocks = { cup: 0, gauges: 0, music: 0 }; await Promise.all([ diff --git a/src/idz/handler/saveProfile.ts b/src/idz/handler/saveProfile.ts index fe68704..311fbc2 100644 --- a/src/idz/handler/saveProfile.ts +++ b/src/idz/handler/saveProfile.ts @@ -28,6 +28,7 @@ export async function saveProfile( w.story().save(req.profileId, req.story), w.titles().save(req.profileId, req.titles), w.unlocks().save(req.profileId, req.unlocks), + w.settings().save(req.profileId, req.settings), ]); return { diff --git a/src/idz/handler/saveTimeAttack.ts b/src/idz/handler/saveTimeAttack.ts index 0227052..31dbad9 100644 --- a/src/idz/handler/saveTimeAttack.ts +++ b/src/idz/handler/saveTimeAttack.ts @@ -6,21 +6,23 @@ export async function saveTimeAttack( w: World, req: SaveTimeAttackRequest ): Promise { - const state = await w.timeAttack().load(req.profileId); - const existing = state.courses.find( - course => course.courseId === req.payload.courseId - ); - - if (existing === undefined || existing.totalMsec > req.payload.totalMsec) { - const newCourses = state.courses.filter( - course => course.courseId !== req.payload.courseId + if (req.payload.totalMsec > 0) { + const state = await w.timeAttack().load(req.profileId); + const existing = state.courses.find( + course => course.courseId === req.payload.courseId ); - newCourses.push(req.payload); + if (existing === undefined || existing.totalMsec > req.payload.totalMsec) { + const newCourses = state.courses.filter( + course => course.courseId !== req.payload.courseId + ); - const newState = { courses: newCourses }; + newCourses.push(req.payload); - await w.timeAttack().save(req.profileId, newState); + const newState = { courses: newCourses }; + + await w.timeAttack().save(req.profileId, newState); + } } return { diff --git a/src/idz/model/settings.ts b/src/idz/model/settings.ts index 8654255..b98de6e 100644 --- a/src/idz/model/settings.ts +++ b/src/idz/model/settings.ts @@ -1,11 +1,6 @@ export interface Settings { - bgMusic: number; - forceQuitEn: boolean; - steeringForce: number; - bgVolume: number; - seVolume: number; - cornerGuide: boolean; - lineGuide: boolean; - ghostEn: boolean; - taResultSkip: boolean; // TA = Time Attack presumably + music: number; + pack: number; + paperCup: number; + gauges: number; } diff --git a/src/idz/request/saveProfile.ts b/src/idz/request/saveProfile.ts index 17b8fd8..3702bf0 100644 --- a/src/idz/request/saveProfile.ts +++ b/src/idz/request/saveProfile.ts @@ -2,6 +2,7 @@ import { BackgroundCode, Id, TitleCode } from "../model/base"; import { Car } from "../model/car"; import { MissionState } from "../model/mission"; import { Profile } from "../model/profile"; +import { Settings } from "../model/settings"; import { Story } from "../model/story"; import { Unlocks } from "../model/unlocks"; @@ -20,4 +21,5 @@ export interface SaveProfileRequest { car: Car; story: Story; unlocks: Unlocks; + settings: Settings; } diff --git a/src/idz/request/saveSettings.ts b/src/idz/request/saveSettings.ts index 6a065dc..0db7356 100644 --- a/src/idz/request/saveSettings.ts +++ b/src/idz/request/saveSettings.ts @@ -8,7 +8,5 @@ export interface SaveSettingsRequest { dpoint: number; // ?? why settings: Settings; field_0010: number; - field_0011: number; - field_0012: number; field_0013: number; }