mirror of
https://github.com/djhackersdev/minime.git
synced 2026-07-18 16:21:23 -05:00
wip
This commit is contained in:
parent
5bac5b6abc
commit
fecc0e7981
|
|
@ -11,7 +11,7 @@ import { loadConfig2 } from "./loadConfig2";
|
|||
import { loadGarage } from "./loadGarage";
|
||||
import { loadGeneralReward } from "./loadGeneralReward";
|
||||
import { loadGhost } from "./loadGhost";
|
||||
import { loadProfile } from "./loadProfile";
|
||||
import { loadProfile2 } from "./loadProfile2";
|
||||
import { loadRewardTable } from "./loadRewardTable";
|
||||
import { loadServerList } from "./loadServerList";
|
||||
import { loadStocker } from "./loadStocker";
|
||||
|
|
@ -23,7 +23,8 @@ import { msg00AD } from "./msg00AD";
|
|||
import { saveExpedition } from "./saveExpedition";
|
||||
import { saveGarage } from "./saveGarage";
|
||||
import { saveNewCar } from "./saveNewCar";
|
||||
import { saveProfile } from "./saveProfile";
|
||||
import { saveProfile2 } from "./saveProfile2";
|
||||
import { saveProfile3 } from "./saveProfile3";
|
||||
import { saveSettings } from "./saveSettings";
|
||||
import { saveStocker } from "./saveStocker";
|
||||
import { saveTimeAttack } from "./saveTimeAttack";
|
||||
|
|
@ -56,7 +57,7 @@ const funcList: ReaderFn[] = [
|
|||
loadGarage,
|
||||
loadGeneralReward,
|
||||
loadGhost,
|
||||
loadProfile,
|
||||
loadProfile2,
|
||||
loadRewardTable,
|
||||
loadServerList,
|
||||
loadStocker,
|
||||
|
|
@ -70,7 +71,8 @@ const funcList: ReaderFn[] = [
|
|||
saveExpedition,
|
||||
saveGarage,
|
||||
saveNewCar,
|
||||
saveProfile,
|
||||
saveProfile2,
|
||||
saveProfile3,
|
||||
saveSettings,
|
||||
saveStocker,
|
||||
saveTimeAttack,
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import { RequestCode } from "./_defs";
|
||||
import { LoadProfileRequest } from "../request/loadProfile";
|
||||
import { AimeId } from "../../model";
|
||||
|
||||
loadProfile.msgCode = 0x0067 as RequestCode;
|
||||
loadProfile.msgLen = 0x0020;
|
||||
|
||||
export function loadProfile(buf: Buffer): LoadProfileRequest {
|
||||
return {
|
||||
type: "load_profile_req",
|
||||
aimeId: buf.readUInt32LE(0x0004) as AimeId,
|
||||
luid: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"),
|
||||
};
|
||||
}
|
||||
30
src/idz/decoder/loadProfile2.ts
Normal file
30
src/idz/decoder/loadProfile2.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { RequestCode } from "./_defs";
|
||||
import {
|
||||
LoadProfileRequest2,
|
||||
LoadProfileRequest3,
|
||||
} from "../request/loadProfile";
|
||||
import { AimeId } from "../../model";
|
||||
|
||||
loadProfile2.msgCode = 0x0067 as RequestCode;
|
||||
loadProfile2.msgLen = 0x0020;
|
||||
|
||||
export function loadProfile2(buf: Buffer): LoadProfileRequest2 {
|
||||
return {
|
||||
type: "load_profile_req",
|
||||
format: 2,
|
||||
aimeId: buf.readUInt32LE(0x0004) as AimeId,
|
||||
luid: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"),
|
||||
};
|
||||
}
|
||||
|
||||
loadProfile3.msgCode = 0x0012f as RequestCode;
|
||||
loadProfile3.msgLen = 0x0020;
|
||||
|
||||
export function loadProfile3(buf: Buffer): LoadProfileRequest3 {
|
||||
return {
|
||||
type: "load_profile_req",
|
||||
format: 3,
|
||||
aimeId: buf.readUInt32LE(0x0004) as AimeId,
|
||||
luid: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"),
|
||||
};
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@ import { mission } from "./_mission";
|
|||
import { RequestCode } from "./_defs";
|
||||
import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base";
|
||||
import { Profile } from "../model/profile";
|
||||
import { SaveProfileRequest } from "../request/saveProfile";
|
||||
import { SaveProfileRequest2 } from "../request/saveProfile";
|
||||
import { bitmap } from "./_bitmap";
|
||||
|
||||
saveProfile.msgCode = 0x0068 as RequestCode;
|
||||
saveProfile.msgLen = 0x0940;
|
||||
saveProfile2.msgCode = 0x0068 as RequestCode;
|
||||
saveProfile2.msgLen = 0x0940;
|
||||
|
||||
export function saveProfile(buf: Buffer): SaveProfileRequest {
|
||||
export function saveProfile2(buf: Buffer): SaveProfileRequest2 {
|
||||
const storyRows = new Array();
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
|
|
@ -46,6 +46,7 @@ export function saveProfile(buf: Buffer): SaveProfileRequest {
|
|||
|
||||
return {
|
||||
type: "save_profile_req",
|
||||
format: 2,
|
||||
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>,
|
||||
lv: buf.readUInt16LE(0x0026),
|
||||
exp: buf.readUInt32LE(0x0028),
|
||||
101
src/idz/decoder/saveProfile3.ts
Normal file
101
src/idz/decoder/saveProfile3.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import { car } from "./_car";
|
||||
import { mission } from "./_mission";
|
||||
import { RequestCode } from "./_defs";
|
||||
import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base";
|
||||
import { Profile } from "../model/profile";
|
||||
import { SaveProfileRequest2 } from "../request/saveProfile";
|
||||
import { bitmap } from "./_bitmap";
|
||||
|
||||
saveProfile3.msgCode = 0x0138 as RequestCode;
|
||||
saveProfile3.msgLen = 0x0a70;
|
||||
|
||||
export function saveProfile3(buf: Buffer): SaveProfileRequest2 {
|
||||
const storyRows = new Array();
|
||||
|
||||
/* Story seems to have changed somewhat
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
const cells = new Array();
|
||||
const rowOffset = 0xXXXX + i * 0x3c;
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
const a = buf.readUInt32LE(rowOffset + 0x04 + j * 4);
|
||||
const b = buf.readUInt16LE(rowOffset + 0x28 + j * 2);
|
||||
const cell = { a, b };
|
||||
|
||||
cells.push(cell);
|
||||
}
|
||||
|
||||
const row = { cells };
|
||||
|
||||
storyRows.push(row);
|
||||
}
|
||||
*/
|
||||
|
||||
const coursePlays = new Map<CourseNo, number>();
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
coursePlays.set(i as CourseNo, buf.readUInt16LE(0x0554 + 2 * i));
|
||||
}
|
||||
|
||||
const freeCar = {
|
||||
validFrom: buf.readUInt32LE(0x0138),
|
||||
};
|
||||
|
||||
const freeContinue = {
|
||||
validFrom: buf.readUInt32LE(0x0038),
|
||||
validTo: buf.readUInt32LE(0x003c),
|
||||
};
|
||||
|
||||
return {
|
||||
type: "save_profile_req",
|
||||
format: 2,
|
||||
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>,
|
||||
lv: buf.readUInt16LE(0x0026),
|
||||
exp: buf.readUInt32LE(0x0028),
|
||||
fame: buf.readUInt32LE(0x04fc),
|
||||
dpoint: buf.readUInt32LE(0x04f8),
|
||||
mileage: buf.readUInt32LE(0x0008),
|
||||
title: buf.readUInt16LE(0x0040) as TitleCode,
|
||||
titles: bitmap(buf.slice(0x0042, 0x00f6)),
|
||||
background: buf.readUInt8(0x0874) as BackgroundCode,
|
||||
coursePlays,
|
||||
missions: {
|
||||
team: mission(buf.slice(0x0430, 0x0452)),
|
||||
solo: mission(buf.slice(0x0848, 0x086a)),
|
||||
},
|
||||
car: car(buf.slice(0x0958, 0x09b8)),
|
||||
story: {
|
||||
x: buf.readUInt16LE(0x0818),
|
||||
y: buf.readUInt8(0x07fc),
|
||||
rows: storyRows,
|
||||
},
|
||||
unlocks: {
|
||||
cup: buf.readUInt8(0x0110),
|
||||
gauges: buf.readUInt16LE(0x0114),
|
||||
music: buf.readUInt16LE(0x0140),
|
||||
lastMileageReward: buf.readUInt32LE(0x013c),
|
||||
},
|
||||
tickets: {
|
||||
freeCar:
|
||||
freeCar.validFrom !== 0
|
||||
? {
|
||||
validFrom: new Date(freeCar.validFrom * 1000),
|
||||
}
|
||||
: undefined,
|
||||
freeContinue:
|
||||
freeContinue.validFrom !== 0 && freeContinue.validTo !== 0
|
||||
? {
|
||||
validFrom: new Date(freeContinue.validFrom * 1000),
|
||||
validTo: new Date(freeContinue.validTo * 1000),
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
settings: {
|
||||
music: buf.readUInt16LE(0x04ee),
|
||||
pack: buf.readUInt32LE(0x0034),
|
||||
paperCup: buf.readUInt8(0x00f6),
|
||||
gauges: buf.readUInt8(0x00f7),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { loadProfile1 } from "./loadProfile1";
|
||||
import { loadProfile2 } from "./loadProfile2";
|
||||
import { loadProfile3 } from "./loadProfile3";
|
||||
import { LoadProfileResponse } from "../response/loadProfile";
|
||||
|
||||
export function loadProfile(res: LoadProfileResponse) {
|
||||
|
|
@ -10,6 +11,9 @@ export function loadProfile(res: LoadProfileResponse) {
|
|||
case 2:
|
||||
return loadProfile2(res);
|
||||
|
||||
case 3:
|
||||
return loadProfile3(res);
|
||||
|
||||
default:
|
||||
const exhaust: never = res;
|
||||
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ export function loadProfile2(res: LoadProfileResponse2) {
|
|||
buf.writeUInt32LE(res.dpoint, 0x03e8);
|
||||
buf.writeUInt32LE(res.fame, 0x0404);
|
||||
iconv.encode(res.name + "\0", "shift_jis").copy(buf, 0x03ee);
|
||||
buf.writeUInt16LE(res.story.x, 0x06bc);
|
||||
buf.writeUInt8(res.story.y, 0x0670);
|
||||
buf.writeUInt16LE(res.story.x, 0x06bc);
|
||||
mission(res.missions.solo).copy(buf, 0x06e4);
|
||||
chara(res.chara).copy(buf, 0x070c);
|
||||
bitmap(res.titles, 0xb4).copy(buf, 0x720);
|
||||
|
|
|
|||
101
src/idz/encoder/loadProfile3.ts
Normal file
101
src/idz/encoder/loadProfile3.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import iconv = require("iconv-lite");
|
||||
|
||||
import { bitmap } from "./_bitmap";
|
||||
import { car } from "./_car";
|
||||
import { chara } from "./_chara";
|
||||
import { mission } from "./_mission";
|
||||
import { LoadProfileResponse3 } from "../response/loadProfile";
|
||||
|
||||
export function loadProfile3(res: LoadProfileResponse3) {
|
||||
const buf = Buffer.alloc(0x0ea0);
|
||||
|
||||
// Initialize all TA grades to uhh... fuck knows
|
||||
buf.fill(0xff, 0x07e4, 0x080c);
|
||||
|
||||
for (const score of res.timeAttack) {
|
||||
const { routeNo } = score;
|
||||
|
||||
buf.writeUInt32LE(
|
||||
(new Date(score.timestamp).getTime() / 1000) | 0, // Date ctor hack
|
||||
0x00e4 + routeNo * 4
|
||||
);
|
||||
|
||||
buf.writeUInt16LE(0, 0x067c + 2 * routeNo); // ???
|
||||
buf.writeUInt16LE(0xffff, 0x0184 + 2 * routeNo); // National rank
|
||||
buf.writeUInt32LE((score.totalTime * 1000) | 0, 0x00e4 + 4 * routeNo);
|
||||
buf.writeUInt8(score.flags, 0x06cc + routeNo);
|
||||
buf.writeUInt8(score.grade, 0x07e4 + routeNo);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
buf.writeUInt16LE(
|
||||
(score.sectionTimes[i] * 1000) >> 2,
|
||||
0x06f4 + 6 * routeNo + 2 * i
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 9 && i < res.story.rows.length; i++) {
|
||||
const row = res.story.rows[i];
|
||||
const rowOffset = 0x0256 + i * 0x26;
|
||||
|
||||
for (let j = 0; j < 9 && j < row.cells.length; j++) {
|
||||
const cell = row.cells[j];
|
||||
const cellOffset = rowOffset + j * 4;
|
||||
|
||||
buf.writeUInt16LE(cell.a, cellOffset + 0);
|
||||
buf.writeUInt16LE(cell.b, cellOffset + 2);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [courseId, playCount] of res.coursePlays.entries()) {
|
||||
if (courseId < 0 || courseId >= 20) {
|
||||
throw new Error(`Course id out of range: ${courseId}`);
|
||||
}
|
||||
|
||||
buf.writeUInt16LE(playCount, 0x053c + 2 * courseId);
|
||||
}
|
||||
|
||||
const { freeCar, freeContinue } = res.tickets;
|
||||
|
||||
if (freeCar) {
|
||||
buf.writeUInt32LE((freeCar.validFrom.getTime() / 1000) | 0, 0x0214);
|
||||
}
|
||||
|
||||
if (freeContinue) {
|
||||
buf.writeUInt32LE((freeContinue.validFrom.getTime() / 1000) | 0, 0x04b8);
|
||||
buf.writeUInt32LE((freeContinue.validTo.getTime() / 1000) | 0, 0x04bc);
|
||||
}
|
||||
|
||||
buf.writeUInt16LE(0x012e, 0x0000);
|
||||
buf.writeUInt8(res.unlocks.cup, 0x00b4);
|
||||
buf.writeUInt16LE(res.unlocks.gauges, 0x00b8);
|
||||
buf.writeUInt32LE(res.unlocks.lastMileageReward, 0x0218);
|
||||
buf.writeUInt16LE(res.unlocks.music, 0x021c);
|
||||
buf.writeUInt16LE(0, 0x0456); // Team leader
|
||||
mission(res.missions.team).copy(buf, 0x0460);
|
||||
buf.writeUInt16LE(0xffff, 0x0462); // [1]
|
||||
buf.writeUInt32LE(res.profileId, 0x0494);
|
||||
buf.writeUInt32LE(res.mileage, 0x0498);
|
||||
buf.writeUInt16LE(res.settings.music, 0x04a4);
|
||||
buf.writeUInt16LE(res.lv, 0x04a8);
|
||||
buf.writeUInt32LE(res.exp, 0x04ac);
|
||||
buf.writeUInt32LE(res.settings.pack, 0x04b4);
|
||||
buf.writeUInt32LE(res.dpoint, 0x04c4);
|
||||
buf.writeUInt32LE(res.fame, 0x04e0);
|
||||
iconv.encode(res.name + "\0", "shift_jis").copy(buf, 0x04ca);
|
||||
buf.writeUInt8(res.story.y, 0x080c);
|
||||
buf.writeUInt16LE(res.story.x, 0x0828);
|
||||
mission(res.missions.solo).copy(buf, 0x0858);
|
||||
chara(res.chara).copy(buf, 0x0880);
|
||||
bitmap(res.titles, 0xb4).copy(buf, 0x0894);
|
||||
buf.writeUInt8(res.settings.paperCup, 0x094d);
|
||||
buf.writeUInt8(res.settings.gauges, 0x094e);
|
||||
buf.writeUInt32LE(res.teamId || 0xffffffff, 0x0954);
|
||||
buf.writeUInt32LE(res.carCount, 0x0dd0);
|
||||
car(res.car).copy(buf, 0x0dd4);
|
||||
|
||||
// [1] Currently unknown, but if this field is zero then the player will have
|
||||
// a "model record" emblem in their profile card.
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ export async function loadProfile(
|
|||
|
||||
return {
|
||||
type: "load_profile_res",
|
||||
format: 2,
|
||||
format: req.format as any, // TS fart
|
||||
name: profile.name,
|
||||
profileId: profile.id,
|
||||
lv: profile.lv,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ export async function saveProfile(
|
|||
w: Repositories,
|
||||
req: SaveProfileRequest
|
||||
): Promise<GenericResponse> {
|
||||
console.log("*** PROFILE SAVE TEMPORARILY DISABLED ***");
|
||||
|
||||
return { type: "generic_res", status: 1 };
|
||||
|
||||
const now = new Date();
|
||||
const profile = await w.profile().load(req.profileId);
|
||||
const chara = await w.chara().load(req.profileId);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
import { AimeId } from "../../model";
|
||||
|
||||
export interface LoadProfileRequest {
|
||||
interface LoadProfileRequestBase {
|
||||
type: "load_profile_req";
|
||||
aimeId: AimeId;
|
||||
luid: string;
|
||||
}
|
||||
|
||||
export interface LoadProfileRequest2 extends LoadProfileRequestBase {
|
||||
format: 2;
|
||||
}
|
||||
|
||||
export interface LoadProfileRequest3 extends LoadProfileRequestBase {
|
||||
format: 3;
|
||||
}
|
||||
|
||||
export type LoadProfileRequest = LoadProfileRequest2 | LoadProfileRequest3;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Story } from "../model/story";
|
|||
import { Tickets } from "../model/tickets";
|
||||
import { Unlocks } from "../model/unlocks";
|
||||
|
||||
export interface SaveProfileRequest {
|
||||
interface SaveProfileRequestBase {
|
||||
type: "save_profile_req";
|
||||
profileId: ExtId<Profile>;
|
||||
lv: number;
|
||||
|
|
@ -26,3 +26,13 @@ export interface SaveProfileRequest {
|
|||
tickets: Tickets;
|
||||
settings: Settings;
|
||||
}
|
||||
|
||||
export interface SaveProfileRequest2 extends SaveProfileRequestBase {
|
||||
format: 2;
|
||||
}
|
||||
|
||||
export interface SaveProfileRequest3 extends SaveProfileRequestBase {
|
||||
format: 3;
|
||||
}
|
||||
|
||||
export type SaveProfileRequest = SaveProfileRequest2 | SaveProfileRequest3;
|
||||
|
|
|
|||
|
|
@ -41,4 +41,11 @@ export interface LoadProfileResponse2 extends LoadProfileResponseBase {
|
|||
format: 2;
|
||||
}
|
||||
|
||||
export type LoadProfileResponse = LoadProfileResponse1 | LoadProfileResponse2;
|
||||
export interface LoadProfileResponse3 extends LoadProfileResponseBase {
|
||||
format: 3;
|
||||
}
|
||||
|
||||
export type LoadProfileResponse =
|
||||
| LoadProfileResponse1
|
||||
| LoadProfileResponse2
|
||||
| LoadProfileResponse3;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user