Planet Ring

EarthCall Project

Introduction

EarthCall Project is the codename of a project to create a functional server of the online videogame Planet Ring of the Sega Dreamcast.
Server is open-sourced and licensed with the Afflero GPL.

The game Planet Ring supports VGA, keyboard (on port B), microphone (port A2) and VMU. It uses 12 blocks to save the User Profile.
It has 50/60Hz selector and is in various languages.

More info in here: https://sourceforge.net/projects/earthcall-project/

Encryption:

The game DOES NOT use any encryption system in any part of the game.

General Packet Format

A typical structure of a packet follows this rule:

XX(:P):\0
where:
XX->Command of the packet (ej: SU ).
P-> Arguments (they can be 0, 1 or multiple arguments. Between them they always use the symbol ":" as separation).
\0-> A packet always ends with a null character (0), preceded by : after the last argument

Packet data always ends with a null character (0). This ensures there's a clear separation between the variable delimiter (:) and the end of data flag.

Protect Code (Secret Code)

To prevent piracy, every game had a unique serial code. This code came when the user buys the game. Maybe it can be used as a recovery account system…
We still don't know the Generation System… but all codes are 10 Capital Letters.

Valid examples:

UGKVVLTMNF
AJCCBPRMFB
FKERBOPLIO
UOQLUPQPNH

Connection Initialization:

-Game only works with MODEM, and it needs DIAL TONE
-Original server direction is "master.ring.dream-key.com". We have to create a tool to change easily the IP to our server.
-For PC-DC users: set AUTOMATIC DNS (0.0.0.0) and use a software like "Dual Server" to easily redirect DNS.
-Game connects to that IP with a TCP port 7641
-With an ACK packet (of TCP connection) the game accepts the connection.

Then, the game asks for Username sending the "SU:" command.

After sending the SU:user, if it doesn’t exist the server sends “NP:” to create a new profile. While creating the profile the server might send error messages like these (DU: EU: NG).

If the user exists the server sends “CP:” for the user to enter the password. If password is wrong, the server sends “EP:”.

Once everything is fine, the game sends CU and awaits confirmation from the server (OK:ip:port:).

This welcomes the client to Planet Ring and saves data to the visual memory unit. The client sends an OT command (Move Request). After that, the server sends GO:ip32bitsignedint:7641: .

The client sends another OT:, server needs to send another GO, to which the client responds with IN:user:place which is confirmed by OK:m_tables:n_visitors This moves the user finally to the planet.

Note: There is a debug address: "ringgate.dkey.co.uk", but Planet Ring doesn't use it.

Once Logged In:

Upon entering an attraction the client sends requests AQ:username: on 7641 TCP and others on various UDP ports depending on the attraction:

-WORLD: 7649 -> UQ:neoblast:0:
-INFORMATION CENTER: 7650 -> UQ:neoblast:0:
-SPLASH: 7651-> UQ:neoblast:0: TQ:neoblast:-1:
-BALL BUBBLE: 7652-> UQ:neoblast:0: TQ:neoblast:-1:
-SOAR 7653 -> UQ:neobalst:0: TQ:neoblast:-1:
-DOROBO 7654 -> UQ:neoblast:0: TQ:neoblast:-1:

Also every X seconds it sends al AL command, presumably to ask for the client data for messenger and/or table status.

Once in the attraction the user sends AQ, the server needs to send an AR:maxtables:0: . Then the client will expect as many TR as the number specified in the last command (and will show that number of tables). Each one of them needs to have different table id, or they will all render in the same place.

About maintenance mode

There is an important question about latency. PR is very sensitive to latency between some packets relating to rendering table. Here are some facts we discovered:

  • By default, if NO UDP ( and no AR:maxtables:0: ) packets are sent, Planet Ring will render about 105 tables per attraction, well positioned, and default status FULL!
  • We suspect that on login phase, the game has to prepare internal variables to render tables. If it does not have time, all tables will be rendered on the same place!
  • Also, Planet Ring has a cache of the position of the tables, even when a user disconnects and reconnects online!!
  • If a player exits, and then reenters immediately to an attraction, the TR commands are ignored.
  • If a player exits from an attraction and PR shows an "Attraction maintenance" message to the user, then the nº of tables (AR value) will be repainted correctly and status FULL!! That mode is when game can't access to the world (WHITE SCREEN).
  • Even if they are rendered OK, if we set too many tables (like 50 or 100), some tables does not appear (TR latency). Seems that this fact also happened in Original Server, too.

