Open hjri opened 2 years ago
Thanks for checking it out!
opening web interface gives an error since /list endpoint returns ] instead of []
I knew this would be an issue, it shouldn't effect functionality but i've fixed it anyway. Let me know if it's fixed for you.
Rest of the UI seemingly also breaks as buttons seemingly just refresh page (i.e. submit a form).
This is as designed, it returns back to the main page after submitting. Currently there is no "api" setup to monitor if and what card is currently inserted, it's planned but very low right now. Similarly the site is designed to show an image of a generated card which is a WIP on the prt
branch.
Having an API would be really REALLY nice. Unfortunately I can't really help with the code (as much as I wish I could) since I have zero knowledge in C++, but I might end up reimplementing emulator in JS (node).
My general idea is to make a drop-in replacement for actual WMMT3 machines that uses RFID/NFC/IC cards instead of paper-magnetic ones, while storing card data on a server.
Just so that I can stop bothering arcade owner to turn on the card reader :DDDDD (since it's freeplay)
(and hopefully maybe make F-Zero AX and Mario Kart GP more playable at same time)
Having an API would be really REALLY nice. [...] but I might end up reimplementing emulator in JS (node).
What else would you like to see? Card status is planned and is trivial to implement when I have motivation.
(and hopefully maybe make F-Zero AX and Mario Kart GP more playable at same time)
These 2 should be playable as is, but I don't own them to test, as well as iDOLM@STER.
I could potentially test F-Zero and Mario Kart if we manage to get the wiring for it.
What else would you like to see?
I'm not entirely sure how emulator works regarding card write limits or if changing the load status requires machine restart or not but here's some suggestions:
My idea of new flow would be:
Biggest question for me right now - does emulator handle card expiration at all, i.e. does "card data" means actual card dump and after card is "used up" you need to unload it manually and it changes the file automatically as it "dispenses" new card? Or "card data" is a save file and either hacks card use counter or handles expiration process automatically?
I think the biggest issue right now is documentation.
Set/unset "dispenser empty" If NFC card is scanned it requests emulator to set dispenser to "full" and load the given file (creating one if needed)
It's possible to expose this, but I'm not sure how games will handle having the dispenser depleted and filled while running. I guess it would depend per-game how it handles that, and if it doesn't handle it well then you'd need to restart the machine or enter test mode and go back.
webhook/hup signal to a given PID to indicate that card needs to be taken out (i.e. to signal "card master" controller program that it needs to move card data to a backup or to "reset" the NFC reader) card/emulator status api or webhook/pubsub/websocket
I think I want to avoid over complicating things by adding dependencies to handle sockets, etc. So at most I'd be able to offer more of what's on the site backend with more documentation so you can do what you need to do via http requests.
api to (re)load card data
I'm not quite sure what you mean. Currently the emulator creates 1-3 files on the specified folder being card.bin
appended with .track_1
through 3. When the game ejects the card we automatically (can be changed) "grab" the card and tell the game the card it's removed. Once the player wants to reinsert the card, the data is read again from the specified file. There's no cache when there's nothing in the machine.
Biggest question for me right now - does emulator handle card expiration at all, i.e. does "card data" means actual card dump and after card is "used up" you need to unload it manually and it changes the file automatically as it "dispenses" new card? Or "card data" is a save file and either hacks card use counter or handles expiration process automatically?
We don't do any type of hacking on the card data (tho possible depending on game - i've mostly RE'ed the MT2 struct but that's out of scope). When a card is used up it simply ejects the card and writes the expired card data to the fs, then the games themselves will issue the dispense command (as the tray will be empty now) and write the new card data over the expired card.
I could potentially test F-Zero and Mario Kart if we manage to get the wiring for it.
I'd love that.
Wiring:
J3 on Triforce to Female 9-pin D-sub that connects to USB Serial Adapter:
Pin 3 [or 8] (GND) - Pin 5 (GND)
Pin 4 (TXD) - Pin 2 (RXD)
Pin 5 (RXD) - Pin 3 (TXD)
Bridge pin6 (RTS), and 7 (CTS) together on the Triforce side
I think I want to avoid over complicating things by adding dependencies to handle sockets
websockets is probably the easiest/most convenient way of having programmable two-way communication tho. Regular HTTP API is one-way only and to listen for events you'd need to poll it regularly, which might not be something you'd want on an "embedded" kind of system.
and write the new card data over the expired card.
so, basically the expired card is essentially discarded and same save file is used for newly dispensed card? Yeah that seems fine, but it would also be cool to somehow save the expired card data, since they aren't really expired, just at end of their lifespan, and still have at least 5 uses remaining, which WMMT3 uses for "bring a friend" kind of thing: https://wanganmidnight.fandom.com/wiki/Discarded_tuning_card
It's possible to expose this, but I'm not sure how games will handle having the dispenser depleted and filled while running. I guess it would depend per-game how it handles that, and if it doesn't handle it well then you'd need to restart the machine or enter test mode and go back.
Yeah, I don't know either but we could also test that. Potentially real-life solution could wire into machine itself as well to reset. Arcade I'm doing this for has Mario Kart GP (seemingly has card reader but no cards), F-Zero AX (no card reader (only game cube memory card slot), owner tells me cards are practically unobitanium), and Maxi3DX+ we could test how games react to different emulated situations, but we'll need some way to set emulator state in real time, if not websockets then some command prompt could make do.
but we'll need some way to set emulator state in real time
This is already possible via http get actions. I've added the ability to change the dispenser status via them as well. For documentation purposes....
http://127.0.0.1/actions?
cardname=name.bin
insert
remove
dispenser=true/false
list
it would also be cool to somehow save the expired card data
You'd have to keep copies of every write, there's no way to know what one is a expired card unless you work on RE'ing the card structure (and add custom handling, oos).
I've added the ability to change the dispenser status via them as well.
nice!! thank you!
You'd have to keep copies of every write
keeping copies every time would probably be even better tbh.
there's no way to know what one is a expired card
not exactly, it's a bit game specific, but you could just have a timeout/amendment mechanism, i.e.
IIRC Maxi3DX+ will refuse to use card that's about to expire if dispenser is empty.
also, just a thought - since game prints human-readable information on card itself that could be used to determine card status, i.e. it changes "name" segment to some of the predefined strings, i.e. "Disused Card" "プレゼントカード" (present card), it also changes "mileage" and "password" section to instructions, at least for present card.
Just tested WMMT3DX+ and F-Zero. Wiring was kinda flimsy (i used jumper wires on the male DB9 connector directly - not very reliable but should work for testing)
Couldn't get ANY response out of WMMT3DX+ no matter how we wired them, just nothing - debug logs never shown anything as if it's not connected. I suspect it miiiight be using different serial protocol or different baud settings (?) or something else entirely. Machine just shown error i think E51 during POST when it got to card reader testing.
F-Zero AX however did get some response - but game refused to start - self test in the menu fails and just straight up booting the game gets card reader error. Here's a dump of things:
[info] Starting API server...
[debug] SerIo::Read:
[debug] 02 06 40 00 00 00 03 45 02 06 40 00 00 00 03 45 02 06
[debug] CardIo::ReceivePacket:
[debug] 40 00 00 00
[debug] SerIo::SendAck: 06
[debug] SerIo::Read:
[debug] 02 06 40 00 00 00 03 45 02 06 40 00 00 00 03 45 02 06 40 00 00 00 03 45
[debug] CardIo::ReceivePacket:
[debug] 40 00 00 00
[debug] SerIo::SendAck: 06
[debug] CardIo::ReceivePacket:
[debug] 40 00 00 00
[debug] SerIo::SendAck: 06
[debug] CardIo::ReceivePacket:
[debug] 40 00 00 00
[debug] SerIo::SendAck: 06
F-Zero: It doesn't make much sense to me that it we wouldn't reply to a 0x40 (cancel), but it looks like that's what it's expecting or it's not sending the ACK. I've tested it in MT2 and it "works" but causes a delay in moving to the new screen to create a card (it issues this on the page where it asks you if you have a card).
MT3DX+: I'm not sure about this. I know for a fact it works for the TeknoParrot guys during their testing but they don't connect to it via a normal serial connection. If it were only baud rate it should likely produce garbage but you're not seeing that.
I've created a new branch skip_40_b
which skips 0x40 and adds a new config.ini
value for baud rate.
Edit: Testing on MT3 skipping 0x40 causes the game to lockup. So something very strange is happening with F-Zero.
cfgetispeed(&local_50);
cfgetospeed(&local_50);
iVar1 = *(int *)(this + 0x14);
if (iVar1 == 1) {
in_buad = 0xe;
out_baud = 0xe;
}
else if (iVar1 == 2) {
in_buad = 0xf;
out_baud = 0xf;
}
else {
in_buad = 0xd;
out_baud = 0xd;
if (iVar1 != 0) {
return 0;
}
}
[...]
cfsetispeed(&local_50,in_buad);
cfsetospeed(&local_50,out_baud);
If I follow this correctly it should only be possible for N2 to set 9600, 19200, and 38400 baud on the serial port.
While chatting with derole we found out that it's 38400b by default for MT3. I've pushed my changes to the main branch. F-Zero I'm still not sure what that could be, perhaps RTS/CTS not being bridged, not sure.
Last time we tried f-zero again it didn't work at all so i'm assuming it could easily be wiring issue, after all i'm just sticking female header of a jumper wire into male DB9 socket, it should work but I guess not as reliable, to eliminate wiring issue i'm waiting for a DB9 breakout adapter to arrive, we'll make proper harnesses and stuff, but it'll take time, probably 2 weeks.
Meanwhile I'll try contributing proper API and more debugging logging for the future.
F-Zero and MT3 are issues with parity. Both appear to use even parity. I've created a new branch that's not ready to be merged as fix/settings_work
, this exposes parity via config.ini.
See: https://github.com/GXTX/YACardEmu/tree/fix/settings_work#info
Just testing this program with a disconnected serial adapter (i don't have an arcade machine but plan on making some public-arcade-ready solution for someone) and just opening web interface gives an error since
/list
endpoint returns]
instead of[]
. Rest of the UI seemingly also breaks as buttons seemingly just refresh page (i.e. submit a form).built myself on debian linux x86-64