my place to keep DOAO from dying
Thank you for your service.
the 640x480 option still worked
You are right, you have to do 640x480 and also uncheck "Effects", for _low.emp to be activated.
But the outgame replacement needs to be tested more thoroughly to check if it has some side effects that affect the ingame gameplay interface...
I guess they just didn't update the compressed textures, because they didn't use them at that time. I think a texture exporter could be created, to go fast through all the swapped textures and compare them side by side, and see if they match.
fixes that the previous unreleased server had
Without a source code i don't think this is doable. Maybe just the "level up animations"
It doesn't use the DOAO version that had some strange tweaks
Long story short, maybe they did this for a reason. Like maybe they tried to avoid problematic code that leads to desynchronization between players. We'll never know for sure. I'll put a reminder here that using skins(from doa3/doax) that alter the default skeleton is a no-no for online battles.
 

WAZAAAAA

Well-Known Member
You are right, you have to do 640x480 and also uncheck "Effects", for _low.emp to be activated.
oh you're right, it has to be both 640x480 AND Effects OFF in order to crash when entering matches. Hey I was wondering, what about creating symbolic links for each removed low.emp file that point to the regular .emp counterpart to avoid crashing but still keep the installation size low? Would it work? Is it easy to pack into setups? I pretty much never had to use symlinks before idk lol

Long story short, maybe they did this for a reason. Like maybe they tried to avoid problematic code that leads to desynchronization between players. We'll never know for sure. I'll put a reminder here that using skins(from doa3/doax) that alter the default skeleton is a no-no for online battles.
nahh you're overthinking, it's more likely that some scrubby employee in an office more than a decade ago got hit by one too many unblockable attacks and decided to apply stupid sneaky "balance" changes
 
I fixed the crash for missing "_low.emp" files(that no one will ever encounter anyway), and then made a big fuss about it. :)
(look inside the archive to see what I mean)
 

Attachments

  • Fix_for_missing_low_emp_files.zip
    280.2 KB · Views: 229
I like the idea of removing the duplicate "outgame" high quality textures and keeping the better compressed _dxt.gsr alternatives to save space... because fuck the outgame, who cares about the dumb lobby shit.

But the outgame replacement needs to be tested more thoroughly to check if it has some side effects that affect the ingame gameplay interface...
So. I tried to make a list of textures that would be better to keep in lower compression. The list so far:
free_wait_detail_chara3.gsr
avatar_menu.gsr
dr_l_01.gsr
dr_l_02.gsr
dr_r_01.gsr
dr_r_02.gsr
ingame_time.gsr
chara_font_ingame.gsr
chat.gsr
these will fix the blue timer, one of the loading screens, the chat background and something else. I also attached all these files to this post. Unpack them to 'DoAO/data/2d/' folder. To make this list I used a script that copied all the textures to a folder and converted to dds format.
Python:
#-------------------------------------------------------------------------------
# Purpose: convert all DoAO gsr files to dds (or only the _DXT doubles, to make a blacklist of bad _DXT files)
#-------------------------------------------------------------------------------
## options
path = "D:\games\DoA Online\data" # #WRITE HERE THE PATH TO THE DOAONLINE DATA FOLDER LOCATION
convert_doubles_only  = True  # True - convert only '_DXT.gsr' + doubles, False - converts ALL gsr to dds
save_to_output_folder = True  # True - saves dss to the original folders, False - save all to 'GSR_textures' folder


import os, struct
##create folder
outdir = path[:-4]+"GSR_textures/"
testlist = []
##dds headers
ddsha = b"\x44\x44\x53\x20\x7C\x00\x00\x00\x07\x10\x0A\x00"# this + height + width + size + DXT*
tempdds = [0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0x20, 4,b'DXT1',0,0, 0,0,0,0x1000, 0,0,0,0]
ddshc = {
b'DXT1': struct.pack("<15L4s10L", *tempdds),
b'DXT3': struct.pack("<15L4s10L", *tempdds[:15]+[b'DXT3']+tempdds[16:]),
b'DXT5': struct.pack("<15L4s10L", *tempdds[:15]+[b'DXT5']+tempdds[16:]),
b'\x15\x00\x00\x00': struct.pack("<26L", *tempdds[:14]+[0x41,0,0x20,0xff0000, 0xff00,0xff,0xff000000,0x1000, 0,0,0,0]),
b'\x16\x00\x00\x00': struct.pack("<26L", *tempdds[:14]+[0x41,0,0x20,0xff0000, 0xff00,0xff,0xff000000,0x1000, 0,0,0,0])}

