I was playing a little bit with the first retail Ultima Online 1.25.0 release and found some info willing to share:

The login client keys doesn't follow the known algorithm. I had to find them via disassembly:
Login Encryption Key #1: 0xF1A372D5
Login Encryption Key #2: 0x3A1FD527

Otherwise, the encryption algorithm works (Decrypt_Old). The packet protocol is following:
  1. Client -> 4 bytes seed
  2. Client -> 0x80: Account Login
  3. Server -> 0xA8: Account Login Ack
Now the biggest problem. I have verified in the disassembled packet table that there is no 0xA8 packet:

Packet table:
Packet  Size
0x00    100
0x01    5
0x02    3
0x03    dynamic
0x04    2
0x05    5
0x06    5
0x07    7
0x08    14
0x09    5
0x0A    11
0x0B    266
0x0C    dynamic
0x0D    3
0x0E    dynamic
0x0F    61
0x10    215
0x11    dynamic
0x12    dynamic
0x13    10
0x14    6
0x15    9
0x16    1
0x17    dynamic
0x18    dynamic
0x19    dynamic
0x1A    dynamic
0x1B    37
0x1C    dynamic
0x1D    5
0x1E    4
0x1F    8
0x20    19
0x21    8
0x22    2
0x23    26
0x24    7
0x25    20
0x26    5
0x27    2
0x28    5
0x29    1
0x2A    5
0x2B    2
0x2C    2
0x2D    17
0x2E    15
0x2F    10
0x30    5
0x31    1
0x32    2
0x33    2
0x34    10
0x35    653
0x36    dynamic
0x37    8
0x38    7
0x39    9
0x3A    dynamic
0x3B    dynamic
0x3C    dynamic
0x3D    2
0x3E    37
0x3F    dynamic
0x40    201
0x41    dynamic
0x42    dynamic
0x43    553
0x44    713
0x45    5
0x46    dynamic
0x47    11
0x48    73
0x49    93
0x4A    5
0x4B    9
0x4C    dynamic
0x4D    dynamic
0x4E    6
0x4F    2
0x50    dynamic
0x51    dynamic
0x52    dynamic
0x53    2
0x54    12
0x55    1
0x56    11
0x57    110
0x58    106
0x59    dynamic
0x5A    dynamic
0x5B    4
0x5C    2
0x5D    73
0x5E    dynamic
0x5F    49
0x60    5
0x61    9
0x62    15
0x63    13
0x64    1
0x65    4
0x66    dynamic
0x67    21
0x68    dynamic
0x69    dynamic
0x6A    3
0x6B    9
0x6C    18
0x6D    3
0x6E    14
0x6F    dynamic
0x70    28
0x71    dynamic
0x72    5
0x73    2
0x74    dynamic
0x75    35
0x76    16
0x77    16
0x78    dynamic
0x79    9
0x7A    dynamic
0x7B    2
0x7C    dynamic
0x7D    13
0x7E    2
0x7F    dynamic
0x80    62
0x81    dynamic
0x82    2
0x83    39
0x84    69
0x85    2
0x86    dynamic
0x87    dynamic
0x88    66
0x89    dynamic
0x8A    dynamic
0x8B    dynamic
0x8C    11
0x8D    dynamic
0x8E    dynamic
0x8F    dynamic
0x90    19
0x91    65
0x92    dynamic
0x93    98
0x94    dynamic
0x95    9
0x96    dynamic
0x97    2
0x98    dynamic
0x99    26
0x9A    dynamic
0x9B    258
0x9C    309
0x9D    51
0x9E    dynamic
0x9F    dynamic
0xA0    3
0xA1    9
0xA2    9
0xA3    9
0xA4    149

I can't figure out what packet to send next :( I was digging through old emulators (UO98, Fuse 0.97, UOX build 19), but had no luck. They all use the 0xA8 packet. So I'm lost. Any hints?
 
Nvm I was stupid and tired, read the sentence wrong on the packet ;D its just the flag 0x5D noth another packet. My bad :D
 
