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) 2006, 2007, 2008 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 
28 #include "machine/general_operations.h"
29 
30 #include <string>
31 #include <vector>
32 
33 #include "systems/base/system.h"
34 #include "systems/base/graphics_system.h"
35 #include "systems/base/text_system.h"
36 #include "machine/rlmachine.h"
37 #include "libreallive/gameexe.h"
38 #include "libreallive/bytecode.h"
39 #include "utilities/exception.h"
40 
41 namespace getSystemObjImpl {
42 
43 template <>
GetSystemObj(RLMachine & machine)44 System& GetSystemObj(RLMachine& machine) {
45   return machine.system();
46 }
47 
48 template <>
GetSystemObj(RLMachine & machine)49 EventSystem& GetSystemObj(RLMachine& machine) {
50   return machine.system().event();
51 }
52 
53 template <>
GetSystemObj(RLMachine & machine)54 GraphicsSystem& GetSystemObj(RLMachine& machine) {
55   return machine.system().graphics();
56 }
57 
58 template <>
GetSystemObj(RLMachine & machine)59 TextSystem& GetSystemObj(RLMachine& machine) {
60   return machine.system().text();
61 }
62 
63 template <>
GetSystemObj(RLMachine & machine)64 SoundSystem& GetSystemObj(RLMachine& machine) {
65   return machine.system().sound();
66 }
67 
68 template <>
GetSystemObj(RLMachine & machine)69 CGMTable& GetSystemObj(RLMachine& machine) {
70   return machine.system().graphics().cg_table();
71 }
72 
73 template <>
GetSystemObj(RLMachine & machine)74 TextPage& GetSystemObj(RLMachine& machine) {
75   return machine.system().text().GetCurrentPage();
76 }
77 
78 }  // namespace getSystemObjImpl
79 
80 // -----------------------------------------------------------------------
81 // MultiDispatch
82 // -----------------------------------------------------------------------
MultiDispatch(RLOperation * op)83 MultiDispatch::MultiDispatch(RLOperation* op) : handler_(op) {}
84 
~MultiDispatch()85 MultiDispatch::~MultiDispatch() {}
86 
ParseParameters(const std::vector<std::string> & input,libreallive::ExpressionPiecesVector & output)87 void MultiDispatch::ParseParameters(
88     const std::vector<std::string>& input,
89     libreallive::ExpressionPiecesVector& output) {
90   for (auto const& parameter : input) {
91     const char* src = parameter.c_str();
92     output.push_back(libreallive::GetComplexParam(src));
93   }
94 }
95 
96 /// TODO(erg): Port this up to the new expression handling code
operator ()(RLMachine & machine,const libreallive::CommandElement & ff)97 void MultiDispatch::operator()(RLMachine& machine,
98                                const libreallive::CommandElement& ff) {
99   const libreallive::ExpressionPiecesVector& parameter_pieces =
100       ff.GetParsedParameters();
101 
102   for (unsigned int i = 0; i < parameter_pieces.size(); ++i) {
103     const libreallive::ExpressionPiecesVector& element =
104         parameter_pieces[i].GetContainedPieces();
105     handler_->Dispatch(machine, element);
106   }
107 
108   machine.AdvanceInstructionPointer();
109 }
110 
111 // -----------------------------------------------------------------------
112 // ReturnGameexeInt
113 // -----------------------------------------------------------------------
ReturnGameexeInt(const std::string & full_key,int en)114 ReturnGameexeInt::ReturnGameexeInt(const std::string& full_key, int en)
115     : full_key_name_(full_key), entry_(en) {}
116 
operator ()(RLMachine & machine)117 int ReturnGameexeInt::operator()(RLMachine& machine) {
118   Gameexe& gexe = machine.system().gameexe();
119   std::vector<int> values = gexe(full_key_name_);
120   if (static_cast<size_t>(entry_) < values.size()) {
121     return values[entry_];
122   } else {
123     std::ostringstream oss;
124     oss << "Could not access piece " << entry_ << " in Gameexe key \""
125         << full_key_name_ << "\"";
126     throw std::runtime_error(oss.str());
127   }
128 }
129 
130 // -----------------------------------------------------------------------
131 // InvokeSyscomAsOp
132 // -----------------------------------------------------------------------
InvokeSyscomAsOp(const int syscom)133 InvokeSyscomAsOp::InvokeSyscomAsOp(const int syscom) : syscom_(syscom) {}
134 
operator ()(RLMachine & machine)135 void InvokeSyscomAsOp::operator()(RLMachine& machine) {
136   machine.system().InvokeSyscom(machine, syscom_);
137 }
138 
139 // -----------------------------------------------------------------------
140 // UndefinedFunction
141 // -----------------------------------------------------------------------
UndefinedFunction(int modtype,int module,int opcode,int overload)142 UndefinedFunction::UndefinedFunction(int modtype,
143                                      int module,
144                                      int opcode,
145                                      int overload)
146     : modtype_(modtype),
147       module_(module),
148       opcode_(opcode),
149       overload_(overload) {}
150 
Dispatch(RLMachine & machine,const libreallive::ExpressionPiecesVector & parameters)151 void UndefinedFunction::Dispatch(
152     RLMachine& machine,
153     const libreallive::ExpressionPiecesVector& parameters) {
154   throw rlvm::UnimplementedOpcode(name(), modtype_, module_, opcode_, overload_);
155 }
156 
DispatchFunction(RLMachine & machine,const libreallive::CommandElement & f)157 void UndefinedFunction::DispatchFunction(RLMachine& machine,
158                                          const libreallive::CommandElement& f) {
159   throw rlvm::UnimplementedOpcode(machine, name(), f);
160 }
161 
ParseParameters(const std::vector<std::string> & input,libreallive::ExpressionPiecesVector & output)162 void UndefinedFunction::ParseParameters(
163     const std::vector<std::string>& input,
164     libreallive::ExpressionPiecesVector& output) {
165   throw rlvm::UnimplementedOpcode(name(), modtype_, module_, opcode_, overload_);
166 }
167 
operator ()(RLMachine & machine,const libreallive::CommandElement & f)168 void UndefinedFunction::operator()(RLMachine& machine,
169                                    const libreallive::CommandElement& f) {
170   throw rlvm::UnimplementedOpcode(machine, name(), f);
171 }
172 
173 // Template instantiations.
174 template RLOperation* CallFunction<EventSystem>(void (EventSystem::*)(int));
175 template RLOperation* CallFunction<GraphicsSystem>(void (GraphicsSystem::*)(int));
176 template RLOperation* CallFunction<SoundSystem>(void (SoundSystem::*)(int));
177 template RLOperation* CallFunction<System>(void (System::*)(int));
178 template RLOperation* CallFunction<TextSystem>(void (TextSystem::*)(int));
179 template RLOperation* ReturnIntValue<EventSystem, int>(int (EventSystem::*)() const);
180 template RLOperation* ReturnIntValue<GraphicsSystem, int>(int (GraphicsSystem::*)() const);
181 template RLOperation* ReturnIntValue<RLMachine, int>(int (RLMachine::*)() const);
182 template RLOperation* ReturnIntValue<SoundSystem, int>(int (SoundSystem::*)() const);
183 template RLOperation* ReturnIntValue<TextSystem, int>(int (TextSystem::*)() const);
184