TLDR:

Setting up YGOpen into my project was a lot of deju-vue only this time more frustrating. I was able to get .pb files set up from the protobuf definitions, dealt with a lot of annoyances getting the .dll for the YGOpen built, only to then deal with more annoyances getting it properly connected with CGO. Eventually, I got a simple C++ API laid out and the system built with connections to the YGOpen library. Currently at a working duel loop that can handle phase transitions of passing turn back and forth.

Protocol

Now that I’ve got a better understanding of Protoc, I really appreciate it’s use. I was able to produce the go .pb files using this code:

package ygopenpb

//go:generate protoc --proto_path=../../ygopen/include/ygopen/proto --go_out=. --go_opt=paths=source_relative --go_opt=Mdeck.proto=github.com/spb8026/ygo-visualizer/ygopenpb --go_opt=Mbanlist.proto=github.com/spb8026/ygo-visualizer/ygopenpb --go_opt=Mduel_data.proto=github.com/spb8026/ygo-visualizer/ygopenpb --go_opt=Mduel_msg.proto=github.com/spb8026/ygo-visualizer/ygopenpb --go_opt=Mduel_answer.proto=github.com/spb8026/ygo-visualizer/ygopenpb duel_data.proto duel_msg.proto duel_answer.proto

YGOpen Build

Alot of struggle getting this to work and properly connected to my Go bridge. I eventually was able to use MSYS2 and Ninja to get the libygopen.a file built. Did a lot of restructuring to try to settle on how I want the dependencies of this project to work, especially since I was struggling to get ygopen to work without the source code. The current file layout is as follows:

Encoder Implementation

ygo_duel_step in bridge.cpp:

  1. Calls OCG_DuelProcess to advance the engine
  2. On AWAITING or END, calls OCG_DuelGetMessage to get the raw buffer
  3. Iterates the buffer: each message is prefixed with a 4-byte LE length
  4. For each message, calls YGOpen::Codec::Edo9300::OCGCore::encode_one(arena, context, ptr)
  5. On OK: serializes the Msg* to string and pushes to encoded_msgs
  6. On SWALLOWED: skips, no message stored
  7. On UNKNOWN: skips

ygo_duel_next_msg pops messages from encoded_msgs one at a time.

The arena is reset at the start of each step to prevent accumulation.