Nvm I was stupid and tired, read the sentence wrong on the packet ;D its just the flag 0x5D noth another packet. My bad :D
I was trying all the flags :) 0x5D, 0xFF, 0xCC, 0x64, it doesn't work. The point is that this version of client doesn't know 0xA8 packet (otherwise it would be in the packet table). The login sequence must have been different in those old days.
 
I was reading through UO98 forum and come to this thread A few tidbits | JoinUO Forums

Guy called Kair uploaded an archive with all packets descriptions. It is really comprehensive :) and it contains description for 0x81 packet:

Packet 0x81:
0x81 - Login OK
---------------
Client->Server:No
Server->Client:Yes
Length:dynamic

byte 0x81
short size
byte numCharacters
byte serverFlags = 0xCD

loop x 5
{
    char[0x1E] charName
    char[0x1E] charPass
}

byte numServers
loop x numServers
{
    byte serverID
    char[0x10] serverName
}
    
byte numStartingLocs
loop x numStartingLocs
{
    byte cityID
    char[0x1F] cityName
    char[0x1F] tavernName
}

I haven't tried yet, but I think that this is the missing packet.
 
Few months later :) I have figured it out. The next packet is 0x81.

BUT, unlike the client 1.25.35:
So I'm lame. The encryption patch only does the outbound encryption. I knew that when I made it, I just didn't think about it :)
1.25.0 uses inbound decryption. I had to disassemble the decryption routine to figure out how to encrypt packets on server, here it is:
Encrypt:
FirstEncryptKey = ((~seed & 0xF0F0F0F) ^ 0x70E050A) | ((seed & 0xF0F0F0F0) ^ 0xA06020E0);
SecondEncryptKey = ((seed & 0xF0F0F0F) ^ 0x40C010D) | ((~seed & 0xF0F0F0F0) ^ 0xF0B03090);

for (var i = offset; i < offset + length; i++)
{
  buffer[i] = (byte)(FirstEncryptKey ^ buffer[i]);

  var oldKey0 = FirstEncryptKey;
  var oldKey1 = SecondEncryptKey;

  FirstEncryptKey = ((oldKey0 << 1) | (oldKey1 >> 31)) ^ 0xAF572D13;
  SecondEncryptKey = ((oldKey1 << 1) | (oldKey0 >> 31)) ^ 0xFA7D5231;
}

For the sake of completeness, here is the known server decryption routine:
Decrypt:
FirstDecryptKey = ((~seed ^ 0x00001357) << 16) | ((seed ^ 0xffffaaaa) & 0x0000ffff);
SecondDecryptKey = ((seed ^ 0x43210000) >> 16) | ((~seed ^ 0xabcdffff) & 0xffff0000);

for (var i = offset; i < offset + length; i++)
{
  buffer[i] = (byte)(FirstDecryptKey ^ buffer[i]);

  var oldKey0 = FirstDecryptKey;
  var oldKey1 = SecondDecryptKey;

  FirstDecryptKey = ((oldKey0 >> 1) | (oldKey1 << 31)) ^ 0x3A1FD527;
  SecondDecryptKey = ((oldKey1 >> 1) | (oldKey0 << 31)) ^ 0xF1A372D5;
}

And then, finally it works! :)

PS: Encrypt keys (0xAF572D13, 0xFA7D5231) and decrypt keys (0x3A1FD527, 0xF1A372D5) seems to be same from 1.23.0 to prior some version before 1.25.35 where they became dynamic.
 
This feature was actually part of the early release versions as well. It was supposed to influence melee combat, for example you might hit less but block more. But if my memory is correct, it really didn't do very much. They eventually just removed the feature.

You'll also note that this was before they showed skill increase/decrease in increments. Skill gain back then was really slow and players complained that they couldn't tell how close they were to gaining a % in a skill, so they later added showing skill gain in 1/10th increments.
 
How does one go about playing the game like that? I'd love to see it in action! Can someone message me on Discord and let me screenshare and demo this for me? Fascinating!
 
Back