News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Castlevania Circle of the Moon Dialogue  (Read 3726 times)

caminopreacher

  • Full Member
  • ***
  • Posts: 139
  • "What is a man?"
    • View Profile
Castlevania Circle of the Moon Dialogue
« on: December 15, 2019, 10:22:39 pm »
Hello all.
Would anyone know if there is a way to edit Circle of the Moon's dialogue? The DSVania Editor tool doesn't work. I have a conversion table, but it doesn't seem to be working either. Any ideas? Thanks!

Solid One

  • Full Member
  • ***
  • Posts: 123
  • Silent Fighter
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #1 on: December 16, 2019, 06:34:31 am »
About 9 years ago, me and some friends translated this game to brazilian portuguese. For the text part, we developed a dumper / inserter in python based on MetroID, another dumper / inserter for Metroid Zero Mission.

Here's the source code:

Code: [Select]
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-

#MetroID: [GBA]Metroid Zero Mission Dumper Inserter
#Copyright (C) 2007 Trans-Center, Odin
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

try: import psyco
except ImportError: pass
import sys
# POG é vida!
class CCOTMDI:
    def __init__(self, filename):
        self.rom_file = open(filename, "r+b")
        self.pointer_addresses = [0x670C64, 0x671163, 0x67084C, 0x670B8B]
        self.invert_three = lambda offset: ((offset << 16)|((offset & 0x00FF00))|(offset >> 16)) & 0xFFFFFF
        self.invert_table = lambda table: dict([[v,k] for k,v in table.items()])
        # Preguiça de codar um módulo para tabelas :)
        self.table = {0x09: "<QL>\n", 0x02: "<QS>\n", 0x0B: "<VRMLH>",
0x00: "<FIM>\n\n", 0x5C: "<SETAESQ>", 0x5D: "<SETACIMA>",
0x5E: "<SETABAIXO>", 0x5B: "<SETADIR>",
0x26: " ", 0x27: "_", 0x3E: "A", 0x4D: "B",
0x44: "C", 0x45: "D", 0x4E: "E", 0x56: "F",
0x4F: "G", 0x40: "H", 0x43: "I", 0x6B: "J",
0x5F: "L", 0x42: "M", 0x52: "N", 0x67: "O",
0x4B: "P", 0x3B: "Q", 0x46: "R", 0x41: "S",
0x47: "T", 0x60: "U", 0x6E: "V", 0x6D: "X",
0x6F: "Z", 0x29: "a", 0x3C: "b", 0x33: "c",
0x32: "d", 0x28: "e", 0x3A: "f", 0x39: "g",
0x31: "h", 0x2D: "i", 0x62: "j", 0x3D: "k",
0x30: "l", 0x36: "m", 0x2E: "n", 0x2B: "o",
0x38: "p", 0x61: "q", 0x2C: "r", 0x2F: "s",
0x2A: "t", 0x34: "u", 0x3F: "v", 0x37: "w",
0x57: "x", 0x65: "z", 0x64: "0", 0x6A: "1",
0x63: "2", 0x6C: "3", 0x71: "4", 0x69: "5",
0x72: "8", 0x35: ".", 0x4C: ",", 0x50: "+",
0x51: "'", 0x48: "?", 0x4A: "!", 0x68: "%",
0x70: "/", 0x73: "&", 0x54: "(", 0x55: ")",
0x58: "-", 0x59: "[", 0x5A: "]", 0x79: "á",
0x7A: "à", 0x7B: "ã", 0x7C: "â", 0x7D: "é",
0x87: "ê", 0x9A: "í", 0x9B: "ó", 0xA5: "õ",
0xAE: "ô", 0xAF: "ú", 0xCD: "ç", 0x66: "Á",
0x49: "É", 0x53: "Í"}
    def __readed_to_int(self, readed):
        """Bytes lidos para inteiros."""
        integer = 0
        for x in readed: integer = (integer << 8) | ord(x)
        return integer
    def __buffering_pointers(self):
        """Armazena ponteiros."""
        pointers_block_1, pointers_block_2 = [], []
        # Armazenando endereços do primeiro bloco
        self.rom_file.seek(self.pointer_addresses[0], 0)
        while self.rom_file.tell() <= self.pointer_addresses[1]:
            pointer = self.invert_three(self.__readed_to_int(self.rom_file.read(3)))
            pointers_block_1.append(pointer)
            self.rom_file.seek(1, 1)
        # Armazenando endereços do segundo bloco
        self.rom_file.seek(self.pointer_addresses[2], 0)
        while self.rom_file.tell() <= self.pointer_addresses[3]:
            pointer = self.invert_three(self.__readed_to_int(self.rom_file.read(3)))
            pointers_block_2.append(pointer)
            self.rom_file.seek(1, 1)
        return pointers_block_1, pointers_block_2
    def extract(self):
        """Extrai o texto da ROM."""
        text_addresses_1, text_addresses_2 = self.__buffering_pointers()
        script_file_1 = open("script_1.txt", "w+b")
        script_file_2 = open("script_2.txt", "w+b")
        # Escreve o Script 1
        for x in range(len(text_addresses_1)):
            self.rom_file.seek(text_addresses_1[x], 0)
            while True:
                bytes = self.__readed_to_int(self.rom_file.read(1))
                if self.table.has_key(bytes) and bytes != 0x0000: script_file_1.write(self.table[bytes])
                elif bytes == 0x0000:
                    script_file_1.write(self.table[bytes])
                    break
                else: script_file_1.write("<$" + hex(bytes) + ">")
        # Escreve o Script 2
        for x in range(len(text_addresses_2)):
            self.rom_file.seek(text_addresses_2[x], 0)
            while True:
                bytes = self.__readed_to_int(self.rom_file.read(1))
                if self.table.has_key(bytes) and bytes != 0x0000: script_file_2.write(self.table[bytes])
                elif bytes == 0x0000:
                    script_file_2.write(self.table[bytes])
                    break
                else: script_file_2.write("<$" + hex(bytes) + ">")       
        raw_input("\t* Extração concluída.\n\t  Pressione qualquer tecla para sair.")
        script_file_1.close()
        script_file_2.close()
    def insert(self, insertion_address = 0x700000): # Função Megazord
        """Insere o texto de volta na ROM."""
        self.rom_file.seek(insertion_address, 0)
        new_pointers_1, new_pointers_2 = [], []
        new_pointers_1.append(self.invert_three(self.rom_file.tell()))
        inverted_table = self.invert_table(self.table)
        try:
            script_file_1 = open("script_1.txt", "rb")
            script_file_2 = open("script_2.txt", "rb")
        except IOError:
            raw_input("\t* Arquivo de script não encontrado.\n\t  Pressione qualquer tecla para sair.")
            sys.exit()
        # Inserindo o texto do primeiro script de volta na ROM
        while True:
            byte = script_file_1.read(1)
            # Tratamento das tags
            if byte == "<":
                tag_string = ""
                while True:
                    tag_byte = script_file_1.read(1)
                    if tag_byte != ">":
                        tag_string += tag_byte
                        continue
                    elif tag_string[0] == "$":
                        self.rom_file.write(chr(int(tag_string[1:], 16) & 0xFF))
                        break
                    elif tag_string == "QL":
                        self.rom_file.write(chr(0x09))
                        break
                    elif tag_string == "QS":
                        self.rom_file.write(chr(0x02))
                        break
                    elif tag_string == "FIM":
                        self.rom_file.write(chr(0x00))
                        new_pointers_1.append(self.invert_three(self.rom_file.tell()))
                        break
                    elif tag_string == "VRMLH":
                        self.rom_file.write(chr(0x0B))
                        break
                    elif tag_string == "SETAESQ":
                        self.rom_file.write(chr(0x5C))
                        break
                    elif tag_string == "SETADIR":
                        self.rom_file.write(chr(0x5B))
                        break
                    elif tag_string == "SETACIMA":
                        self.rom_file.write(chr(0x5D))
                        break
                    elif tag_string == "SETABAIXO":
                        self.rom_file.write(chr(0x5E))
                        break
                    else:
                        raw_input("\t* Houve um erro com uma tag.\n\t  Pressione qualquer tecla para sair.")
                        sys.exit()
            # Tratamento dos caracteres
            elif inverted_table.has_key(byte):
                self.rom_file.write(chr(inverted_table[byte] & 0xFF))
                continue
            if not byte: break
        # Inserindo o texto do segundo script de volta na ROM
        new_pointers_2.append(new_pointers_1.pop())
        while True:
            byte = script_file_2.read(1)
            # Tratamento das tags
            if byte == "<":
                tag_string = ""
                while True:
                    tag_byte = script_file_2.read(1)
                    if tag_byte != ">":
                        tag_string += tag_byte
                        continue
                    elif tag_string[0] == "$":
                        self.rom_file.write(chr(int(tag_string[1:], 16) & 0xFF))
                        break
                    elif tag_string == "QL":
                        self.rom_file.write(chr(0x09))
                        break
                    elif tag_string == "QS":
                        self.rom_file.write(chr(0x02))
                        break
                    elif tag_string == "FIM":
                        self.rom_file.write(chr(0x00))
                        new_pointers_2.append(self.invert_three(self.rom_file.tell()))
                        break
                    elif tag_string == "VRMLH":
                        self.rom_file.write(chr(0x0B))
                        break
                    elif tag_string == "SETAESQ":
                        self.rom_file.write(chr(0x5C))
                        break
                    elif tag_string == "SETADIR":
                        self.rom_file.write(chr(0x5B))
                        break
                    elif tag_string == "SETACIMA":
                        self.rom_file.write(chr(0x5D))
                        break
                    elif tag_string == "SETABAIXO":
                        self.rom_file.write(chr(0x5E))
                        break
                    else:
                        raw_input("\t* Houve um erro com uma tag.\n\t  Pressione qualquer tecla para sair.")
                        sys.exit()
        # Tratamento dos caracteres
            elif inverted_table.has_key(byte):
                self.rom_file.write(chr(inverted_table[byte] & 0xFF))
                continue
            if not byte: break
        new_pointers_2.pop()
        # Atualização dos ponteiros
        self.rom_file.seek(self.pointer_addresses[0])
        for x in range(len(new_pointers_1)):
            self.rom_file.write(chr(new_pointers_1[x] >> 16))
            self.rom_file.write(chr(new_pointers_1[x] >> 8 & 0xFF))
            self.rom_file.write(chr(new_pointers_1[x] & 0xFF))
            self.rom_file.seek(1, 1)
        self.rom_file.seek(self.pointer_addresses[2])
        for y in range(len(new_pointers_2)):
            self.rom_file.write(chr(new_pointers_2[y] >> 16))
            self.rom_file.write(chr(new_pointers_2[y] >> 8 & 0xFF))
            self.rom_file.write(chr(new_pointers_2[y] & 0xFF))
            self.rom_file.seek(1, 1)
        raw_input("\t* Inserção dos textos concluída.\n\t  Pressione qualquer tecla para sair.")
        script_file_1.close()
        script_file_2.close()

