Cotton 2 English Patch

Translating Cotton 2 0.9

Here is a brief update on the current status.

Thanks to @Danthrax's help the script is now final. I re-edited the intro images and the first scene with the updated text and moved on to the second scene. This scene caused some problems because the data is laid out somewhat differently than before, but I managed to figure it out. At this moment I've finished 6 out of the 8 scenes. After the last two scenes are done, the things left to do will be:
  • Translate the 3 or 4 text images that use the shaded hand-drawn style
  • Translate the stage hints that are displayed when you die
  • Translate the error screens that are shown when there is a problem with the RAM cartridge
 
Here is a brief update on the current status.

Thanks to @Danthrax's help the script is now final. I re-edited the intro images and the first scene with the updated text and moved on to the second scene. This scene caused some problems because the data is laid out somewhat differently than before, but I managed to figure it out. At this moment I've finished 6 out of the 8 scenes. After the last two scenes are done, the things left to do will be:
  • Translate the 3 or 4 text images that use the shaded hand-drawn style
  • Translate the stage hints that are displayed when you die
  • Translate the error screens that are shown when there is a problem with the RAM cartridge
Feel free to toss anything else my way for editing!
 
Update time.

I'm in the final stretch of the project. Everything is translated now except for the three images that use the handwritten shaded font. I'll play test the game now on real hardware and do some fine tuning where necessary. I'll also try to design something for the remaining images. I'll probably try to find a nice looking handwritten font and shade it myself.

It shouldn't be long now before I release.
 
Can you post those handwritten messages here (as they appear in the game), so we might be able to help with translations?
 
Can you post those handwritten messages here (as they appear in the game), so we might be able to help with translations?

These are the images. The translated versions should say:

0046_CHR_VS0: You there!!
0100_CHR_VS0: Here I go!!
0164_CHR_VS7: The taste was so-so, was it?!!

If someone wants to try to design something I would appreciate it. But please submit a letter or two before doing all the text, because I don't want people to do work, only for me to use something else. Also, don't use any fonts you don't have a license to use. I need to know which font you used to determine if it's ok.

Edit: I should add that I'm willing to pay to license a font if it's reasonably priced. In fact, I already paid for the font I use as normal game font.
 

Attachments

  • 0046_CHR_VS0.png
    0046_CHR_VS0.png
    16.7 KB · Views: 262
  • 0100_CHR_VS0.png
    0100_CHR_VS0.png
    2.8 KB · Views: 265
  • 0164_CHR_VS7.png
    0164_CHR_VS7.png
    3.8 KB · Views: 280
Last edited:
Update time.

I'm in the final stretch of the project. Everything is translated now except for the three images that use the handwritten shaded font. I'll play test the game now on real hardware and do some fine tuning where necessary. I'll also try to design something for the remaining images. I'll probably try to find a nice looking handwritten font and shade it myself.

It shouldn't be long now before I release.
If you are releasing via my tool give me a heads up since the version I sent you is not a public release.
 
The patch is now available to download in the resources section. Please enjoy the game and report any problems you find.

On a related note, Success recently published Cotton Remake on Nintendo Switch in Japan. If you want to support the original developer or want to see more of the Cotton Series, it might be worth a look.
 
Last edited:
The patch is now available to download in the resources section. Please enjoy the game and report any problems you find.

On a related note, Success recently published Cotton Remake on Nintendo Switch in Japan. If you want to support the original developer or want to see more of the Cotton Series, it might be worth a look.

Congratulations, Nanash! I can't wait to play it later today. Thanks for letting me help out a little with the script editing.

As for Cotton Reboot, I took the plunge for a Switch collector's edition a couple weeks ago. Couldn't resist the art book and tea set. But most of all, I'm glad to be able to show support to Success for the franchise.
 
The patch is now available to download in the resources section. Please enjoy the game and report any problems you find.

On a related note, Success recently published Cotton Remake on Nintendo Switch in Japan. If you want to support the original developer or want to see more of the Cotton Series, it might be worth a look.
Thanks for this, gonna try it today!
 
if the fullscreen hack is added, I recommend using the "Optional" choice, which will prompt a user if they want to apply it.
 
can you add the fullscreen hack in the patch?
(it removes the black borders around the image)

Is the fullscreen hack not compatible with the translated version? I think it would make more sense to make it compatible than to incorporate it into my patch, since both hacks have different scopes.
 
Last edited:
Is the fullscreen hack not compatible with the translated version? I think it would make more sense to make it compatible than to incorporate it into my patch, since both hacks have different scopes.
They are compatible. You do not touch A00.bin.


can you add the fullscreen hack in the patch?
(it removes the black borders around the image)

SSP is just a renamed zip file.

If you rename the extention to ZIP, you can open it in windows.

