txt.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "strings"
  7. "unicode/utf16"
  8. )
  9. const PlaceHolderString = "==== THIS IS PLACEHOLDER TEXT PLEASE DO NOT TRANSLATE ===="
  10. // TXT represents the text data of the txt1 section
  11. type TXT struct {
  12. Flag uint8
  13. Origin uint8
  14. Alpha uint8
  15. _ uint8
  16. PaneName [16]byte
  17. UserData [8]byte
  18. XTranslation float32
  19. YTranslation float32
  20. ZTranslation float32
  21. XRotate float32
  22. YRotate float32
  23. ZRotate float32
  24. XScale float32
  25. YScale float32
  26. Width float32
  27. Height float32
  28. StringLength uint16
  29. MaxStringLength uint16
  30. MatIndex uint16
  31. FontIndex uint16
  32. Alignment uint8
  33. _ uint8
  34. _ uint16
  35. TextOffset uint32
  36. TopColor [4]uint8
  37. BottomColor [4]uint8
  38. FontSizeX float32
  39. FontSizeY float32
  40. CharacterSize float32
  41. LineSize float32
  42. }
  43. func (r *Root) ParseTXT(data []byte, sectionSize uint32) {
  44. var text TXT
  45. err := binary.Read(bytes.NewReader(data), binary.BigEndian, &text)
  46. if err != nil {
  47. panic(err)
  48. }
  49. // Strip the null bytes from the strings
  50. name := strings.Replace(string(text.PaneName[:]), "\x00", "", -1)
  51. userData := strings.Replace(string(text.UserData[:]), "\x00", "", -1)
  52. utf16String := data[text.TextOffset-8 : sectionSize-8]
  53. // Convert the UTF-16 string to UTF-8
  54. var full []uint16
  55. for i := 0; i < len(utf16String); i += 2 {
  56. current := binary.BigEndian.Uint16([]byte{utf16String[i], utf16String[i+1]})
  57. if current == 0 {
  58. // Our string was terminated
  59. break
  60. }
  61. full = append(full, current)
  62. }
  63. // Strip null bytes
  64. decodedString := strings.Replace(string(utf16.Decode(full)), "\x00", "", -1)
  65. fmt.Println(len(decodedString))
  66. if decodedString == "あああああああああああああああああああ" {
  67. decodedString = PlaceHolderString
  68. }
  69. txtXML := XMLTXT{
  70. Name: name,
  71. UserData: userData,
  72. Visible: text.Flag & 0x1,
  73. Widescreen: (text.Flag & 0x2) >> 1,
  74. Flag: text.Flag,
  75. Origin: Coord2D{X: float32(text.Origin % 3), Y: float32(text.Origin / 3)},
  76. Alpha: text.Alpha,
  77. Padding: 0,
  78. Translate: Coord3D{X: text.XTranslation, Y: text.YTranslation, Z: text.ZTranslation},
  79. Rotate: Coord3D{X: text.XRotate, Y: text.YRotate, Z: text.ZRotate},
  80. Scale: Coord2D{X: text.XScale, Y: text.YScale},
  81. Width: text.Width,
  82. Height: text.Height,
  83. MaxStringLength: text.MaxStringLength,
  84. MatIndex: text.MatIndex,
  85. TextAlignment: text.Alignment,
  86. XSize: text.FontSizeX,
  87. YSize: text.FontSizeY,
  88. CharSize: text.CharacterSize,
  89. LineSize: text.LineSize,
  90. TopColor: Color8{
  91. R: text.TopColor[0],
  92. G: text.TopColor[1],
  93. B: text.TopColor[2],
  94. A: text.TopColor[3],
  95. },
  96. BottomColor: Color8{
  97. R: text.BottomColor[0],
  98. G: text.BottomColor[1],
  99. B: text.BottomColor[2],
  100. A: text.BottomColor[3],
  101. },
  102. Text: decodedString,
  103. }
  104. r.Panes = append(r.Panes, Children{TXT: &txtXML})
  105. }
  106. func (b *BRLYTWriter) WriteTXT(txt XMLTXT) {
  107. temp := bytes.NewBuffer(nil)
  108. header := SectionHeader{
  109. Type: SectionTypeTXT,
  110. Size: 124,
  111. }
  112. var name [16]byte
  113. copy(name[:], txt.Name)
  114. var userData [8]byte
  115. copy(userData[:], txt.UserData)
  116. text := strings.Replace(txt.Text, "\\n", "\n", -1)
  117. encodedText := utf16.Encode([]rune(text))
  118. textLength := len(encodedText)*2 + 2
  119. pane := TXT{
  120. Flag: txt.Flag,
  121. Origin: uint8(txt.Origin.X + (txt.Origin.Y * 3)),
  122. Alpha: txt.Alpha,
  123. PaneName: name,
  124. UserData: userData,
  125. XTranslation: txt.Translate.X,
  126. YTranslation: txt.Translate.Y,
  127. ZTranslation: txt.Translate.Z,
  128. XRotate: txt.Rotate.X,
  129. YRotate: txt.Rotate.Y,
  130. ZRotate: txt.Rotate.Z,
  131. XScale: txt.Scale.X,
  132. YScale: txt.Scale.Y,
  133. Width: txt.Width,
  134. Height: txt.Height,
  135. StringLength: uint16(textLength),
  136. MaxStringLength: txt.MaxStringLength,
  137. MatIndex: txt.MatIndex,
  138. FontIndex: 0,
  139. Alignment: txt.TextAlignment,
  140. TextOffset: 116,
  141. TopColor: [4]uint8{txt.TopColor.R, txt.TopColor.G, txt.TopColor.B, txt.TopColor.A},
  142. BottomColor: [4]uint8{txt.BottomColor.R, txt.BottomColor.G, txt.BottomColor.B, txt.BottomColor.A},
  143. FontSizeX: txt.XSize,
  144. FontSizeY: txt.YSize,
  145. CharacterSize: txt.CharSize,
  146. LineSize: txt.LineSize,
  147. }
  148. write(temp, header)
  149. write(temp, pane)
  150. write(temp, encodedText)
  151. pos := 0
  152. for (b.Len()+temp.Len())%4 != 0 {
  153. temp.WriteByte(0)
  154. pos += 1
  155. }
  156. // If there is no modulo padding, pad with an u32
  157. if pos == 0 {
  158. write(temp, uint32(0))
  159. }
  160. binary.BigEndian.PutUint32(temp.Bytes()[4:8], uint32(temp.Len()))
  161. write(b, temp.Bytes())
  162. }