if __name__ == "__main__":
    print """\t+===============================+
        |\tCCotM DI 0.1\t\t|\n\t|\tTrans-Center, 2010\t|\n\t|\tSolid_One\t\t|
        +===============================+"""
    while True:
        filename = raw_input(">>> Arquivo [GBA]Castlevania Circle of the Moon: ")
        if filename == "": filename = "[GBA]Castlevania Circle of the Moon.gba"
        try:
            action = CCOTMDI(filename)
            while True:
                print ">>> Escolha opção:\n\t1. Extrair Texto(Via Ponteiros)\n\t2. Inserir Texto\n\t3. Sair do Programa"
                task = raw_input(">>> Sua opção: ")
                if task.isdigit() == True: task = int(task)
                if task < 1 or task > 3: print "\t* Inválido..."
                elif task == 1:
                    action.extract()
                    break
                elif task == 2:
                    action.insert()
                    break
                else:
                    sys.exit()
            break
        except IOError:
            print "\t* Arquivo %s não encontrado." % filename
            continue

And here's some instructions to make it work:

Dumping scripts
1. Copy and paste all contents in the code tag above, and save it into a file named "ccotm_di.py";
2. Copy the original american Circle of the Moon rom into the same folder of the file above (it should have crc32 1cc059a4). Preferrably, rename it to "ccotm.gba";
3. Install Python interpreters into your computer. Preferrably, grab any 2.7.x version, since I don't know for sure if it'll work on Python 3;
4. Run it on terminal with "python ccotm_di.py";
5. Type the name of the original Circle of the Moon rom ("ccotm.gba", according to step 2) and press Enter;
6. Choose option 1 in order to extract all game texts into two script files (script_1.txt and script_2.txt);

