1 // -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi:tw=80:et:ts=2:sts=2
3 //
4 // -----------------------------------------------------------------------
5 //
6 // This file is part of RLVM, a RealLive virtual machine clone.
7 //
8 // -----------------------------------------------------------------------
9 //
10 // Copyright (C) 2010 Elliot Glaysher
11 //
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25 // -----------------------------------------------------------------------
26
27 #include "systems/base/little_busters_ef00dll.h"
28
29 #include <iostream>
30 #include <string>
31
32 #include "machine/rlmachine.h"
33 #include "utilities/exception.h"
34 #include "libreallive/intmemref.h"
35
36 using libreallive::IntMemRef;
37
38 namespace {
39
40 static int random_dirtable[] = {0, 2, 1, 3, 0, 2, 1, 3, 1, 3, 2, 0, 1, 3, 2, 0,
41 0, 0, 0, 0, 3, 1, 2, 0, 3, 1, 3, 1, 0, 2, 3, 1};
42
43 } // namespace
44
CallDLL(RLMachine & machine,int func,int arg1,int arg2,int arg3,int arg4)45 int LittleBustersEF00DLL::CallDLL(RLMachine& machine,
46 int func,
47 int arg1,
48 int arg2,
49 int arg3,
50 int arg4) {
51 switch (func) {
52 case 0:
53 ConfigureEffect(arg1, arg2, arg3, arg4);
54 break;
55 case 1:
56 PerformCalculations(machine, arg1);
57 break;
58 default:
59 std::cerr << "LittleBustersEF00DLL::callDLL(): Invalid function: " << func
60 << std::endl;
61 return -1;
62 }
63 return 0;
64 }
65
ConfigureEffect(int arg1,int arg2,int arg3,int arg4)66 void LittleBustersEF00DLL::ConfigureEffect(int arg1,
67 int arg2,
68 int arg3,
69 int arg4) {
70 if (!lb_ef_param)
71 lb_ef_param.reset(new double[sizeof(double) * 0x60 * 8]);
72
73 int param_top, param_size;
74 if (arg1 == 1) {
75 param_top = 0;
76 param_size = 0x20;
77 } else {
78 param_top = arg2;
79 param_size = arg3;
80 if (param_top < 0)
81 param_top = 0;
82 if (param_top > 0x20)
83 param_top = 0x20;
84 if (param_size + param_top > 0x20)
85 param_size = 0x20 - param_top;
86 }
87 for (int i = 0; i < 8; i++) {
88 double* param = lb_ef_param.get() + i * 0x60 + param_top * 3;
89 for (int j = 0; j < param_size; j++) {
90 *param++ = random() % 800 - 400;
91 *param++ = random() % 600 - 300;
92 *param++ = random() % 700 - 350;
93 }
94 }
95 if (arg4 != 1)
96 return;
97 int* dir = &random_dirtable[(random() & 3) * 8];
98 for (int i = 0; i < 8; i++) {
99 double* param = lb_ef_param.get() + i * 0x60;
100 double x = random() % 600 - 300;
101 double y = random() % 480 - 240;
102 if (x < 0)
103 x -= 80;
104 else
105 x += 80;
106 if (y < 0)
107 y -= 80;
108 else
109 y += 80;
110
111 switch (*dir++) {
112 case 0:
113 if (x < 0)
114 x = -x;
115 if (y < 0)
116 y = -y;
117 break;
118 case 1:
119 if (x > 0)
120 x = -x;
121 if (y < 0)
122 y = -y;
123 break;
124 case 2:
125 if (x < 0)
126 x = -x;
127 if (y > 0)
128 y = -y;
129 break;
130 case 4:
131 if (x > 0)
132 x = -x;
133 if (y > 0)
134 y = -y;
135 break;
136 }
137 param[9] = x * 1.2;
138 param[10] = y * 1.2;
139 param[11] *= 1.2;
140 param[12] *= -0.08;
141 param[13] *= -0.08;
142 param[14] *= -0.08;
143 param[15] = -param[9];
144 param[16] = -param[10];
145 param[17] = -param[11];
146 }
147 }
148
PerformCalculations(RLMachine & machine,int index)149 void LittleBustersEF00DLL::PerformCalculations(RLMachine& machine, int index) {
150 if (!lb_ef_param) {
151 throw rlvm::Exception("Effect calculation was called before setting");
152 }
153
154 int v5_1154 =
155 machine.GetIntValue(IntMemRef(libreallive::INTF_LOCATION, 1154 + index));
156 int j = ((v5_1154) & 0x1f) + index * 0x20;
157 int k = ((v5_1154 + 1) & 0x1f) + index * 0x20;
158 int l = ((v5_1154 + 2) & 0x1f) + index * 0x20;
159 int m = ((v5_1154 + 3) & 0x1f) + index * 0x20;
160 j *= 3;
161 k *= 3;
162 l *= 3;
163 m *= 3;
164
165 // 0 < x < 1
166 // va - vd は 0-1 の範囲で対称性を持つ3次関数
167 double x = double(machine.GetIntValue(
168 IntMemRef(libreallive::INTF_LOCATION, 1162 + index))) *
169 0.001;
170 double va = (x * x * x) / 6;
171 double vb = (-x * x * x + 3 * x * x - 3 * x + 1) / 6;
172 double vc = (3 * x * x * x - 6 * x * x + 4) / 6;
173 double vd = (-3 * x * x * x + 3 * x * x + 3 * x + 1) / 6;
174
175 double r1 = va * lb_ef_param[m + 3] + vd * lb_ef_param[l + 3] +
176 vc * lb_ef_param[k + 3] + vb * lb_ef_param[j + 3];
177 double r2 = va * lb_ef_param[m + 2] + vd * lb_ef_param[l + 2] +
178 vc * lb_ef_param[k + 2] + vb * lb_ef_param[j + 2];
179 double r3 = va * lb_ef_param[m + 1] + vd * lb_ef_param[l + 1] +
180 vc * lb_ef_param[k + 1] + vb * lb_ef_param[j + 1];
181 if (r1 != 400) {
182 r2 = r2 * 800 / (400 - r1);
183 r3 = r3 * 700 / (400 - r1);
184 }
185
186 machine.SetIntValue(IntMemRef(libreallive::INTF_LOCATION, 1151), r2);
187 machine.SetIntValue(IntMemRef(libreallive::INTF_LOCATION, 1152), r3);
188 machine.SetIntValue(IntMemRef(libreallive::INTF_LOCATION, 1153), r1);
189 }
190
GetDLLName() const191 const std::string& LittleBustersEF00DLL::GetDLLName() const {
192 static std::string n("EF00");
193 return n;
194 }
195