def main():
    parsedir(path)
    print(testlist)

    if testlist:
        if type(testlist[0])==bytes:
            for tst in testlist:
                print("".join(["%2s "%hex(c)[2:] for c in tst]))
        elif type(testlist[0])==int:
                print((len(testlist)*"%4xh ")%tuple(testlist))

def parsedir(path):
    if not (os.path.exists(outdir) and os.path.isdir(outdir)):
        os.makedirs(outdir)
    filenames= os.listdir(path)
    for filename in filenames: # loop through all the files and folders
        fpath = os.path.join(path, filename)
        if os.path.isdir(fpath):
            parsedir(fpath)
        else:
            if not convert_doubles_only:
                if  len(filename) > 3  and  filename[-4:] == '.gsr':
                    gsr2dds(fpath, outdir + filename[:-4] + '.dds')

            elif len(filename) > 7  and  filename[-8:] == '_dxt.gsr':
                    nondxtname = fpath[:-8] + '.gsr'
                    if os.path.isfile(nondxtname):
                        #copy these pairs to outdir; convert them to dds for visual comparison; make a blacklist of bad dxts
                        #get the gsr header
                        dxtdata = gsr2dds(fpath, outdir + filename[:-4] + '.dds')
                        gsrdata = gsr2dds(nondxtname,  outdir + filename[:-8] + '.dds')


def gsr2dds(gsrpath, ddspath):
    if os.path.isfile(ddspath):#if the file already exists then skip; TODO: add option to rename the file if already exists
        print('dds already exist, skip:', gsrpath)
    else:
        with open(gsrpath, "rb") as f:
            txheader = struct.unpack('<2L4s5L4s3L', f.read(0x30))#
            if txheader[0] == 0x20 and txheader[2] == b'gsr\x00' and txheader[8] == b'tex\x00':#gsr header size, gsr0 magic, tex0 magic
                f.seek(txheader[-1])
                txmagic, txwidth, txheight, txun1, txsize, txoffset, pad1, pad2  = struct.unpack('<4s5L2L', f.read(0x20))#[b'DXT1', b'DXT3', b'DXT5', b'\x15\x00\x00\x00', b'\x16\x00\x00\x00'], width, height, [1 2 3 4 5], size, offset0
                with open(ddspath, "wb") as fs:
                    fs.write(ddsha)
                    fs.write(struct.pack('<3L', txheight, txwidth, txsize))
                    fs.write(ddshc[txmagic])
                    fs.write(f.read())

    return ''
if __name__ == '__main__':
    main()
To use this script change the 'path' string to point to your 'DoA Online/data' folder, if you make the 'convert_doubles_only' False, it will convert all found gsr files to dds, not only the _DXT ones. This script can be used to spot more 'broken' textures if there are any.



--------------------------
And I'm not sure if this is the right place, but I have a question, what is the most commonly used version of doa2u, American, Japanese or European? Are there differences between these versions, like between doa3.0 / doa3.1 / doa3.2 ? The Idea is, if i make a patch for doa2u, for which version should i make the patch.
 
Last edited:

WAZAAAAA

Well-Known Member
godlike

And I'm not sure if this is the right place, but I have a question, what is the most commonly used version of doa2u, American, Japanese or European? Are there differences between these versions, like between doa3.0 / doa3.1 / doa3.2 ? The Idea is, if i make a patch for doa2u, for which version should i make the patch.
afaik there's only 1 Xbox DOA2U version.
the only known differences between the DOA2U versions are subtitles support and the Tag bug being fixed youtu.be/n7RQUlKK0go
 