Rename A00.BIN in the patch to A00.BIN._RPL and drop it in the main directory of the zip.

Rename the zip back to SSP, and you should be good.
 
After helping out on some other rom hacking projects, I'm now back at working on the 1.0 version of the Cotton 2 translation. Currently I'm only aware of one minor error in the script that needs to be fixed. If there is anything else, now would be a good time to report it. Since this alone would be such a minor update, I decided to do a popular challenge for advanced rom hackers: Making a variable width font (vwf) for the game.

Like most Japanese games Cotton 2 uses a monospace font, i.e. all text characters are printed on fixed grid. For the current version of the patch I just changed the spacing of the grid. This looks fine to be honest, but there is some awkward spacing here and there. Mainly around narrow characters like "i" and "l". So what you want to do is adjust the spacing depending on the width of the characters.

To achieve this, I need to change the games code in some way. If already done this in some minor ways to adjust the monospace font spacing, text speed and to reduce the frequency of the typing sound fx. These were mostly minor changes, where I just changed some immediates, literals and constants in the assembly code. Only the sound fx required some code injection. I actually wrote it directly in machine language, which is only really viable for very simple stuff, because things like loading literals relative to the PC can get annoying very fast. Luckily I already have a working assembly toolchain ready now, because I needed one for the Rent-A-Hero No.1 hacking project. The toolchain/IDE I use is HEW aka "High-performance Embedded Workshop". It's meant to be used to program Renesas MCUs like the SuperH family and works like a charm for this application.

To modify the text drawing routine, you first have to understand how it works. I believe I've written about how the game works before, but not in great detail. All of the game's assets are stored in a container format with the extension *.MF, all the game's code is stored in *.bin files. The game uses a different bin file for each scene. So every cut scene and every level has it's own file. This also means that there is a lot of redundant code. To create a vwf, the game needs to know the width of each character, so the first task is to get this information into the game.

Unlike most text heavy games like RPGs, Cotton 2 doesn't really have a dedicated text rendering routine. I suspect the devs basically repurposed their normal level code to create the cut scenes and the whole thing turned out a bit hack-y. Here are my reasons: There is no traditional font table in the game, instead the game stores each character as a separate image together with all the other images of that scene. Meaning functionally there isn't really a difference between the letter "A" and a character sprite, for example. All images are stored together in a section called *.SPT of the *.MF file. Each image in this section has it's own header that contains it's width, height and size. I wrote a script that decomposes the *.SPT section into a human readable format, so here is an example from the first cut scene:

Code:
0000,0000_CHR_VS0.tlm,16842752,352,224,0
0001,0001_CHR_VS0.tlm,16842752,352,224,0
0002,0002_CHR_VS0.tlm,16842752,296,448,0
0003,0003_CHR_VS0.tlm,16842752,296,112,0
0004,0004_CHR_VS0.lz00,0,296,112,4
0005,0005_CHR_VS0.lz00,0,296,112,4
0006,0006_CHR_VS0.lz00,0,296,112,4
0007,0007_CHR_VS0.lz00,0,296,112,4
0008,0008_CHR_VS0.lz00,0,88,72,4
0009,0009_CHR_VS0.lz00,0,88,72,4
0010,0010_CHR_VS0.lz00,0,64,64,4
0011,0011_CHR_VS0.lz00,0,64,64,4
0012,0012_CHR_VS0.lz00,0,64,72,4
0013,0013_CHR_VS0.lz00,0,88,80,4
...

Since each character is an image and each image has a header that contains it's width, I thought getting the width information would be straight forward. Just change the width of each character image to it's true width (e.g. i -> 3px, A -> 8px, comma -> 4px, ...) and then read the information from the image header. (The image width doesn't affect the font spacing though, so I'd still need write my own routine.) But hardware limitations made this approach impossible. As it turns out, the VDP1 can only draw sprites with a width divisible by 8. So my character images have to retain the 8x16 size or otherwise they can't be drawn. Luckily I found out that I can append information to images without breaking anything. Since images are loaded by pointer and the size is calculated by width*height*bpp (bit per pixel), data appended to the image gets completely ignored by the game. I can just append the true width the character as 4 byte integer and load this information later to determine the correct spacing.

With the spacing information now in the game, the next step is to write the new spacing calculation. The text of the game is stored in the *.SCH section of the *.MF file. This section contains instruction on how to load images, again not just text images, but all the images of the scene. Here is what it looks like decomposed to a text file:

