neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

instruction.hpp (29698B)


      1 #ifndef UUID_0A01B0B9_DA9A_4A05_919B_A5503594CA9D
      2 #define UUID_0A01B0B9_DA9A_4A05_919B_A5503594CA9D
      3 #pragma once
      4 
      5 #include "file.hpp"
      6 #include "../../source.hpp"
      7 #include "../item.hpp"
      8 
      9 #include <libshit/lua/auto_table.hpp>
     10 
     11 #include <boost/endian/arithmetic.hpp>
     12 
     13 namespace Neptools::Stsc
     14 {
     15 
     16   class InstructionBase : public Item
     17   {
     18     LIBSHIT_LUA_CLASS;
     19   public:
     20     InstructionBase(Key k, Context& ctx, uint8_t opcode)
     21       : Item{k, ctx}, opcode{opcode} {}
     22 
     23     static InstructionBase& CreateAndInsert(ItemPointer ptr, Flavor f);
     24 
     25     const uint8_t opcode;
     26 
     27   protected:
     28     void InstrDump(Sink& sink) const;
     29     std::ostream& InstrInspect(std::ostream& os, unsigned indent) const;
     30 
     31   private:
     32     virtual void PostInsert(Flavor f) = 0;
     33   };
     34 
     35   using Tagged = uint32_t;
     36   struct Code;
     37 
     38   template <typename T> struct TupleTypeMap { using Type = T; };
     39   template<> struct TupleTypeMap<std::string> { using Type = LabelPtr; };
     40   template<> struct TupleTypeMap<void*> { using Type = LabelPtr; };
     41   template<> struct TupleTypeMap<Code*> { using Type = LabelPtr; };
     42 
     43   template <typename T>
     44   using TupleTypeMapT = typename TupleTypeMap<T>::Type;
     45 
     46   // namegen
     47   template <char... Args> struct StringContainer
     48   {
     49     template <char... X> using Append = StringContainer<Args..., X...>;
     50     static inline constexpr const char str[sizeof...(Args)+1] = { Args... };
     51   };
     52 
     53   template <typename Cnt, typename... Args> struct AppendTypes;
     54   template <typename Cnt> struct AppendTypes<Cnt> { using Type = Cnt; };
     55 #define NEPTOOLS_GEN(x, ...)                                         \
     56   template <typename Cnt, typename... Args>                          \
     57   struct AppendTypes<Cnt, x, Args...>                                \
     58   {                                                                  \
     59     using Type = typename AppendTypes<typename Cnt::template Append< \
     60       '_',__VA_ARGS__>, Args...>::Type;                              \
     61   }
     62   NEPTOOLS_GEN(uint8_t, 'u','i','n','t','8');
     63   NEPTOOLS_GEN(uint16_t, 'u','i','n','t','1','6');
     64   NEPTOOLS_GEN(uint32_t, 'u','i','n','t','3','2');
     65   NEPTOOLS_GEN(float, 'f','l','o','a','t');
     66   NEPTOOLS_GEN(std::string, 's','t','r','i','n','g');
     67   NEPTOOLS_GEN(Code*, 'c','o','d','e');
     68   NEPTOOLS_GEN(void*, 'd','a','t','a');
     69 #undef NEPTOOLS_GEN
     70 
     71   template <bool NoReturn, typename... Args>
     72   class SimpleInstruction final : public InstructionBase
     73   {
     74     using Pref = StringContainer<
     75       'n','e','p','t','o','o','l','s','.','s','t','s','c','.',
     76       's','i','m','p','l','e','_','i','n','s','t','r','u','c','t','i','o','n','_'>;
     77     using Boold = std::conditional_t<
     78       NoReturn,
     79       Pref::Append<'t','r','u','e'>,
     80       Pref::Append<'f','a','l','s','e'>>;
     81     using TypeName = typename AppendTypes<Boold, Args...>::Type;
     82 
     83     LIBSHIT_DYNAMIC_OBJ_GEN;
     84   public:
     85     static constexpr const char* TYPE_NAME = TypeName::str;
     86 
     87     SimpleInstruction(Key k, Context& ctx, uint8_t opcode, Source src);
     88     SimpleInstruction(
     89       Key k, Context& ctx, uint8_t opcode, TupleTypeMapT<Args>... args)
     90       : InstructionBase{k, ctx, opcode}, args{std::move(args)...} {}
     91 
     92     static const FilePosition SIZE;
     93     FilePosition GetSize() const noexcept override { return SIZE; }
     94 
     95     using ArgsT = std::tuple<TupleTypeMapT<Args>...>;
     96     ArgsT args;
     97 
     98   private:
     99     void Parse_(Context& ctx, Source& src);
    100     void Dump_(Sink& sink) const override;
    101     void Inspect_(std::ostream& os, unsigned indent) const override;
    102     void PostInsert(Flavor f) override;
    103   };
    104 
    105   class InstructionRndJumpItem final : public InstructionBase
    106   {
    107     LIBSHIT_DYNAMIC_OBJECT;
    108   public:
    109     InstructionRndJumpItem(Key k, Context& ctx, uint8_t opcode, Source src);
    110     FilePosition GetSize() const noexcept override { return 2 + tgts.size()*4; }
    111 
    112     LIBSHIT_LUAGEN(get: "::Libshit::Lua::GetSmartOwnedMember")
    113     std::vector<Libshit::NotNull<LabelPtr>> tgts;
    114 
    115   private:
    116     void Parse_(Context& ctx, Source& src);
    117     void Dump_(Sink& sink) const override;
    118     void Inspect_(std::ostream& os, unsigned indent) const override;
    119     void PostInsert(Flavor f) override;
    120   };
    121 
    122   class UnimplementedInstructionItem final : public InstructionBase
    123   {
    124     LIBSHIT_DYNAMIC_OBJECT;
    125   public:
    126     UnimplementedInstructionItem(
    127       Key k, Context& ctx, uint8_t opcode, const Source&)
    128       : InstructionBase{k, ctx, opcode}
    129     { LIBSHIT_THROW(Libshit::DecodeError, "Unimplemented instruction"); }
    130 
    131     FilePosition GetSize() const noexcept override { return 0; }
    132 
    133   private:
    134     void Dump_(Sink&) const override {}
    135     void Inspect_(std::ostream&, unsigned) const override {}
    136     void PostInsert(Flavor) override {}
    137   };
    138 
    139   class InstructionJumpIfItem final : public InstructionBase
    140   {
    141     LIBSHIT_DYNAMIC_OBJECT;
    142   public:
    143     struct FixParams
    144     {
    145       boost::endian::little_uint16_t size;
    146       boost::endian::little_uint32_t tgt;
    147 
    148       void Validate(FilePosition rem_size, FilePosition size);
    149     };
    150     static_assert(sizeof(FixParams) == 6);
    151 
    152     struct NodeParams
    153     {
    154       boost::endian::little_uint8_t operation;
    155       boost::endian::little_uint32_t value;
    156       boost::endian::little_uint16_t left;
    157       boost::endian::little_uint16_t right;
    158 
    159       void Validate(uint16_t size);
    160     };
    161     static_assert(sizeof(NodeParams) == 9);
    162 
    163     struct Node : Libshit::Lua::ValueObject
    164     {
    165       uint8_t operation = 0;
    166       uint32_t value = 0;
    167       size_t left = 0, right = 0;
    168 
    169       Node() = default;
    170       Node(uint8_t operation, uint32_t value, size_t left, size_t right)
    171         : operation{operation}, value{value}, left{left}, right{right} {}
    172       LIBSHIT_LUA_CLASS;
    173     };
    174 
    175     InstructionJumpIfItem(Key k, Context& ctx, uint8_t opcode, Source src);
    176     InstructionJumpIfItem(Key k, Context& ctx, uint8_t opcode,
    177                           Libshit::NotNull<LabelPtr> tgt, std::vector<Node> tree)
    178       : InstructionBase{k, ctx, opcode}, tgt{tgt}, tree{Libshit::Move(tree)} {}
    179 #if LIBSHIT_WITH_LUA
    180     InstructionJumpIfItem(
    181       Key k, Context& ctx, Libshit::Lua::StateRef vm, uint8_t opcode,
    182       Libshit::NotNull<LabelPtr> tgt, Libshit::Lua::RawTable tree);
    183 #endif
    184 
    185     FilePosition GetSize() const noexcept override
    186     { return 1 + sizeof(FixParams) + tree.size() * sizeof(NodeParams); }
    187 
    188     Libshit::NotNull<LabelPtr> tgt;
    189     LIBSHIT_LUAGEN(get: "::Libshit::Lua::GetSmartOwnedMember")
    190     std::vector<Node> tree;
    191 
    192     void Dispose() noexcept override;
    193 
    194   private:
    195     void Parse_(Context& ctx, Source& src);
    196     void Dump_(Sink& sink) const override;
    197     void Inspect_(std::ostream& os, unsigned indent) const override;
    198     void InspectNode(std::ostream& os, size_t i) const;
    199     void PostInsert(Flavor f) override;
    200   };
    201 
    202   class InstructionJumpSwitchItemNoire : public InstructionBase
    203   {
    204     LIBSHIT_DYNAMIC_OBJECT;
    205   public:
    206     struct FixParams
    207     {
    208       boost::endian::little_uint32_t expected_val;
    209       boost::endian::little_uint16_t size;
    210 
    211       void Validate(FilePosition rem_size);
    212     };
    213     static_assert(sizeof(FixParams) == 6);
    214 
    215     struct ExpressionParams
    216     {
    217       boost::endian::little_uint32_t expression;
    218       boost::endian::little_uint32_t tgt;
    219 
    220       void Validate(FilePosition size);
    221     };
    222     static_assert(sizeof(ExpressionParams) == 8);
    223 
    224     struct Expression : Libshit::Lua::ValueObject
    225     {
    226       uint32_t expression;
    227       Libshit::NotNull<LabelPtr> target;
    228 
    229       Expression(uint32_t expression, Libshit::NotNull<LabelPtr> target)
    230         : expression{expression}, target{std::move(target)} {}
    231       LIBSHIT_LUA_CLASS;
    232     };
    233 
    234 
    235     InstructionJumpSwitchItemNoire(
    236       Key k, Context& ctx, uint8_t opcode, Source src);
    237     InstructionJumpSwitchItemNoire(
    238       Key k, Context& ctx, uint8_t opcode, uint32_t expected_val,
    239       bool last_is_default, Libshit::AT<std::vector<Expression>> expressions)
    240       : InstructionBase{k, ctx, opcode}, expected_val{expected_val},
    241         last_is_default{last_is_default},
    242         expressions{Libshit::Move(expressions)} {}
    243 
    244 
    245     FilePosition GetSize() const noexcept override
    246     { return 1 + sizeof(FixParams) + expressions.size() * sizeof(ExpressionParams); }
    247 
    248     uint32_t expected_val;
    249     bool last_is_default;
    250 
    251     LIBSHIT_LUAGEN(get: "::Libshit::Lua::GetSmartOwnedMember")
    252     std::vector<Expression> expressions;
    253 
    254     void Dispose() noexcept override;
    255 
    256   protected:
    257     InstructionJumpSwitchItemNoire(Key k, Context& ctx, uint8_t opcode)
    258       : InstructionBase{k, ctx, opcode} {}
    259 
    260     void Parse_(Context& ctx, Source& src);
    261     void Dump_(Sink& sink) const override;
    262     void InspectBase(std::ostream& os, unsigned indent) const;
    263     void Inspect_(std::ostream& os, unsigned indent) const override;
    264     void PostInsert(Flavor f) override;
    265   };
    266 
    267   class InstructionJumpSwitchItemPotbb final : public InstructionJumpSwitchItemNoire
    268   {
    269     LIBSHIT_DYNAMIC_OBJECT;
    270   public:
    271 
    272     InstructionJumpSwitchItemPotbb(
    273       Key k, Context& ctx, uint8_t opcode, Source src);
    274     InstructionJumpSwitchItemPotbb(
    275       Key k, Context& ctx, uint8_t opcode, uint32_t expected_val,
    276       bool last_is_default, Libshit::AT<std::vector<Expression>> expressions,
    277       uint8_t trailing_byte)
    278       : InstructionJumpSwitchItemNoire{
    279       k, ctx, opcode, expected_val, last_is_default, Libshit::Move(expressions)},
    280         trailing_byte{trailing_byte} {}
    281 
    282     FilePosition GetSize() const noexcept override
    283     { return 1 + InstructionJumpSwitchItemNoire::GetSize(); }
    284 
    285     uint8_t trailing_byte;
    286 
    287   private:
    288     void Parse_(Context& ctx, Source& src);
    289     void Dump_(Sink& sink) const override;
    290     void Inspect_(std::ostream& os, unsigned indent) const override;
    291   };
    292 
    293   // compile time map of opcode->instruction classes
    294   template <Flavor F, uint8_t Opcode> struct InstructionMap
    295   { using Type = SimpleInstruction<false>; };
    296 
    297   // In POTBB dummy instructions skip one byte...
    298   template <uint8_t Opcode> struct InstructionMap<Flavor::POTBB, Opcode>
    299   { using Type = SimpleInstruction<false, uint8_t>; };
    300 
    301 #define NEPTOOLS_OPCODE(flavor, id, ...) \
    302   template<> struct InstructionMap<Flavor::flavor, id> \
    303   { using Type = __VA_ARGS__; }
    304 #define NEPTOOLS_SIMPLE_OPCODE(flavor, id, ...)        \
    305   NEPTOOLS_OPCODE(flavor, id, SimpleInstruction<__VA_ARGS__>)
    306 
    307   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x01, true);
    308   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x04, true);
    309   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x05, false, uint32_t);
    310   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x06, false, Code*);
    311   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x07, true);
    312   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x0a, false, Code*);
    313   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x0b, false, uint8_t, void*);
    314   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x0c, false, uint8_t);
    315   NEPTOOLS_OPCODE(NOIRE, 0x0d, InstructionRndJumpItem);
    316   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x0e, false, std::string);
    317   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x0f, true,  std::string, std::string);
    318   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x10, false, Tagged, Code*);
    319   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x11, false, Tagged, Code*);
    320   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x12, false, uint32_t, uint8_t);
    321   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x13, false, Tagged, uint8_t, uint32_t, Code*);
    322   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x14, false, Tagged, uint8_t, uint32_t, Code*);
    323   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x15, false, Tagged, Tagged);
    324   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x16, false, Tagged, Tagged);
    325   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x17, false, Tagged, Tagged);
    326   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x18, false, Tagged, Tagged);
    327   NEPTOOLS_OPCODE(NOIRE, 0x19, UnimplementedInstructionItem); // noreturn
    328   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x1a, false, Code*);
    329   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x1b, true);
    330   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x1c, false, uint8_t);
    331   NEPTOOLS_OPCODE(NOIRE, 0x1d, InstructionJumpIfItem);
    332   NEPTOOLS_OPCODE(NOIRE, 0x1e, InstructionJumpSwitchItemNoire);
    333   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x1f, false, Tagged, uint16_t);
    334   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x20, false, uint8_t, void*, void*);
    335   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x21, false, void*, void*);
    336   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x22, false, void*, void*);
    337   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x23, false, void*, void*);
    338   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x24, false, Tagged);
    339   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x30, false, std::string, uint8_t, uint8_t);
    340   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x31, false, uint8_t, uint16_t);
    341   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x32, false, float, uint16_t);
    342   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x33, false, uint32_t, uint8_t);
    343   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x34, false, uint32_t, uint16_t);
    344   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x35, false, uint32_t, uint8_t);
    345   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x36, false, uint32_t, float, uint16_t);
    346   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x37, false, uint16_t);
    347   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x38, false, std::string);
    348   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x39, false, uint16_t);
    349   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x3a, false, uint8_t);
    350   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x3f, false, Tagged);
    351   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x40, false, Tagged, uint16_t, uint8_t);
    352   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x41, false, uint16_t);
    353   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x42, false, uint8_t);
    354   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x43, false, uint16_t, uint16_t, uint16_t, uint8_t);
    355   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x44, false, float, uint16_t, uint8_t, uint8_t);
    356   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x45, false, uint8_t, uint32_t, uint8_t, uint16_t);
    357   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x46, false, uint8_t, uint16_t);
    358   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x47, false, uint8_t, uint16_t, uint16_t, uint16_t, uint8_t);
    359   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x48, false, uint8_t, uint16_t, uint16_t, uint16_t,  uint8_t);
    360   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x49, false, uint8_t, float, uint16_t, uint8_t, uint8_t);
    361   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4a, false, uint8_t, uint8_t);
    362   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4b, false, uint8_t, uint8_t, uint16_t);
    363   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4c, false, uint8_t, uint32_t);
    364   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4d, false, uint8_t, uint8_t);
    365   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4e, false, uint8_t, float, float, uint16_t);
    366   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x4f, false, std::string);
    367   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x50, false, uint16_t, uint16_t, std::string);
    368   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x51, false, uint8_t);
    369   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x53, false, uint8_t);
    370   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x54, false, uint8_t, uint8_t);
    371   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x55, false, uint8_t);
    372   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x57, false, uint8_t, uint16_t);
    373   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x58, false, uint8_t, uint16_t);
    374   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x59, false, uint8_t, uint8_t, uint8_t, uint8_t);
    375   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5a, false, uint32_t);
    376   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5b, false, uint8_t);
    377   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5c, false, uint32_t, uint8_t);
    378   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5d, false, uint8_t, uint16_t);
    379   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5e, false, uint8_t, uint8_t);
    380   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x5f, false, uint16_t, uint8_t, uint8_t);
    381   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x60, false, Tagged, uint8_t, uint8_t);
    382   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x61, false, uint32_t);
    383   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x62, false, std::string);
    384   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x63, false, uint8_t);
    385   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x64, false, uint8_t);
    386   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x65, false, uint8_t);
    387   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x66, false, uint8_t);
    388   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x67, false, uint32_t, Tagged);
    389   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x68, false, uint32_t);
    390   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x69, false, uint8_t, uint32_t, std::string);
    391   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6a, false, uint16_t, uint8_t);
    392   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6b, false, uint8_t);
    393   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6c, false, uint32_t);
    394   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6d, false, uint8_t);
    395   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6e, false, Tagged);
    396   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x6f, false, std::string, uint8_t);
    397   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x70, false, uint32_t);
    398   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x71, true, Tagged);
    399   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x73, false, std::string);
    400   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x74, false, uint16_t);
    401   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x75, false, uint16_t, uint8_t);
    402   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x76, false, uint8_t, Tagged);
    403   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x77, false, uint8_t, std::string);
    404   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x78, false, uint16_t);
    405   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x79, false, uint8_t);
    406   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7a, false, Tagged);
    407   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7b, false, uint8_t);
    408   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7c, false, uint32_t);
    409   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7d, false, std::string);
    410   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7e, false, uint8_t, uint32_t);
    411   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x7f, false, uint16_t, uint8_t);
    412   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x80, false, uint32_t, std::string);
    413   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x81, true);
    414   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x82, false, uint32_t, uint32_t, Tagged);
    415   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x83, false, uint32_t, Tagged);
    416   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x84, false, Tagged);
    417   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x87, false, uint16_t, uint8_t);
    418   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x88, false, uint16_t, Tagged);
    419   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x89, false, uint8_t, uint8_t);
    420   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8a, false, uint8_t, Tagged);
    421   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8b, false, uint8_t, Tagged);
    422   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8c, false, uint32_t, uint32_t, Tagged);
    423   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8d, false, uint8_t);
    424   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8e, false, Tagged);
    425   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x8f, false, Tagged);
    426   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x90, false, Tagged);
    427   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x91, false, Tagged);
    428   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x92, false, Tagged);
    429   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x93, false, std::string, uint8_t, Tagged);
    430   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x94, false, Tagged);
    431   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x95, false, std::string, uint8_t);
    432   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x96, false, uint8_t);
    433   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x97, false, uint8_t);
    434   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x98, false, uint16_t, Tagged);
    435   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0x99, false, Tagged);
    436   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa0, false, void*);
    437   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa1, false, uint8_t, void*, uint16_t, uint16_t);
    438   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa2, false, uint16_t, void*, uint16_t, uint16_t);
    439   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa3, false, std::string);
    440   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa5, false, void*);
    441   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa6, false, uint8_t, void*, uint16_t, uint16_t);
    442   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa7, false, uint8_t, uint8_t);
    443   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa8, false, uint8_t, Tagged);
    444   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xa9, false, Tagged);
    445   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xaa, false, Tagged);
    446   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xab, false, Tagged);
    447   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xb0, false, uint16_t);
    448   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xb1, false, uint16_t, Tagged);
    449   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xb3, false, uint16_t, Tagged);
    450   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xb4, false, uint16_t);
    451   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xb5, false, uint8_t);
    452   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd0, false, uint32_t, uint8_t);
    453   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd1, false, uint32_t, uint8_t, uint8_t);
    454   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd2, false, uint32_t, uint8_t, uint8_t, float);
    455   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd3, false, uint32_t, uint8_t);
    456   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd4, false, uint32_t, uint8_t);
    457   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd5, false, uint32_t, uint16_t, float, float, float, float, uint8_t);
    458   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd6, false, uint32_t);
    459   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd7, false, uint32_t, float, float, float, float, uint16_t, uint8_t);
    460   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd8, false, uint8_t, uint8_t, float, float, float, float, uint16_t, uint8_t);
    461   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xd9, false, uint32_t, uint8_t);
    462   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xda, false, uint8_t);
    463   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xdb, false, uint8_t, uint16_t, uint8_t, uint8_t, float, uint8_t);
    464   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xdc, false, uint8_t);
    465   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xdd, false, uint32_t);
    466   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xdf, false, uint8_t);
    467   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf0, false, uint8_t, Tagged);
    468   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf1, false, uint8_t, uint16_t);
    469   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf2, false, uint8_t, std::string);
    470   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf3, false, uint8_t, uint8_t);
    471   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf4, false, std::string);
    472   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf5, false, uint16_t, uint8_t);
    473   NEPTOOLS_SIMPLE_OPCODE(NOIRE, 0xf7, false, uint16_t, uint8_t);
    474 
    475   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x00, false); // Nop
    476   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x01, true);  // Exit
    477   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x02, true);  // Cont
    478   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x03, false, uint8_t /*ignored*/); // Endv
    479   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x04, true);  // InfiniWait (infinite loop)
    480   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x05, false, uint32_t); // VWait
    481   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x06, false, Code*); // Goto (actually, call)
    482   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x07, true);  // Return
    483   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x08, false); // RetAddrPush
    484   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x09, false); // RetAddrPop
    485   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x0a, false, uint32_t /*ignored*/); // Call1V
    486   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x0b, false, uint8_t, void*); // SubStart
    487   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x0c, false, uint8_t); // SubStop
    488   NEPTOOLS_OPCODE(POTBB, 0x0d, InstructionRndJumpItem); // RndJump
    489   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x0e, false, std::string /*ignored*/); // Printf
    490   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x0f, true,  std::string); // FileJump
    491   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x10, false, Tagged, Code*); // IsFlg
    492   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x11, false, Tagged, Code*); // NgFlg
    493   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x12, false, Tagged, uint8_t); // FlgSw
    494   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x13, false, Tagged, uint8_t, Tagged, Code*); // IsPrm
    495   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x14, false, Tagged, uint8_t, Tagged, Code*); // NgPrm
    496   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x15, false, Tagged, Tagged); // SetPrm
    497   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x16, false, Tagged, Tagged); // SetPrmWk
    498   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x17, false, Tagged, Tagged); // AddPrm
    499   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x18, false, Tagged, Tagged); // AddPrmWk
    500   // Tagged, Code*... (unknown count, impossible to determine)
    501   NEPTOOLS_OPCODE(POTBB, 0x19, UnimplementedInstructionItem); // noreturn, PrmBranch
    502   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x1a, false, Code*); // Call
    503   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x1b, true); // CallRet
    504   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x1c, true, uint8_t); // SubEndWait
    505   NEPTOOLS_OPCODE(POTBB, 0x1d, InstructionJumpIfItem); // JumpIf
    506   NEPTOOLS_OPCODE(POTBB, 0x1e, InstructionJumpSwitchItemPotbb); // JumpSwitch
    507   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x1f, false, Tagged, uint16_t); // RandPrm
    508   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x20, false, uint8_t, void*, void*); // DataBaseParam
    509   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x21, false, uint16_t); // CourseFlag
    510   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x22, false, uint16_t); // SetNowScenario
    511   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x23, false, uint16_t); // CharEntry
    512   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x24, false, uint16_t); // CrossFade
    513   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x25, false, uint8_t, uint16_t, uint8_t); // PatternCrossFade
    514   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x26, false, uint8_t); // DispTone
    515   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x27, false, uint8_t); // Monologue
    516   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x28, false, uint16_t, uint8_t /*unused*/, uint8_t, uint16_t, uint16_t, uint16_t, float, uint8_t); // ExiPlay
    517   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x29, false, uint8_t /*unused*/, uint8_t); // ExiStop
    518   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2a, false, uint8_t, uint8_t, uint8_t, uint16_t, uint8_t); // PatternFade
    519   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2b, false, float, uint8_t, uint8_t); // Ambiguous
    520   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2c, false, float, float, uint16_t); // AmbiguousFade
    521   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2d, false, uint32_t /*unused*/); // TouchWait
    522   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2e, false, Tagged, uint16_t); // CourseFlagGet
    523   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x2f, false, uint16_t); // Chapter
    524   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x30, false, std::string, uint8_t, uint8_t); // Movie
    525   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x31, false, uint8_t, uint16_t); // BgmPlay
    526   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x32, false, float, uint16_t); // BgmVolume
    527   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x33, false, uint32_t, uint8_t); // SePlay
    528   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x34, false, uint32_t, uint16_t); // SeStop
    529   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x35, false, uint32_t, uint8_t); // SeWait
    530   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x36, false, uint32_t, float, uint16_t); // SeVolume
    531   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x37, false, uint16_t); // SeAllStop
    532   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x38, false, std::string); // VoicePlay
    533   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x39, false, uint16_t); // VoiceStop
    534   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x3a, false, uint8_t); // VoiceWait
    535   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x3b, false, Tagged); // VoiceVolumePlay
    536   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x3e, false, uint32_t /*unused*/); // BackLogReset
    537   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x3f, false, Tagged); // GetCountry
    538   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x40, false, uint32_t, uint16_t, uint8_t); // BgOpen
    539   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x41, false, uint16_t); // BgClose
    540   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x42, false, uint16_t, uint16_t); // BgFrame
    541   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x43, false, uint16_t, uint16_t, uint16_t, uint8_t); // BgMove
    542   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x44, false, float, uint16_t, uint8_t, uint8_t); // BgScale
    543   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x45, false, uint8_t, uint32_t, uint8_t, uint16_t); // BustOpen
    544   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x46, false, uint8_t, uint16_t); // BustClose
    545   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x47, false, uint8_t, uint16_t, uint16_t, uint16_t, uint8_t); // BustClose
    546   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x48, false, uint8_t, uint16_t, uint16_t, uint16_t /*unused*/, uint8_t); // BustMoveAdd
    547   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x49, false, uint8_t, float, uint16_t, uint8_t, uint8_t); // BustScale
    548   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4a, false, uint8_t, uint8_t); // BustPriority
    549   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4b, false, uint8_t, uint8_t, uint8_t, uint16_t); // BustQuake
    550   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4c, false, uint8_t); // SetEntryCharFlg
    551   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4d, false, uint16_t /*unused*/); // BustTone
    552   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4e, false, uint8_t, float, float, uint16_t); // BustFade
    553   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x4f, false, std::string); // Name
    554   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x50, false, uint16_t, uint16_t, std::string, uint8_t, uint16_t); // Message
    555   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x51, false, uint8_t); // MessageWait
    556   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x52, false); // MessageWinClose
    557   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x53, false, uint8_t); // MessageFontSize
    558   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x54, false, uint16_t, uint16_t); // MessageQuake
    559   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x55, false, uint8_t); // Trophy
    560   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x56, false); // MessageDelete
    561   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x57, false, uint16_t, uint16_t); // Quake
    562   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x58, false, uint8_t, uint8_t, uint16_t); // Fade
    563   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x59, false, Code* /*guess*/, std::string, uint16_t); // Choice
    564   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5a, true);  // ChoiceStart
    565   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5b, false, Tagged); // GetBg
    566   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5c, false, uint16_t); // FontColor
    567   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5d, false, uint8_t); // WorldType
    568   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5e, false, Tagged); // GetWorld
    569   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x5f, true, uint16_t); // FlowChart
    570   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x60, true, std::string); // MiniGame
    571   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x61, false, Tagged, uint16_t); // CourseOpenGet
    572   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x62, false); // SystemSave
    573   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x63, false, uint8_t); // BackLogNg
    574   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x64, false, uint8_t); // EventSkipNg
    575   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x65, false, uint8_t); // EventAutoNg
    576   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x66, false, uint8_t); // StopNg
    577   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x67, false); // DataSave
    578   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x68, false); // SkipStop
    579   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x69, false, std::string, std::string); // MessageVoice
    580   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x6a, false, std::string, std::string); // MessageVoice2
    581   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x6b, false, uint8_t); // SaveNg
    582   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x6f, false, std::string, uint8_t); // Dialog
    583   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x70, false, uint16_t, uint8_t); // ExiLoopStop
    584   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x71, false, uint16_t, uint8_t); // ExiEndWait
    585   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x72, false, uint8_t); // ClearSet
    586   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x73, false, std::string); // SaveTitleSet
    587   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x78, false, uint16_t); // VideoFlg
    588   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x79, false, uint16_t, uint16_t /*unused*/); // AlbumFlg
    589   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x7a, false, uint8_t); // WaitFlg
    590   NEPTOOLS_SIMPLE_OPCODE(POTBB, 0x7b, false, uint8_t); // AudioFlg
    591 
    592 
    593 #undef NEPTOOLS_OPCODE
    594 #undef NEPTOOLS_SIMPLE_OPCODE
    595 
    596   template <Flavor F, uint8_t Opcode>
    597   using InstructionItem = typename InstructionMap<F, Opcode>::Type;
    598 }
    599 
    600 #endif