qsp-decoder.coffee 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. {File, Directory} = require 'atom'
  2. fs = require 'fs'
  3. module.exports =
  4. class QspDecoder
  5. constructor: (@data, @file) ->
  6. @decodeFile()
  7. decodeFile: ->
  8. prepare = @prepare()
  9. if !prepare
  10. return
  11. version = @readLine(prepare)
  12. console.log @toString(version.line)
  13. password = @readLine(version.next)
  14. console.log @toString @decode password.line
  15. locations = @readLine password.next
  16. locationsNumber = (@toString @decode locations.line).valueOf()
  17. next = locations.next
  18. builder = new ProjectBuilder(@config)
  19. for i in [0...locationsNumber]
  20. location = @readLocation next
  21. next = location.next
  22. builder.createLocation location
  23. prepare: ->
  24. @config = {}
  25. @config.ucs2le = @data[1] == 0
  26. @config.crlf = @data[7 * if @config.ucs2le then 2 else 1] == 13
  27. @config.encodedPath = @file.getPath()
  28. check = @readLine(0, 9)
  29. if @toString(check.line) == 'QSPGAME'
  30. return check.next
  31. else
  32. return 0
  33. readLocation: (position) ->
  34. name = @readLine position
  35. description = @readLine name.next
  36. code = @readLine description.next
  37. actions = @readLine code.next
  38. actionsNumber = (@toString @decode actions.line).valueOf()
  39. next = actions.next
  40. actions = []
  41. for i in [0...actionsNumber]
  42. action = @readAction next
  43. next = action.next
  44. actions.push(action)
  45. name: @toString @decode name.line
  46. description: @toString @decode description.line
  47. code: @toString @decode code.line
  48. actions: actions
  49. next: next
  50. readAction: (position) ->
  51. picture = @readLine position
  52. name = @readLine picture.next
  53. code = @readLine name.next
  54. picture: @toString @decode picture.line
  55. name: @toString @decode name.line
  56. code: @toString @decode code.line
  57. next: code.next
  58. readLine: (start, max) ->
  59. counter = start
  60. line = []
  61. that = @
  62. check = ->
  63. if that.config.crlf
  64. return line[line.length - 1] == 10 and line[line.length - 2] == 13
  65. else
  66. return line[line.length - 1] == 10
  67. while !check() and counter < @data.length
  68. line.push(@readSymbol(counter))
  69. counter += if @config.ucs2le then 2 else 1
  70. if max and line.length > max
  71. break
  72. line: if line.length > 0 then line[0...if @config.crlf then -2 else -1] else []
  73. next: counter
  74. readSymbol: (position) ->
  75. code = @data[position]
  76. code += @data[position + 1] * 256 if @config.ucs2le
  77. return code
  78. decode: (line) ->
  79. for i in [0...line.length]
  80. line[i] += 5
  81. return line
  82. toString: (line) ->
  83. result = ""
  84. step = 65535
  85. for i in [0...line.length] by step
  86. result += String.fromCharCode.apply(@, line[i...i + step])
  87. return result
  88. class ProjectBuilder
  89. constructor: (@config) ->
  90. @directoryStack = []
  91. @root = new Directory(@config.encodedPath[[email protected]('.')])
  92. try
  93. fs.mkdirSync(@root.getPath(), 0o755)
  94. catch error
  95. createLocation: (location) ->
  96. fs.writeFileSync("#{@root.getPath()}/#{location.name}.qsrc", location.code, {mode: 0o644})
  97. createDirectoryRecursive: (directory, callback) ->
  98. if directory.getParent().exists()
  99. that = @
  100. directory.create(0o755).then(() ->
  101. if that.directoryStack.length > 0
  102. that.createDirectoryRecursive(that.directoryStack.pop(), callback)
  103. else
  104. callback()
  105. )
  106. else
  107. @directoryStack.push(directory)
  108. createDirectoryRecursive(directory.getParent(), callback)
  109. write: (path, data) ->