Joining Tables

When the client sends a TI:user:place: command, the server should send TA: . Similar with TO and TL.
TS Commands are a must to set players name, and let the game know about them.
When there's a change in Table status (player joins, game start)… , server have to resend TR status to ALL the players that are inside the attraction.

Ports (Verified)

Info and General
TCP 7641 (client does the connection)
TCP 8001 (TEML - Info board)

Client Info
UDP 7648 (CLIENT RECEIVES IN THIS PORT EVERYTHING FROM SERVER)

Parts of the Game
COMUDP 7649
INFOUDP 7650
KOSEUDP 7651
BUBBUDP 7652
SOARUDP 7653
INTRUDP 7654

VoIP
UDP 1285 (VoIP Negotiation)
UDP 1028 (VoIP Data)

Commands list

- Still incomplete, but gives a general view of the server functionalities. There are TCP commands and UDP ones.
- Minimal time between messages: 50 ms.
- loginid means the UserName.

TCP Client -> Server (Login and Info)

SU:%s: (Verified)
SUBMIT USER (loginid)
To login on the system.

CU:%s:%s:%d: (Verified)
CHECK USER (username:password:ringversion)
ringversion value: 0 if no microphone, 1 if has microphone
Asks server for confirmation.

OT:%s:%d: (Verified)
OUT / MOVE TO (loginid:targplace)
Command is sent after OK and when you go to the planet.
targetplace indicates where you want to go:

0 -> Door (Exit)
1-> Info Center
2-> Planet
10-> Splash
11-> Ball Bubble
12-> Soar
13-> Dream Dorobo

NU:%s:%s:%s::%d:%d:%s:%d:%d:%s:%d:%d:%d:%d: (Verified)
NEW USER (loginid:password:protectcode:name:age:boy(0)/girl(1):region:body and clothes color:language:birthdate:inteligence:amability:aspect:ringversion)

I.e: NU:Neo:1234:AAAAAAAAAA::0:1:CAMBRIDGE:460548:1025:20001231:25:81:49:1:

IMPORTANT: Planet Ring lefts field "name" empty, and puts "age" with value 0!!

PQ:%s: (Verified)
PLAYER QUERY (loginid)
Ask server for PROFILE VIEW when trying to modify the profile in the counter, it waits for a PR:

PM:%s:%s:%d:%s:%d:%d:%d:%d:%d:%d: (Verified)
PLAYER MODIFY (loginid:password:boy(0)/girl(1):region:body and clothes color:language:birthdate:inteligence:amability:aspect)
Modify player settings to save them in the database

RO:%s: (Verified)
RING OUT (loginid)
Client disconnects.

IN:%s:%d: (Verified)
ENTRY REQUEST (loginid:targplace)
Command is sent by client after GO with parameters, it needs to be confirmed by the server with OK:m_tables:n_visitors
Or else there will be an “attraction under maintenance” error message.

TCP Client -> Server (Inside World)

TRO:%s:%d: (Verified)
TABLE RING OUT (loginid,nowtable)
Client disconnects from the 'nowtable' attraction and logouts.

AQ:%s: (Verified)
Attraction query (loginid)
When user enters into an attraction, client asks for attraction max tables data (TCP 7641). Server must reply with AR with the number of available tables.

TI:%s:%d: (Verified)
TABLE IN (loginid:tableid (int) )
Client says to the Server that he joins into the Table. Reply with TA if OK.

TO:%s:%d: (Verified)
TABLE OUT (loginid:tableid (int) )
Client says to the Server that he left the Table. Reply with TL if OK.

GQ:%s:%d: (Verified)
GAME QUERY (loginid, tableid)
Client asks Server to start the game.

GE:%s:%d: (Verified)
GAME EXIT (loginid,actualTable) Clients sends to server when it exits an attraction. Server should then send GX.
If User exits using Start+A+B+X+Y+L+R, also sends a GE :)

TCP Server-> Client (Login)