grap3fruitman

Well-Known Member
Standard Donor
The changes were deliberate. Someone shared an internal spreadsheet from the devs on DOACentral back in the day with all of them listed. It was like one per character or something but I don't remember exactly.
 

WAZAAAAA

Well-Known Member
The changes were deliberate. Someone shared an internal spreadsheet from the devs on DOACentral back in the day with all of them listed. It was like one per character or something but I don't remember exactly.
I don't think mopafo is asking about Xbox DOA2U vs PC DOAO... just Xbox DOA2U itself
 
So, some things to clear up. I'm the guy who was behind the b0ny nickname. In the old times, my hdd died and I lost all my doa related stuff. That was a breaking point, since that time, it was a few weeks ago when I thought again about doa, the moment when I saw the news about gta re3 and revc, and then I found you guys, still modding these old games.

So, how I created the server. I wrote a little code to the game executable, to save to files, all the communication between the game and the original server, when the server was still up. Then, with the last release of the game, leaked the 'server.pdb' file, with the debug symbols for an older version of the original server(can't find anymore the compatible client).
I found again this pdb file in the repack of the game from the russian site, somehow the torrent still has seeds(https://zooqle.com/dead-or-alive-online-v2-0-rus-repack-2011-2-0-vyk8p.html)
It seems like I can't find anymore the old tool I used to decompile the 'server.pdb' to a text file with all the constants/enumerations/structures/whatever. And other pdb decompilers are not doing a great job, one would be 'cvdump, but the output text file is hard to read and understand, other decompilers I found, are crashing trying to decompile all the content, the most readable output is made by 'pdbex''(command line: pdbex.exe * server.pdb -o server.txt), tough the old tool was much better and didn't crash.
And I can tell you that the 'newServer.exe' code is shit, I wasn't the right guy to write a server.
RIP a ton of scripts i used for myself, and all the half docummented research, and ida decompilation files.

Also about the qLoader. When the limited space, the loader provides for patching data, was surpassed, I dumped a majority* of patches to 'client.exe', and renamed it to 'client2.exe', so the old patches wont work with it, and then I did it again with 'client3.exe', and now the qLoader is out of space again. (*from what I remember, not all patches can be applied directly to the executable)

What I have now. From the russian torrent I have the decompiled pdb, and also all the versions of 'client.exe', that can be used to understand what patches where made to the executable(I pray that the 'client.exe' is a clean one). Also I decompiled all the qLoader files found in the WAZAAAAAs 'DOAOcollection', and will try to look at patched data and maybe remember some things( the patches inside qLoaders are in groups).

Some plans. I saw that DoAX skins won't work with doa2u. The pack is provided with a qLoaderC5, I suppose this loader is patching the doaX skeleton hierarchy to look somewhat decent when used for the converted skins. I'd like to try and add these patches to doa2u, so the skins won't look like abominations. (this could break the look of the naked green kasumi clone that comes out of the jar, it's the only thing that uses this kind of skeleton)

Here is the python script I used to decompile qLoaders:
Python:
#-------------------------------------------------------------------------------
# Decompile r!sc patchers to original files for DoAOnline s/qLoaderXX patchers
#-------------------------------------------------------------------------------
import os, struct
inpath  = 'C:\WORK\doaol\qLoaders'                  #the path to the folder with s/qLoaderNN;
outpath = os.path.join(inpath, 'converted')         #files will be convertet to the 'converted' subfolder
if not os.path.exists(outpath): os.makedirs(outpath)#if path the output folder doesn't exist then make it


def main():
    for fname in os.listdir(inpath):
        if fname[-4:] == '.exe':
            with open(os.path.join(inpath,fname), 'rb') as f:
                f.seek(0x1204)
                exename = f.read(0x30).decode('utf8').rstrip(chr(0))
                olines = ["F="+exename, 'O='+fname, ";\tadd comments after ';' at the end of a line. (F=program_name, O=loader_name)"] #store text to onlines
                f.seek(0x1240)
                while True:
                    memofs,bcount = struct.unpack('<LH', f.read(6))
                    if memofs == 0x63732172: # b'r!sc' magic terminator
                        olines.append('$')
                        break
                    sbytes = ["%02x"%b for b in f.read(bcount)]
                    rbytes = ["%02x"%b for b in f.read(bcount)]
                    olines.append('P=%06X'%memofs + '/' + ','.join(sbytes) + '/' + ','.join(rbytes))

                with open(os.path.join(outpath,fname[:-4]+'.txt'), 'w') as fs: #open as text and write; TODO: .txt should be .rpp
                    fs.write(':\t\t\t\r\n'.join(olines))

if __name__ == '__main__':
    main()
And I attached to this post, the 'r!sc' tool I used to make qLoaders.(drag and drop the decompiled file to 'rpp.exe' to compile it back to a loader, or add a '*.rpp' extention to it and open it from the running 'rpp.exe' tool)
 

Attachments

  • rppv15.zip
    27.3 KB · Views: 191
Last edited:

WAZAAAAA

Well-Known Member
So, some things to clear up. I'm the guy who was behind the b0ny nickname.
The_Return_of_the_King_Banner.png
Thank you for making DOAO immortal. Steam, PSN, XBL, Parsec and the world might all burn down one day, but we can always count on newServer.exe for some DOA lmao.

my hdd died
damn, now I feel bad for sending you this private message in 2020 on xentax lmao
Code:
backup your DOA tools

Please reupload all your DOA tools in one place (and source codes if possible) because all links online are dead. Don't let them become forgotten, post them in the DOA thread. It doesn't have to be a pretty, clean and tidy archive... it just has to *exist*. https://gofile.io/?t=uploadFiles

Then, with the last release of the game, leaked the 'server.pdb' file, with the debug symbols for an older version of the original server
dammm so that's how history went huh, cool shit

somehow the torrent still has seeds
yeah lmao I was surprised when I saw it was still alive, I downloaded it shortly before making this thread. That's the 2011-12-24 client, the only other setup I could find was the 2011-07-20 one, which also has the 2 .pdb's and client.exe if you're interested
Code:
----CLIENT INFORMATION----
MAIN CLIENT BASED ON:
NAME:	DoAO Setup.exe
SIZE:	1256458960 bytes
DATE:	2011-12-24
SHA256: 08AF8B0C1D4E91E6DE56BAB2A63BC1C8C00100E5FE8C0FFAADFC50BB860ACA1F
MIRROR: magnet:?xt=urn:btih:01dafe00ed2a4be1474d044f877e84f7fba49daa&dn=DoAO%20Setup.exe&tr=http%3a%2f%2ftracker.ex.ua%2fannounce&tr=udp%3a%2f%2ftracker.ex.ua%2fannounce&tr=http%3a%2f%2fretracker.local%2fannounce&ws=http%3a%2f%2fwww.ex.ua%2fget%2f35626060

WITH SOME REPLACEMENTS FROM:
NAME:	setup.exe
SIZE:	641611907 bytes
DATE:	2011-07-20
SHA256:	CB5636FD6E071D761A4809826DAD9C0A41AC0EF8D31391F4535432F45F862C00
MIRROR:	https://www.mediafire.com/?u2u4d36r07j4i

pdb decompilers
Have you tried Ghidra? It's modern and made by the NSA, who would've thought that such a large organization would make such a major contribution to open source software lol. Maybe it's useless for what you need but hey, worth to mention. When I add newServer.exe to a Ghidra project it wishes it could have its .pdb (hardcoded path is from your now dead XP HDD I suppose lol).
Code:
PDB Universal> Unable to locate PDB file "d:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\standalone newServer\Release\newServer.pdb" with matching GUID.
 You can manually load PDBs using the "File->Load PDB File..." action.
 Alternatively, you may set the PDB Symbol Repository Path
 using "Edit->Options for [program]" prior to analysis.
PDB Universal> Cannot find candidate PDB files.
PDB Universal> PDB symbol repository directory not found: C:\Symbols
PDB Universal> Skipping PDB processing
It also comes with a "decompile to C/C++ code" feature (File -> Export Program...) which is pretty neat, thanks to that I randomly discovered one more parameter that client.ini accepts: log=0/1/2 (0=no logging 1=log to GUI 2=log to both GUI and slog.txt)

about the qLoader
yeah about the loaders... unfortunately time has passed and antiviruses no longer like those :\ https://www.virustotal.com/gui/file...4ce10a1848590c704b67631a167978cbb68/detection the GAME_START.bat I came up with in my client runs both the loader and the client3.exe, just in case the loader got eaten by the AV (it happens).
 

CoYoTe

Active Member
So, some things to clear up. I'm the guy who was behind the b0ny nickname. In the old times, my hdd died and I lost all my doa related stuff. That was a breaking point, since that time, it was a few weeks ago when I thought again about doa, the moment when I saw the news about gta re3 and revc, and then I found you guys, still modding these old games.

So, how I created the server. I wrote a little code to the game executable, to save to files, all the communication between the game and the original server, when the server was still up. Then, with the last release of the game, leaked the 'server.pdb' file, with the debug symbols for an older version of the original server(can't find anymore the compatible client).
I found again this pdb file in the repack of the game from the russian site, somehow the torrent still has seeds(https://zooqle.com/dead-or-alive-online-v2-0-rus-repack-2011-2-0-vyk8p.html)
It seems like I can't find anymore the old tool I used to decompile the 'server.pdb' to a text file with all the constants/enumerations/structures/whatever. And other pdb decompilers are not doing a great job, one would be 'cvdump, but the output text file is hard to read and understand, other decompilers I found, are crashing trying to decompile all the content, the most readable output is made by 'pdbex''(command line: pdbex.exe * server.pdb -o server.txt), tough the old tool was much better and didn't crash.
And I can tell you that the 'newServer.exe' code is shit, I wasn't the right guy to write a server.
RIP a ton of scripts i used for myself, and all the half docummented research, and ida decompilation files.

Also about the qLoader. When the limited space, the loader provides for patching data, was surpassed, I dumped a majority* of patches to 'client.exe', and renamed it to 'client2.exe', so the old patches wont work with it, and then I did it again with 'client3.exe', and now the qLoader is out of space again. (*from what I remember, not all patches can be applied directly to the executable)

What I have now. From the russian torrent I have the decompiled pdb, and also all the versions of 'client.exe', that can be used to understand what patches where made to the executable(I pray that the 'client.exe' is a clean one). Also I decompiled all the qLoader files found in the WAZAAAAAs 'DOAOcollection', and will try to look at patched data and maybe remember some things( the patches inside qLoaders are in groups).

Some plans. I saw that DoAX skins won't work with doa2u. The pack is provided with a qLoaderC5, I suppose this loader is patching the doaX skeleton hierarchy to look somewhat decent when used for the converted skins. I'd like to try and add these patches to doa2u, so the skins won't look like abominations. (this could break the look of the naked green kasumi clone that comes out of the jar, it's the only thing that uses this kind of skeleton)

Here is the python script I used to decompile qLoaders:
Python:
#-------------------------------------------------------------------------------
# Decompile r!sc patchers to original files for DoAOnline s/qLoaderXX patchers
#-------------------------------------------------------------------------------
import os, struct
inpath  = 'C:\WORK\doaol\qLoaders'                  #the path to the folder with s/qLoaderNN;
outpath = os.path.join(inpath, 'converted')         #files will be convertet to the 'converted' subfolder
if not os.path.exists(outpath): os.makedirs(outpath)#if path the output folder doesn't exist then make it


def main():
    for fname in os.listdir(inpath):
        if fname[-4:] == '.exe':
            with open(os.path.join(inpath,fname), 'rb') as f:
                f.seek(0x1204)
                exename = f.read(0x30).decode('utf8').rstrip(chr(0))
                olines = ["F="+exename, 'O='+fname, ";\tadd comments after ';' at the end of a line. (F=program_name, O=loader_name)"] #store text to onlines
                f.seek(0x1240)
                while True:
                    memofs,bcount = struct.unpack('<LH', f.read(6))
                    if memofs == 0x63732172: # b'r!sc' magic terminator
                        olines.append('$')
                        break
                    sbytes = ["%02x"%b for b in f.read(bcount)]
                    rbytes = ["%02x"%b for b in f.read(bcount)]
                    olines.append('P=%06X'%memofs + '/' + ','.join(sbytes) + '/' + ','.join(rbytes))

                with open(os.path.join(outpath,fname[:-4]+'.txt'), 'w') as fs: #open as text and write; TODO: .txt should be .rpp
                    fs.write(':\t\t\t\r\n'.join(olines))

if __name__ == '__main__':
    main()
And I attached to this post, the 'r!sc' tool I used to make qLoaders.(drag and drop the decompiled file to 'rpp.exe' to compile it back to a loader, or add a '*.rpp' extention to it and open it from the running 'rpp.exe' tool)
Good to see you again B0ny,btw do you have the costumes that USAGIZ sent in the Russian forum of doa online?
 
costumes that USAGIZ sent in the Russian forum
I don't have any files from the old days, sorry.

Have you tried Ghidra?
The bdb decompilers are just tools that extract data from a pdb file. Ghidra is like IDA. Maybe I'll have a look into it tho, for the 'client.exe'

Thank you for making DOAO immortal
Well, in the old days, it was really a thing, being the only doa game for PC. Now I don't really understand the need in DoAO, why would anyone still play it, when you can play DoA2U through an emulator, or play doa5/doa6 with tons of characters and skins. Maybe because of a weak pc? Or because of the online feature? Actually, what is the state of the doa2u online, is there a way to play pvp through internet?


the loaders... unfortunately time has passed and antiviruses no longer like those

If you find a better loader, I can port to it all the patches from s/qLoader. I had a look at what fixes are made by the loaders, and seems like the s/qLoaderC, are patching mostly the things related to compatibility with skins from doax and doa4, like modifying the dox skeleton hierarchy, and extending the size limits of doa/bin/cat/mot files to be able to load huge doa4 files. Seams like for online gameplay is no problem to run the client3.
 
Last edited:

CoYoTe

Active Member
I don't have any files from the old days, sorry.


The bdb decompilers are just tools that extract data from a pdb file. Ghidra is like IDA. Maybe I'll have a look into it tho, for the 'client.exe'


Well, in the old days, it was really a thing, being the only doa game for PC. Now I don't really understand the need in DoAO, why would anyone still play it, when you can play DoA2U through an emulator, or play doa5/doa6 with tons of characters and skins. Maybe because of a weak pc? Or because of the online feature? Actually, what is the state of the doa2u online, is there a way to play pvp through internet?




If you find a better loader, I can port to it all the patches from s/qLoader. I had a look at what fixes are made by the loaders, and seems like the s/qLoaderC, are patching mostly the things related to compatibility with skins from doax and doa4, like modifying the dox skeleton hierarchy, and extending the size limits of doa/bin/cat/mot files to be able to load huge doa4 files. Seams like for online gameplay is no problem to run the client3.
b0ny,if you want doa2u's xbe there he is
 

Attachments

  • default.xbe
    64 KB · Views: 193

Mallo

New Member
Actually, what is the state of the doa2u online, is there a way to play pvp through internet?
Well, there's no way to play DOA2U online (emulators don't support networking yet) other than through DOAO, so that's why it's still played.
 

WAZAAAAA

Well-Known Member
DOAO.exe updated to v4
Code:
- total installation size reduced by 1/3
- C5 Loaders replaced with C6
- some doaoLauncher.exe and newServer.exe GUI buttons started working again

DOAOcollection.7z updated to v3
Code:
VERSION 3 additions:
2021_b0ny_mopafo3971
DOA2U[EU]_doax_patch1
DOA2U_doax_patch2
Fix_for_missing_low_emp_files
rppv15.zip
idr-renamer.bat
qLoaders_Decompiler.py
Remove-uncompressed-textures.py
GSRtoDDSconverter.py
more newServers
more loaders

shoutouts to @mopafo3971 for these
 

CoYoTe

Active Member
DOAO.exe updated to v4
Code:
- total installation size reduced by 1/3
- C5 Loaders replaced with C6
- some doaoLauncher.exe and newServer.exe GUI buttons started working again

DOAOcollection.7z updated to v3
Code:
VERSION 3 additions:
2021_b0ny_mopafo3971
DOA2U[EU]_doax_patch1
DOA2U_doax_patch2
Fix_for_missing_low_emp_files
rppv15.zip
idr-renamer.bat
qLoaders_Decompiler.py
Remove-uncompressed-textures.py
GSRtoDDSconverter.py
more newServers
more loaders

shoutouts to @mopafo3971 for these
If only the close button crash was fixed.... Btw nice update,it's about time.
 

WAZAAAAA

Well-Known Member
@mopafo3971 i c u on doa.getbb.ru homie
reminder that you that you sort of made a DOAO server written in python, check DOAOcollection.7z\MotViewingTutorial\doao_pyserver... just saying in case you forgot lmao
 
@mopafo3971 i c u on doa.getbb.ru homie
reminder that you that you sort of made a DOAO server written in python, check DOAOcollection.7z\MotViewingTutorial\doao_pyserver... just saying in case you forgot lmao
I was asking for my old files. The pyserver is just a joke, managing online pvp is not a simple task to do.

----

Hey Wazaaaaa, here is a tutorial for you:
Make the newServer load it's files from the 'data' folder. (as mentioned in the first guide here: https://www.freestepdodge.com/threads/doa-online-download.8837/post-417170)
Open "6TRAINING2.bin" in a hex editor, go to address 0x20, change '01' to '00', and save the file.
Now "THE WHITE STORM" stage will have stormy whether in training mode(for everyone if you do it for the online server).
It's a pity i didn't find this many years ago, to add stormy "WHITE STORM" as a separate stage on the server.
 
Last edited:
What does 'ParallelServ' option do? It makes possible to run more doao servers on the same computer.
By default the server is running on these ports: TCP:8000,9900 UDP:9000, for login/lobby/ingame
If you want to run more than one doao server(channell), you copy the newServer to separate folders and set the 'ParallelServ' option of additional servers to 'ParallelServ=1'/'ParallelServ=2'/'ParallelServ=3', this will add the number to the port number, for 'ParallelServ=5' it will operate on the ports - TCP:8005,9905 UDP:9005. The additional servers should be added to the list of channels, to be accessed on login. Or custom qLoaders should be created, you can change the ip using the newServer but you'll have to change the port manually(it's right after the ip) using a hex editor.
In game, if you started with a login, you'll go to 'System'->'Switch Chanell' to jump to another server.
Why would you run multiple doao servers? To make sure that players will have the highest ping playing with players from the same continent on dedicated servers. Also to run private servers for experiments.
 
