summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/am/applets/applet_mii_edit.cpp
blob: f8e2bac320715f667a0cfbe6a88289c3deacea41 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/frontend/applets/mii_edit.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applet_mii_edit.h"
#include "core/hle/service/mii/mii_manager.h"

namespace Service::AM::Applets {

MiiEdit::MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
                 const Core::Frontend::MiiEditApplet& frontend_)
    : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}

MiiEdit::~MiiEdit() = default;

void MiiEdit::Initialize() {
    // Note: MiiEdit is not initialized with common arguments.
    //       Instead, it is initialized by an AppletInput storage with size 0x100 bytes.
    //       Do NOT call Applet::Initialize() here.

    const auto storage = broker.PopNormalDataToApplet();
    ASSERT(storage != nullptr);

    const auto applet_input_data = storage->GetData();
    ASSERT(applet_input_data.size() >= sizeof(MiiEditAppletInputCommon));

    std::memcpy(&applet_input_common, applet_input_data.data(), sizeof(MiiEditAppletInputCommon));

    LOG_INFO(Service_AM,
             "Initializing MiiEdit Applet with MiiEditAppletVersion={} and MiiEditAppletMode={}",
             applet_input_common.version, applet_input_common.applet_mode);

    switch (applet_input_common.version) {
    case MiiEditAppletVersion::Version3:
        ASSERT(applet_input_data.size() ==
               sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV3));
        std::memcpy(&applet_input_v3, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
                    sizeof(MiiEditAppletInputV3));
        break;
    case MiiEditAppletVersion::Version4:
        ASSERT(applet_input_data.size() ==
               sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
        std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
                    sizeof(MiiEditAppletInputV4));
        break;
    default:
        UNIMPLEMENTED_MSG("Unknown MiiEditAppletVersion={} with size={}",
                          applet_input_common.version, applet_input_data.size());
        ASSERT(applet_input_data.size() >=
               sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
        std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
                    sizeof(MiiEditAppletInputV4));
        break;
    }
}

bool MiiEdit::TransactionComplete() const {
    return is_complete;
}

Result MiiEdit::GetStatus() const {
    return ResultSuccess;
}

void MiiEdit::ExecuteInteractive() {
    ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet.");
}

void MiiEdit::Execute() {
    if (is_complete) {
        return;
    }

    // This is a default stub for each of the MiiEdit applet modes.
    switch (applet_input_common.applet_mode) {
    case MiiEditAppletMode::ShowMiiEdit:
    case MiiEditAppletMode::AppendMii:
    case MiiEditAppletMode::AppendMiiImage:
    case MiiEditAppletMode::UpdateMiiImage:
        MiiEditOutput(MiiEditResult::Success, 0);
        break;
    case MiiEditAppletMode::CreateMii:
    case MiiEditAppletMode::EditMii: {
        Service::Mii::MiiManager mii_manager;

        const MiiEditCharInfo char_info{
            .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
                          ? applet_input_v4.char_info.mii_info
                          : mii_manager.BuildBase(Mii::Gender::Male)},
        };

        MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
        break;
    }
    default:
        UNIMPLEMENTED_MSG("Unknown MiiEditAppletMode={}", applet_input_common.applet_mode);

        MiiEditOutput(MiiEditResult::Success, 0);
        break;
    }
}

void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) {
    const MiiEditAppletOutput applet_output{
        .result{result},
        .index{index},
    };

    std::vector<u8> out_data(sizeof(MiiEditAppletOutput));
    std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput));

    is_complete = true;

    broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
    broker.SignalStateChanged();
}

void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
                                              const MiiEditCharInfo& char_info) {
    const MiiEditAppletOutputForCharInfoEditing applet_output{
        .result{result},
        .char_info{char_info},
    };

    std::vector<u8> out_data(sizeof(MiiEditAppletOutputForCharInfoEditing));
    std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutputForCharInfoEditing));

    is_complete = true;

    broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
    broker.SignalStateChanged();
}

Result MiiEdit::RequestExit() {
    frontend.Close();
    R_SUCCEED();
}

} // namespace Service::AM::Applets