Inserting scripts back
1. Edit your script files as you wish;
2. Run the tool again on terminal with "python ccotm_di.py";
3. Type the name of the original Circle of the Moon rom ("ccotm.gba", according to step 2 in the "Dumping scripts" section above) and press Enter;
4. Choose option 2 in order to insert back the game texts from the script files into the rom. It'll insert them into an area with lots of empty space in the end of the rom, and it'll automatically update all text pointers for you.


The code tag below shows what you should see on both steps above:

Code: [Select]
+===============================+
        | CCotM DI 0.1 |
| Trans-Center, 2010 |
| Solid_One |
        +===============================+
>>> Arquivo [GBA]Castlevania Circle of the Moon: CCOTM.gba
>>> Escolha opção:
1. Extrair Texto(Via Ponteiros)
2. Inserir Texto
3. Sair do Programa
>>> Sua opção:

And that's it. Hope it helps.

Morinis

  • Sr. Member
  • ****
  • Posts: 465
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #2 on: December 16, 2019, 09:58:13 am »
Hello all.
Would anyone know if there is a way to edit Circle of the Moon's dialogue? The DSVania Editor tool doesn't work. I have a conversion table, but it doesn't seem to be working either. Any ideas? Thanks!


DSVania Editor won't support CotM as the creator has no plans to bring said support to the program sadly.