Python script to unpack doao '*.bgm' audio files:
Python:
#-------------------------------------------------------------------------------
# Name:        Dead or Alive OnLine bgm to ogg unpacker
#-------------------------------------------------------------------------------
import os, struct

bgm_path = r"C:\Games\DeadOrAliveOnline\data\ingame\Sound"
out_path = bgm_path

test = []
def main():
    for fname in os.listdir(bgm_path):
        if '.bgm' not in fname: continue
        with open(os.path.join(bgm_path, fname), 'rb') as f: fdata = f.read()
        if fdata[:10] != b'tl_cipher\x00': continue
        print(fname)
        xoreddata = bytes([b^1 for b in fdata[22:]])
        with open(os.path.join(out_path, fname[:-4]+'.ogg'), 'wb') as fs:
            fs.write(xoreddata[:82-22])

if __name__ == '__main__':
    main()

Python script to unpack doao '*.se' audio files:
Python:
#-------------------------------------------------------------------------------
# Dead or Alive OnLine se audio unpack to ogg with names
#-------------------------------------------------------------------------------
doao_se_path = r"C:\Games\DeadOrAliveOnline\data\ingame\env_se"   # \mvoice, \survival_se, \env_se, \game_se"
outpath = doao_se_path
read_only = 0

import os, struct
def main():
    for flname in os.listdir(doao_se_path):
        if flname[-3:] != '.se':
            continue
        with open(os.path.join(doao_se_path,flname), 'rb') as f:
                srtname = flname[:-3]
                head1 = f.read(0x10)
                if head1 != b'dlink\x00\x00\x00\x00\x00\x00l102\x00':
                    continue
                sesize, secount, is4, is0, names_block_offset, data_block_offset, is00, is000, is0000, str100 = struct.unpack('<10L', f.read(10 * 4))
                #read se names
                fnames = []
                names_block_size = 0
                if names_block_offset:
                    f.seek(names_block_offset)
                    names_block_size = struct.unpack('<L', f.read(4))[0]
                    fnames = [readstr(f) for i in range(secount)]
                print("\r", srtname, secount)
                #parse data // data starts with offsets
                suboffsets = [data_block_offset]
                f.seek(data_block_offset)
                suboffsets = struct.unpack('<%dL'%secount, f.read(secount*4))
                segments = list(set(suboffsets[:]+(sesize,)))
                segments.sort()
                print(suboffsets)

                for i in range(secount):
                    fname = fnames[i] if fnames else ''
                    foffset = suboffsets[i]
                    if not foffset:
                        continue
                    fsize = segments[segments.index(foffset)+1]-foffset
                    outname = "%s_[%02d]_%s.ogg"%(srtname, i, fname[:-4])
                    if not read_only:
                        savepath = os.path.join(outpath,outname)
                        f.seek(foffset)
                        oggfldata = f.read(fsize)
                        with open(savepath, 'wb') as fs:
                            fs.write(oggfldata)

                    #the code bellow is parsing the ogg header and is not necesary
                    f.seek(foffset + 28)
                    packet_type_1 = f.read(1) #identification header
                    vorbis1 = f.read(6)
                    vorbis_version0, audio_channels, audio_sample_rate, bitrate_maximum0, bitrate_nominal, bitrate_minimum0, blocksizes_4bits, framing_flag1 = struct.unpack('<LBLlllBB', f.read(5*4 + 3))
                    oggs014 = f.read(14)
                    u1, uconst_1, u3, blen = struct.unpack('<LLLB', f.read(13))
                    ffb = f.read(blen)
                    packet_type_3 = f.read(1) #comment header
                    vorbis2 = f.read(6)
                    vendor_len = struct.unpack('<L', f.read(4))[0]
                    vendor_str = f.read(vendor_len)
                    user_comments = []
                    user_comment_cnt = struct.unpack('<L', f.read(4))[0]
                    loop = None
                    volume = None
                    for c in range(user_comment_cnt):
                        user_comment_len = struct.unpack('<L', f.read(4))[0]
                        user_comment = f.read(user_comment_len)
                        user_comments.append(user_comment)
                        if user_comment[:5] == b'LOOP=':
                            if user_comment == b'LOOP=se':
                                loop = 0
                            else:
                                loop = user_comment[5:].decode('utf8')
                        elif user_comment[:7] == b'VOLUME=':
                            volume = user_comment[7:].decode('utf8')
                    print("VOL=%3s "%volume, "LOOP=%8s  "%loop, outname)


def readstr(f, pos=-1):
    if pos != -1:
        f.seek(pos)
    text = [f.read(1)]
    while text[-1] != b'\x00':
        text.append(f.read(1))
    return b''.join(text[:-1]).decode('utf-8')

if __name__ == '__main__':
    main()
 
Last edited:
ALL DOA6 DOA5 DOA4 DOA3 DOA2U DOAD
Top