HomeForumsWhat's newResources 
 
 
Translating Cotton 2 0.9
nanash1 - May 22, 2020

 < Prev  1  2  3  4  Next> 

 nanash1 Feb 14, 2021
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

 Danthrax Feb 15, 2021

nanash1 said:

Feel free to toss anything else my way for editing!

 derek (ateam) Feb 16, 2021
Thrilled to see yet another fantastic Saturn fan translation project make such tremendous progress. Keep up the great work!

 nanash1 Feb 28, 2021
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.

 rorirub Feb 28, 2021
Can you post those handwritten messages here (as they appear in the game), so we might be able to help with translations?

 nanash1 Mar 1, 2021

rorirub said:


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.

 Knight0fDragon Mar 1, 2021

nanash1 said:

If you are releasing via my tool give me a heads up since the version I sent you is not a public release.

 nanash1 Mar 9, 2021
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.

 Danthrax Mar 10, 2021

nanash1 said:


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.

 derek (ateam) Mar 10, 2021
Congratulations, fantastic work!

 niuus Mar 10, 2021

nanash1 said:

Thanks for this, gonna try it today!

 retrodadandmodernlad Mar 11, 2021
Great work on the cotton 2 english translation. I had a play of it last night and really enjoyed it, thank you. I also took some footage and did a video.


https://youtube.com/AiCi07w3KhI


 gameofyou1 Mar 19, 2021
Was able to try this out the other night. It is awesome to finally play through this game in english! Well done!

 Knight0fDragon Mar 22, 2021
if the fullscreen hack is added, I recommend using the "Optional" choice, which will prompt a user if they want to apply it.

 Danthrax Mar 22, 2021
Would there be some sort of performance tradeoff to the widescreen hack?

 nanash1 Mar 23, 2021

ADFadsf said:


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.

 Knight0fDragon Mar 23, 2021

nanash1 said:

They are compatible. You do not touch A00.bin.



ADFadsf said:


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.

 nanash1 May 14, 2021
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:



 Danthrax May 18, 2021
It looks beautiful. Great job!

 thesegaguru Aug 25, 2021
Just a heads up if anyone is interested, i've done a little video just taking a look at the translation. Great work and have to say, love the game!


https://youtube.com/CIHr8ua8viI


 < Prev  1  2  3  4  Next>