There are quite a few of us still waiting for a CotM editor so you're not alone :P
YouTube: https://www.youtube.com/channel/UCK5S3RZCjv0O6FmXlSgmHXg


"If you get offended by my honesty then re-evaluate your hobbies on here."

caminopreacher

  • Full Member
  • ***
  • Posts: 139
  • "What is a man?"
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #3 on: December 16, 2019, 04:54:52 pm »
About 9 years ago, me and some friends translated this game to brazilian portuguese. For the text part, we developed a dumper / inserter in python based on MetroID, another dumper / inserter for Metroid Zero Mission.

Here's the source code:

Code: [Select]
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-

#MetroID: [GBA]Metroid Zero Mission Dumper Inserter
#Copyright (C) 2007 Trans-Center, Odin
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

try: import psyco
except ImportError: pass
import sys
# POG é vida!
class CCOTMDI:
    def __init__(self, filename):
        self.rom_file = open(filename, "r+b")
        self.pointer_addresses = [0x670C64, 0x671163, 0x67084C, 0x670B8B]
        self.invert_three = lambda offset: ((offset << 16)|((offset & 0x00FF00))|(offset >> 16)) & 0xFFFFFF
        self.invert_table = lambda table: dict([[v,k] for k,v in table.items()])
        # Preguiça de codar um módulo para tabelas :)
        self.table = {0x09: "<QL>\n", 0x02: "<QS>\n", 0x0B: "<VRMLH>",
0x00: "<FIM>\n\n", 0x5C: "<SETAESQ>", 0x5D: "<SETACIMA>",
0x5E: "<SETABAIXO>", 0x5B: "<SETADIR>",
0x26: " ", 0x27: "_", 0x3E: "A", 0x4D: "B",
0x44: "C", 0x45: "D", 0x4E: "E", 0x56: "F",
0x4F: "G", 0x40: "H", 0x43: "I", 0x6B: "J",
0x5F: "L", 0x42: "M", 0x52: "N", 0x67: "O",
0x4B: "P", 0x3B: "Q", 0x46: "R", 0x41: "S",
0x47: "T", 0x60: "U", 0x6E: "V", 0x6D: "X",
0x6F: "Z", 0x29: "a", 0x3C: "b", 0x33: "c",
0x32: "d", 0x28: "e", 0x3A: "f", 0x39: "g",
0x31: "h", 0x2D: "i", 0x62: "j", 0x3D: "k",
0x30: "l", 0x36: "m", 0x2E: "n", 0x2B: "o",
0x38: "p", 0x61: "q", 0x2C: "r", 0x2F: "s",
0x2A: "t", 0x34: "u", 0x3F: "v", 0x37: "w",
0x57: "x", 0x65: "z", 0x64: "0", 0x6A: "1",
0x63: "2", 0x6C: "3", 0x71: "4", 0x69: "5",
0x72: "8", 0x35: ".", 0x4C: ",", 0x50: "+",
0x51: "'", 0x48: "?", 0x4A: "!", 0x68: "%",
0x70: "/", 0x73: "&", 0x54: "(", 0x55: ")",
0x58: "-", 0x59: "[", 0x5A: "]", 0x79: "á",
0x7A: "à", 0x7B: "ã", 0x7C: "â", 0x7D: "é",
0x87: "ê", 0x9A: "í", 0x9B: "ó", 0xA5: "õ",
0xAE: "ô", 0xAF: "ú", 0xCD: "ç", 0x66: "Á",
0x49: "É", 0x53: "Í"}
    def __readed_to_int(self, readed):
        """Bytes lidos para inteiros."""
        integer = 0
        for x in readed: integer = (integer << 8) | ord(x)
        return integer
    def __buffering_pointers(self):
        """Armazena ponteiros."""
        pointers_block_1, pointers_block_2 = [], []
        # Armazenando endereços do primeiro bloco
        self.rom_file.seek(self.pointer_addresses[0], 0)
        while self.rom_file.tell() <= self.pointer_addresses[1]:
            pointer = self.invert_three(self.__readed_to_int(self.rom_file.read(3)))
            pointers_block_1.append(pointer)
            self.rom_file.seek(1, 1)
        # Armazenando endereços do segundo bloco
        self.rom_file.seek(self.pointer_addresses[2], 0)
        while self.rom_file.tell() <= self.pointer_addresses[3]:
            pointer = self.invert_three(self.__readed_to_int(self.rom_file.read(3)))
            pointers_block_2.append(pointer)
            self.rom_file.seek(1, 1)
        return pointers_block_1, pointers_block_2
    def extract(self):
        """Extrai o texto da ROM."""
        text_addresses_1, text_addresses_2 = self.__buffering_pointers()
        script_file_1 = open("script_1.txt", "w+b")
        script_file_2 = open("script_2.txt", "w+b")
        # Escreve o Script 1
        for x in range(len(text_addresses_1)):
            self.rom_file.seek(text_addresses_1[x], 0)
            while True:
                bytes = self.__readed_to_int(self.rom_file.read(1))
                if self.table.has_key(bytes) and bytes != 0x0000: script_file_1.write(self.table[bytes])
                elif bytes == 0x0000:
                    script_file_1.write(self.table[bytes])
                    break
                else: script_file_1.write("<$" + hex(bytes) + ">")
        # Escreve o Script 2
        for x in range(len(text_addresses_2)):
            self.rom_file.seek(text_addresses_2[x], 0)
            while True:
                bytes = self.__readed_to_int(self.rom_file.read(1))
                if self.table.has_key(bytes) and bytes != 0x0000: script_file_2.write(self.table[bytes])
                elif bytes == 0x0000:
                    script_file_2.write(self.table[bytes])
                    break
                else: script_file_2.write("<$" + hex(bytes) + ">")       
        raw_input("\t* Extração concluída.\n\t  Pressione qualquer tecla para sair.")
        script_file_1.close()
        script_file_2.close()
    def insert(self, insertion_address = 0x700000): # Função Megazord
        """Insere o texto de volta na ROM."""
        self.rom_file.seek(insertion_address, 0)
        new_pointers_1, new_pointers_2 = [], []
        new_pointers_1.append(self.invert_three(self.rom_file.tell()))
        inverted_table = self.invert_table(self.table)
        try:
            script_file_1 = open("script_1.txt", "rb")
            script_file_2 = open("script_2.txt", "rb")
        except IOError:
            raw_input("\t* Arquivo de script não encontrado.\n\t  Pressione qualquer tecla para sair.")
            sys.exit()
        # Inserindo o texto do primeiro script de volta na ROM
        while True:
            byte = script_file_1.read(1)
            # Tratamento das tags
            if byte == "<":
                tag_string = ""
                while True:
                    tag_byte = script_file_1.read(1)
                    if tag_byte != ">":
                        tag_string += tag_byte
                        continue
                    elif tag_string[0] == "$":
                        self.rom_file.write(chr(int(tag_string[1:], 16) & 0xFF))
                        break
                    elif tag_string == "QL":
                        self.rom_file.write(chr(0x09))
                        break
                    elif tag_string == "QS":
                        self.rom_file.write(chr(0x02))
                        break
                    elif tag_string == "FIM":
                        self.rom_file.write(chr(0x00))
                        new_pointers_1.append(self.invert_three(self.rom_file.tell()))
                        break
                    elif tag_string == "VRMLH":
                        self.rom_file.write(chr(0x0B))
                        break
                    elif tag_string == "SETAESQ":
                        self.rom_file.write(chr(0x5C))
                        break
                    elif tag_string == "SETADIR":
                        self.rom_file.write(chr(0x5B))
                        break
                    elif tag_string == "SETACIMA":
                        self.rom_file.write(chr(0x5D))
                        break
                    elif tag_string == "SETABAIXO":
                        self.rom_file.write(chr(0x5E))
                        break
                    else:
                        raw_input("\t* Houve um erro com uma tag.\n\t  Pressione qualquer tecla para sair.")
                        sys.exit()
            # Tratamento dos caracteres
            elif inverted_table.has_key(byte):
                self.rom_file.write(chr(inverted_table[byte] & 0xFF))
                continue
            if not byte: break
        # Inserindo o texto do segundo script de volta na ROM
        new_pointers_2.append(new_pointers_1.pop())
        while True:
            byte = script_file_2.read(1)
            # Tratamento das tags
            if byte == "<":
                tag_string = ""
                while True:
                    tag_byte = script_file_2.read(1)
                    if tag_byte != ">":
                        tag_string += tag_byte
                        continue
                    elif tag_string[0] == "$":
                        self.rom_file.write(chr(int(tag_string[1:], 16) & 0xFF))
                        break
                    elif tag_string == "QL":
                        self.rom_file.write(chr(0x09))
                        break
                    elif tag_string == "QS":
                        self.rom_file.write(chr(0x02))
                        break
                    elif tag_string == "FIM":
                        self.rom_file.write(chr(0x00))
                        new_pointers_2.append(self.invert_three(self.rom_file.tell()))
                        break
                    elif tag_string == "VRMLH":
                        self.rom_file.write(chr(0x0B))
                        break
                    elif tag_string == "SETAESQ":
                        self.rom_file.write(chr(0x5C))
                        break
                    elif tag_string == "SETADIR":
                        self.rom_file.write(chr(0x5B))
                        break
                    elif tag_string == "SETACIMA":
                        self.rom_file.write(chr(0x5D))
                        break
                    elif tag_string == "SETABAIXO":
                        self.rom_file.write(chr(0x5E))
                        break
                    else:
                        raw_input("\t* Houve um erro com uma tag.\n\t  Pressione qualquer tecla para sair.")
                        sys.exit()
        # Tratamento dos caracteres
            elif inverted_table.has_key(byte):
                self.rom_file.write(chr(inverted_table[byte] & 0xFF))
                continue
            if not byte: break
        new_pointers_2.pop()
        # Atualização dos ponteiros
        self.rom_file.seek(self.pointer_addresses[0])
        for x in range(len(new_pointers_1)):
            self.rom_file.write(chr(new_pointers_1[x] >> 16))
            self.rom_file.write(chr(new_pointers_1[x] >> 8 & 0xFF))
            self.rom_file.write(chr(new_pointers_1[x] & 0xFF))
            self.rom_file.seek(1, 1)
        self.rom_file.seek(self.pointer_addresses[2])
        for y in range(len(new_pointers_2)):
            self.rom_file.write(chr(new_pointers_2[y] >> 16))
            self.rom_file.write(chr(new_pointers_2[y] >> 8 & 0xFF))
            self.rom_file.write(chr(new_pointers_2[y] & 0xFF))
            self.rom_file.seek(1, 1)
        raw_input("\t* Inserção dos textos concluída.\n\t  Pressione qualquer tecla para sair.")
        script_file_1.close()
        script_file_2.close()