Code:
0000,0,0,1,1,0,0,0,0
0001,0,0,1,1,0,0,0,0
0002,0,0,1,1,0,0,0,0
0003,0,0,1,1,0,0,0,0
0004,64,0,1,1,0,0,0,0
0005,65,0,1,1,0,0,0,0
0006,65,0,1,1,0,0,0,0
[...]
#pause4,74,0,1,1,0,0,0,0
#scroll,74,0,1,1,0,0,0,0
0114,74,0,1,1,0,0,0,0
#end,74,0,1,1,0,0,0,0
#endz,74,0,1,1,0,0,0,0
#starta,74,0,1,1,0,0,0,0
H,74,0,1,1,0,0,0,0
u,74,0,1,1,0,0,0,0
h,74,0,1,1,0,0,0,0
?,74,0,1,1,0,0,0,0
#pause4,74,0,1,1,0,0,0,0
0114,74,0,1,1,0,0,0,0
\n,74,0,1,1,0,0,0,0
#end,74,0,1,1,103,0,0,0
#starta,74,0,1,1,0,0,0,0
H,74,0,1,1,0,0,0,0
e,74,0,1,1,0,0,0,0
0123,74,0,1,1,0,0,0,0
y,74,0,1,1,0,0,0,0
!,74,0,1,1,0,0,0,0
...

The first item in each row is a relative pointer to the image in the *.SPT section. I've replaced it with a symbolic name of the image to make the translation easier. I actually translated all the text in the game by editing this decomposed text view and recomposing it to the binary representation. But back to the problem at hand. To draw text, the game uses a construct it calls "Event Manager". In a nut shell it's a way to schedule function calls, like a task manager. Here the game schedules a call to the function "InitVisualMessage_Grp" which schedules a call to "InitVisualMessage_Line" for each line of text which schedules a call to "InitVisualMessage_Chr" for each character. InitVisualMessage_Chr is where the magic happens. Here the spacing is calculated. In the unmodified version the position calculation works like this:

Character position = Start Offset + Line Position X 13

Here, 13 is the fixed character spacing or the text grid. In assembly it looks like this:

Code:
mov.w   @r12, r2        ; line position
mov     #h'D, r1        ; default distance to next character
muls    r1, r2
sts     macl, r2
mov.l   @r8, r1         ; start offset
shll16  r2
add     r2, r1
mov.l   r1, @r8

So what I have to do instead is:
  1. Store the last position I've written to in memory
  2. Load the character width from the appended image data
  3. Add this width to the last position to get the current position
  4. Add this to start offset and write it to appropriate memory position
Here is what it looks like in assembly (written in HEW):

Code:
; ###################################################################
;
; Write custom vwf character width
;
; arg0 = char_idx
; arg1 = p_mem
;
; Variables
;
mf_file_bp:            .assign h'6069920
sch_idx_:            .reg r6
p_img:                .reg r7
mf_idx:                .reg r8
p_line_pos            .reg r9
                    .section new,code
f_vwf_gwidth:
                      mov.l   r8, @-r15
                    mov.l   r9, @-r15
                    sts.l     pr, @-r15
                    ; Reset the line position if we're at position 0
                    mov.l    literal3, p_line_pos
                    tst        r4, r4
                    bf/s    skip_lpos_rst
                    mov        r5, r8
                    mov        #0, r0
                    mov        r0, @p_line_pos
skip_lpos_rst:
                    add        #h'48, r8
                    mov.l    @r8, r8                    ; (mf_idx, sch_idx)
                    extu.w    r8, sch_idx_            ; sch_idx
                    shlr16    mf_idx                    ; mf_idx
                    mov        #h'4c, r1                ; sizeof(mf_meta_t)
                    mul.l    r1, mf_idx
                    mov.l    #mf_file_bp, r1            ; mf_meta_t base pointer
                    sts        macl, r3
                    add        r1, r3                    ; pointer to mf_meta_t of specific mf file
                    mov        sch_idx_, r1
                    shll2    r1
                    mov        r1, r0
                    mov.l     @(8, r3), r2            ; bp_sch from mf_meta_t
                    mov.l    @(r0, r2), r1            ; p_sch from pointer table
                    mov.l    @(12, r3), p_img        ; bp_spt from mf_meta_t
                    mov        r2, r0
                    mov.l    @(r0, r1), r1            ; load spt_offset
                    add        r1, p_img                ; p_img = bp_spt + spt_offset
                    add        #h'60, p_img            ; offset to width information
                    mov.l    @p_img, r1                ; load width of character
                    mov        @p_line_pos, r2
                    mov        r2, r3
                    add        r1, r3
                    mov        r3, @p_line_pos
                    mov.l   @r5, r1                    ; left line offset
                    shll16  r2
                    add     r2, r1
                    mov.l   r1, @r5                    ; write char position
                    lds.l     @r15+, pr
                    mov.l   @r15+, r9
                    rts
                    mov.l   @r15+, r8
literal3:
                    .data.l var

And after all this rather dry explanation, here is the final result:


test.png
 
Last edited:
Back
Top