I’ve made a start on the packets required to display other players and NPC’s in game. It appears that the server is responsible for the AI of the NPC. An archived page from the MPS website (the system that SBOL runs on) indicates that Genki used Server+ and AI. I can’t imagine that the data to be sent from the server informs the NPC how to act live during the race. I can’t see a service back in 2003 being able to cope with 1000’s of players while calculating all NPC actions also. I suspect the server instead just provides some values and the NPC acts according based on these values. The packet responsible for spawning a player/NPC is 0x0480 and the packet for movement is 0x0780.
The player sends 0x0400 packets to the server when it changes from safemode and entering shops. This packet isn’t meant to have a response. The usual response to SBOL packets is +0x80 from the received packet. eg Client authenticates with 0x0100 and expects a 0x0180 back. There are some packets that differ from this. and 0x0400 and 0x0700 are amongst these. The 0x0700 packet received from the player is their position. However it contains floats and the returning 0x0780 packet expects shorts (although maybe the client is casting the memory for the shorts received as floats in memory later on). Spawning an NPC with 0x0480 and then moving it with 0x0780 makes it move on the map. However the NPC is nowhere to be seen on the course itself. So must be missing something from these packets.
The 0x0480 contains a 16 character string (the handle), a handful of Short’s, Int’s and Bytes with 3 structures. 2 structures that are 0x6C and another 0x0E in size. 0x6C is the same size for the team data. So it could be this (although why would the other players need to know this information. Surely they only need to know if you’re in a team and if so its name). The Car data structure is 0x60 in size and this has got to be in the packet. So far I’ve not managed to confirm where it is expected in the packet. However the first 3 ints of the 2nd 0x6C structure when the type is set to NPC is the Rival Group and the Rival Number (0-7). The other Int I suspect is the Car ID. Which conveniently leaves 0x60 bytes which matches the car detail size. The 0x0E structure contains the spawn location and type. The location utilizes 2 shorts. there are another 2 which will notify you when they spawn so this would be used if a player joins while you’re already in the course and then a single byte which is used to specify the type. 2 or above indicates NPC and this value needs to be below 0x20 or the packet is ignored. 0 indicates player (yourself. Not used), 1 another player. This leaves 5 remaining bytes of the structure that I need to work out.
The NPC status (Not raced (Blue), Lost (Red) and Won (Green) are pulled from the data sent in the 0x0C81 packet)