if __name__ == "__main__":
    print """\t+===============================+
        |\tCCotM DI 0.1\t\t|\n\t|\tTrans-Center, 2010\t|\n\t|\tSolid_One\t\t|
        +===============================+"""
    while True:
        filename = raw_input(">>> Arquivo [GBA]Castlevania Circle of the Moon: ")
        if filename == "": filename = "[GBA]Castlevania Circle of the Moon.gba"
        try:
            action = CCOTMDI(filename)
            while True:
                print ">>> Escolha opção:\n\t1. Extrair Texto(Via Ponteiros)\n\t2. Inserir Texto\n\t3. Sair do Programa"
                task = raw_input(">>> Sua opção: ")
                if task.isdigit() == True: task = int(task)
                if task < 1 or task > 3: print "\t* Inválido..."
                elif task == 1:
                    action.extract()
                    break
                elif task == 2:
                    action.insert()
                    break
                else:
                    sys.exit()
            break
        except IOError:
            print "\t* Arquivo %s não encontrado." % filename
            continue

And here's some instructions to make it work:

Dumping scripts
1. Copy and paste all contents in the code tag above, and save it into a file named "ccotm_di.py";
2. Copy the original american Circle of the Moon rom into the same folder of the file above (it should have crc32 1cc059a4). Preferrably, rename it to "ccotm.gba";
3. Install Python interpreters into your computer. Preferrably, grab any 2.7.x version, since I don't know for sure if it'll work on Python 3;
4. Run it on terminal with "python ccotm_di.py";
5. Type the name of the original Circle of the Moon rom ("ccotm.gba", according to step 2) and press Enter;
6. Choose option 1 in order to extract all game texts into two script files (script_1.txt and script_2.txt);