DU: (Verified)
DUPLICATED USER (User is already in use)

CP: (Verified)
CHECK PASSWORD (asks client for the password)

NP: (Verified)
NEW PROFILE/PLAYER (on client it appears a Dialog where he/she creates the profile).

EN: (Verified)
ERROR NAME (Error on Username - command not used)

EP: (Verified)
ERROR PASSWORD

EU: (Verified)
ERROR USER (ID exists)

GO:%s:%s: (Verified)
GO OTHER (ip,port)
This needs to be send after any (OT:user:place) the client sends, then the client sends IN:user:place which needs to be confirmed by the server with OK:

Forces a player to go to the Info Center and change the server IP.

OK:%s:7641: (Verified)
With that command, client receives a WELCOME TO PLANET RING. In this moment it saves into VMU.
The IP should be the IP of our server but in 32-bit format signed integer.

i.e: 192.168.1.34 -> -1062731486

OK: (Verified)
Without arguments, is used to confirm a previous client movement of server. It has to be sent after IN:user:place

To avoid merged tables use:

OK:%i:%i (Verified)
First argument is max tables in attraction
Second argument is number of visitors

PR:%s: (Verified)
PROFILE RECEIVED (loginid:sex:region:colors:language:birthdate:inteligence:kindness:lookness:dt_first:dt_latest)
Returns profile to the client after login and after player sends PQ:. Without arguments, it sends a profile reset.

See "PROFILE DATES" for more info how to send them.

GS:%s:%s:%s:%s:1:%s:(1,username,ip) (Verified)
GAME START (idtable:status:numplayers:maxplayers:1:minplayers:(info):)
Gives Client the order to load the minigame.

idtable: Integer, starts from 0.
status: Must be "2" (In game)
numplayers: Integer, Number of players inside the game
maxplayers: Integer, Max. players of the game
minplayers: Integer, Min. players of the game

The parenthesis part is defined for each player, and for each one it defines:
- flag: must be 1 to activate user.
- username
- ip
i.e: 1,Indi,1062731486

TCP Server -> Client (Inside Attraction)

AR:%i:0: (Verified)
Attraction Response (max tables)
Sends the client the max number of tables of the Attraction.

TA: (Verified)
TABLE ADD
The server says to the client that he has entered to the Table.

TL: (Verified)
TABLE LEAVE
The server says to the client that he left the Table. It is necessary to send after a TO, if not client will have a black screen.

TN: (Deprecated)
TABLE NOT IN
This command forces client to leave table, and disconnect. It works, but is not used.

GX:%s: (Verified)
GAME EXIT (loginid)
Shows a green message that "loginid" has left the game.