Inserting scripts back
1. Edit your script files as you wish;
2. Run the tool again on terminal with "python ccotm_di.py";
3. Type the name of the original Circle of the Moon rom ("ccotm.gba", according to step 2 in the "Dumping scripts" section above) and press Enter;
4. Choose option 2 in order to insert back the game texts from the script files into the rom. It'll insert them into an area with lots of empty space in the end of the rom, and it'll automatically update all text pointers for you.


The code tag below shows what you should see on both steps above:

Code: [Select]
+===============================+
        | CCotM DI 0.1 |
| Trans-Center, 2010 |
| Solid_One |
        +===============================+
>>> Arquivo [GBA]Castlevania Circle of the Moon: CCOTM.gba
>>> Escolha opção:
1. Extrair Texto(Via Ponteiros)
2. Inserir Texto
3. Sair do Programa
>>> Sua opção:

And that's it. Hope it helps.

Awesome! Thanks! :beer:

December 16, 2019, 04:57:12 pm - (Auto Merged - Double Posts are not allowed before 7 days.)

DSVania Editor won't support CotM as the creator has no plans to bring said support to the program sadly.



There are quite a few of us still waiting for a CotM editor so you're not alone :P

Glad I'm not the only one... Still rewriting 2 of the 3 gba vanias isn't bad. And since COTM has the least amount of story and is non-canon, I guess it can wait. I'm still mad we couldn't play as Hugh though. Did you see the Aria of Sorrow Hugh Baldwin hack?