GN: (Deprecated)
GAME NOT STARTED
This command says client that Game is not started, but is not needed (just don't send GS).



UDP Client -> Server

UQ:%s:%d: (Verified)
USERLIST QUERY (loginid,place = 0)
Asks for Messenger Users List. Server must return the UP package info.
This command is send to different UDP ports according where the user is.

TQ:%s:-1: (Verified)
TABLE QUERY (loginid, -1)
Asks for Table Info List, when the client enters in an Attraction . Table Info is answered with TR package.

AL:%s: (Verified)
(AL)ive (loginid)
Pooling the server for Users status.

PL:%s:%s: (Verified)
PLAYER LIST (loginid1, loginid2)
User "loginid1" asks for profile info of "loginid2". Info is returned using the PP command.

PS:%s:10:%d:%s:%d:%d:%d:%d: (Verified)
PLAYER SEARCH (loginid, 10, gender, country, lang, zodiac, minage, maxage)
Filter list of Players to show at Messenger part.

gender: 0 -> Male , 1 -> Female, -1 -> Don't care!
country: string or "none"
lang: 0 -> English, 1-> French … , 6 -> Other, -1 -> Don't Care
zodiac: From: 0 -> Aries to 11 -> Piscis, -1 -> Don't care!
minage: Integer
maxage: Integer

i.e.PS:Indi:10:1:BERK:3:1:11:85:

NOTE: It clears ALL the List of Messenger, so next updates should be filtered by server!!

UDP Server -> Client

UO:%s: (Verified)
USER OUT (loginid)
Delete the entry that matches Username in Messenger window.

UP:status:loginid:region:gender:color:ipaddr:userid:status2:colorbar:mic: (Verified)
USERLIST PROFILES
- Server response of UQ command.
- First User is ourself, and the Color of the bar is different!
- User Info CAN BE updated, using the same loginid.

Status (where the player is):
0 -> Door (Exit)
1-> Info Center
2-> Planet
10-> Splash
11-> Ball Bubble
12-> Soar
13-> Dream Dorobo

Region can be ANY String!
gender: 0 -> Male , 1 -> Female
color: See "COLOR AND CLOTHES"
ipaddr: -
userid: -
status2: -
Colorbar (maybe friends / no friends ?): 0-> Transparent/Blue, 1 -> Green, 2-> Yellow.
Mic: 0 -> No Mic , 1 -> With Mic

i.e. : "UP:1:INDIKET:MADRID:0:915:1:1:1:2:1:"

PP:status:loginid:region:gender:lang:age:colour:zodiac: (Verified)

PROFILE PROVIDER
Returns user profile to the game (when it asks for Info). It can be sent multiple times while the client is at query screen (i.e. Activity of the User).

  • Status (where the player is):

0 -> Not Connected
1, 2-> In Planet Ring
10-> In Splash
11-> In Ball Bubble
12-> In Soar
13-> In Dream Dorobo

  • loginid: Name of the user
  • region: any string
  • gender: 0 -> Male , 1 -> Female
  • lang: See "LANGUAGES" section
  • age: any string (numeric)
  • colour: See "COLOR AND CLOTHER" section
  • zodiac: From: 0 -> Aries to 11 -> Piscis

TR:idtable:status:playersin:maxplayers:(playerinfo):minplayers: (Verified)
TABLE RECEIVE
Send info of Tables to the Client: should be send at intervals to the Client when he is inside an attraction.

  • idtable: ID of the table, starts at 0.
  • status: 0 -> Empty, 1-> Wait, 2-> Close, 3-> In Game
  • playersin: Nº of players already inside the Table.
  • maxplayers: Nº of maximum players of a Table (can be seen by nº of "clips")
  • playerinfo: For each player, we have to append each of the player's outfits, and then each of the player's genders (0 = male, 1 = female). At the end of all players, we have to append an extra 0. IMPORTANT: using commas!!
  • minplayers: Minimum nº of players to start a game (can be seen by nº of green "clips").

I.e: For a Table with ID 0, Max. 2 players, and 1 female player IN:
TR:0:1:1:2:952,1,0:1:

For a Table with ID 1, Max. 4 players, and 2 players (1 boy and 1 girl) IN:
TR:1:1:2:4:552,900,0,1,0:1:

TS:idtable:playerposition:status:username:ip:position: (Verified)
TABLE STATUS
Used when a Player enters or Leaves a Table (when we join one). Basic command to let the game know that there are more players. We can send it multiple times (for each status).

  • idtable: ID of the table, starts at 0.
  • playerposition: Position of the player, starts at 0. Max value is 3.
  • status: 1: joins , 0: leaves
  • username: Name of player (if status is 0, is not needed).
  • ip: In integer format, needed for VoIP games.
  • position: can be same as "playerposition"

VERY IMPORTANT: In VoIP games (Dorobo, Splash), when an user Starts a Game (GS), we MUST resend the TS command in order to refill Table Status!!! If not, game won't initialize!

PE: (Deprecated)
PROFILE ERROR
Is not used by the game.

PT:loginid:gender:region: (Deprecated)
QUERY RETURN
Is a DEBUG command to fill the list of online users. Also, with this command, an user can't be updated… if we send same string again, it creates a new one.

loginid: Name of the user
gender: 0 -> Male, 1 -> Female
region: any string


MESSAGE COMMANDS: (Verified)

MS:from:to:message:
MESSAGE SEND

MR:from:to:message:
MESSAGE RECEIVED
This is the format to receive a message from a contact.
Note: When user reads the message, the game sends AUTOMATICALLY a reply message with ## content to let the sender know we read the message (it show into screen "Has read").

MO:loginid: (Deprecated)
MESSAGE OPENED
MO was used in earlier versions: it just made a sound to the user confirming that received has read the message.
In final version, MO is not used anymore.

ME:
MESSAGE ERROR
Show error message to client.

TEML COMMANDS:

FRQ#filename.ext (Verified)
FILE REQUEST
Asks through TCP 8001 port for a resource. It can be a TEML page, or also an image. All info must send in BINARY format using:
- "TEML" header (4 bytes)
- Size of page data (4 bytes)
- Content (start after 0x08 offset)

PST#loginid#formname#formelement#value
SEND POST
Client send to the Server the POST info of the Form elements. I.e: Numeric control is in HEX value.

Others: Profile Dialog

First screen asks for:

Name.
Password (min 3 chars)
Box Password
Boy/Girl
Where are you from? Predefined places
Languages: Up to 3 slots, also predefined
Birth Date (numbers)
Colors: 1st body, 2nd clothes

Second screen asks for:

Intelligence (0-100)
Kindness (0-100)
Aspect (0-100)

Third screen asks for confirmation.

Others: LANGUAGE

If only user chooses the first:
???=0 English=1 French=2 German=3 Spanish=4 Italian=5 Japanese=6 etc=7.
For the second:
???=0 English=256 French=257 German=258 Spanish=259 Italian=260 Japanese=261 etc=262.
For the third:
???=0 English=65536 French=65537 German=65538 Spanish=65539 Italian=65540 Japanese=65541 etc=65542.

If the user chooses 2 or 3, the game sums all the values!

Others: COLOR AND CLOTHES

Color (left to right): 1º = 0, 2º = 256, 3º = 512, 4º = 768, 5º = 1024… (it sums 256).
Clothes (left to right): 1º= 0, 2º = 1, 3º = 2, 4º = 3… (it sums one by one)

The two final values are also added!

Others: PROFILE DATES

The format on which are store the Creation and Last Mod. date, follows the next structure:
- Date (y.m.d) is stored as an integer in base 10.
- If follows a simple bitfield:

2111168512 would be in 32 bits:

011111011101 0101 11100 00000000000

11010 - day 28 (bit 11)
0101 - month 5 (bit 16)
011111011101 - year 2013 (bit 20)

Others: Expansions

It is known that SOAR and DOROBO got extensions when SEGA Servers were online.
In SOAR, the number of max. players in a game was raised to 8, and there were new Tracks.
In DOROBO, there were new labyrinths.

About SOAR, there are more modes in the Binary file:
History, Balloon Charge, Fly High, Grand Prix, Sky Oval, Twilight Circler, Forest Cross and Tutorial.

Default modes are Balloon Charge, Fly High and Grand Prix, but there is an option to unlock all of them!

-----------

TCP COMMANDS (to confirm!!!)

NG:%s
It is used in different situations (means error):
- At login screen -> error regist:
1: Regist form error
2: Il·legal protect code
3: Used protect code
- Outside login part:
%s = move error

RS:%d:%d:%d RANKING START (loginid,nowtable,rankmode) OK
Client sends when he starts a race!

RE:%d:%d:%d:%d: RANKING UPDATE userid,nowtable,rankmode,(info) OK
Client sends when he finishes the race!
(info: i1:i2:i3:i4) where
i1: 0
i2: Nº of players (1, 2…)
i3: 0
i4: Time:
Takes seconds+mil·liseconds together, and divide by 2. i.e.: 12,48 -> 624
If Player is over Time (90 seg), game sends: 32000.

IQ:%d:

UDP COMMANDS (to confirm!!!)

RQ:%d:%d:%d: (OK!)
RANKING REQUEST (uid,mode,rankmode)
Used when there is more than 1 player!

  • uid (think is the id of the player).
  • mode can be 0, or 2 (depending of the page we consult).
  • rankmode is the same as RE or RS.

TX: Move successful ->
Seems that can be used to clean a table of people
Args: idmesa, username

UX: User request key return

RP:%s:%s:%s:%s:%s OK
Ranking Pool
Show info of Ranking after a game.

SOAR (General / Page 1)
(RP:1:username:0:1:#position:1:besttime:position)

username: any string
#position: number in the # column
bestime: number, i.e. 1500 = 30.00 (seg)
position: number

IR: ID SEARCH

TEML

At the login world, there is a NEWS INFORMATION board. Looking at photos (take a look at Planet Ring manual), the user browses a webpage with links.

ABOUT THIS SECTION

- The server has to push the data to the user, on 8001 TCP port. Images are sent in BINARY MODE.
- Pages are stored as TEML files.

The manual shows this example:

NOTICE
latest news
contact
birthday
fortune
questionnaires
staff
test

home
back

The attractions and rankings work with the same system. Both shows an ON-LINE MANUAL.

TOM'S EMBEDDED MARK UP LANGUAGE

Planet Ring uses a HTML like markup language to display news, contests, info and statistics about the game in the information board.
The name comes from TOM, one of the game's programmers.

TEML SEND PACKET STRUCTURE

The TEMP page returns have three parts:

- The header "TEML" (4 bytes)
- The size of the page data (4 bytes-> unsigned long file size)
- The actual page data (starting after that at offset 0x08) BINARY MODE

TEML TAGS

- Every page must start with <TEML> and finish with </TEML>

  • <TEML></TEML> Verified

Open and close a TEML page.

  • <BR> Verified

Jump line.

  • <CENTER>Text</CENTER> Verified

Text or elements rendered inside will be centered to screen.

  • <IMG FILENAME.PNG> Verified

When using IMG tag, Client asks to server for this resource. Also, must be send in binary format.

  • <LINK URL.TEML>Text</LINK> Verified

Shows a cool link in the TEML page (blue and yellow). When user press A, client ASKS for the TEML page: FRQ#URL.TEML

  • <COL 255 0 255> Verified

Sets color for the following text. This tag does not close, so if you want another color just create another COL tag. Format is RGB 888 in decimal, where 0 is the min. value and 255 the max. one.

  • <FRAME 50 50 200 200>Text</FRAME> Verified

Creates an Absolute position (as a DIV), with X1 Y1 X2 Y2. Min. value is 0 and Max. value 359.

  • <GROUP InternalName ExternalName>Text</GROUP> Verified

With GROUP we can create POST variables: It creates a SUBMIT link that when the user push on it, it sends a PST command.

- InternalName: Is the name of the Group: all POST elements inside GROUP must use this name.
- ExternalName: Is the name that PST command will give of the form when is sending the POST.

Inside GROUP we can put text and/or NUMITM, but NEVER a POST tag, or the game will freeze!!

  • <NUMITM InternalName ExternalName minVal maxVal Value> Verified

Creates a Number selector (User can choose a Numeric Value from a range).

- InternalName: Must match with the Group InternalName
- ExternalName: Name of the item that will see in the PST command.

Value in the PST is sent in HEX format! (so, we should convert to Decimal).

<GROUP inter form>
<NUMITM interno val1 2 20 10>
<BR>
<NUMITM intern val2 0 100 50>
<BR>
</GROUP>
  • <TAB Num>Text Verified

Do a Tabulator to the following text. Num is an X coordinate, from 0 to 359.

  • <END> Verified

Alias of </TEML>. Stops anything coming later.

"POST",
"POSTGRP",
"BACKGND"

INFORMATION BROWSERS

In the information centre there are 3 information browsers, each one covering a different aspect of the game, all of them are TEML files, the file structure would be the following:

GREEN BROWSER
ONLINE MANUAL
a_home_%c.teml : Attraction Info

ORANGE BROWSER
NOTICE BOARD
o n_home_%c.teml : Notice Board 

BLUE BROWSER
HIGH SOCRE RANKINGS
o r_home_%c.teml : Ranking Board

WORLD MAP
Opens a teml file with only an IMG tag
with the world map image (inside the GD) and a BACK button.

IMPORTANT:
Right after the "home_" in the teml filename, the client requests for a different teml file depending on language!!!
Thus why it wouldn't work in some tests…
I.e: a_home_s.teml -> when the console language is spanish
a_home_e.teml -> when its set to english

IMAGE FORMAT:

  • Planet Ring will only load PNG images (not PVR), but supports transparency.
  • Max. render size of an image is aprox. 256x256, although you can load a bigger image (300x300).
  • Image keep in front of text (so, no background can be used, even using FRAMES).

Protocol

Domains and Ports

  • master.ring.dream-key.com/146.185.135.179
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License