Thirteen 1355

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #4 on: December 17, 2019, 05:17:09 am »
I don't like how it's been made not canon. It sure is the worst Metroid CV but it's still a great game
Helicoptering about till I find some ROM hacking treasure.

Vanya

  • Hero Member
  • *****
  • Posts: 1752
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #5 on: December 17, 2019, 07:26:06 am »
I've always been of a mind that it could fairly easily be reworked into a backstory for Order of Ecclesia with just a few story edits, name changes, and changing a couple of the cut scenes to fully replace Dracula with Carmilla as the antagonist focusing on the prossession of Dracula's remains.

Thirteen 1355

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #6 on: December 17, 2019, 07:51:05 am »
I've always seen Ecclesia as a nice sequel to Symphony. I'd like to see Circle reworked as taking place before Bloodlines/Portrait.
Helicoptering about till I find some ROM hacking treasure.

Vanya

  • Hero Member
  • *****
  • Posts: 1752
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #7 on: December 17, 2019, 06:51:26 pm »
The way I rote it, it's kind of both.

Thirteen 1355

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #8 on: December 18, 2019, 07:50:11 am »
Cool, I'm interested to see that.
Helicoptering about till I find some ROM hacking treasure.

Vanya

  • Hero Member
  • *****
  • Posts: 1752
    • View Profile
Re: Castlevania Circle of the Moon Dialogue
« Reply #9 on: December 18, 2019, 08:54:26 pm »
I'll see if I can dig it out of my old hard drive.