320x200 OpenComputers video encoder
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rin.lua 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. --[[
  2. rin: nadeshicodec video player
  3. Copyright (c) 2016, 2017, 2018 asie
  4. Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. this software and associated documentation files (the "Software"), to deal in
  6. the Software without restriction, including without limitation the rights to
  7. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  8. of the Software, and to permit persons to whom the Software is furnished to do
  9. so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18. SOFTWARE.
  19. ]]
  20. local args = {...}
  21. local component = require("component")
  22. local computer = require("computer")
  23. local event = require("event")
  24. local gpu = component.gpu
  25. local unicode = require("unicode")
  26. local keyboard = require("keyboard")
  27. local text = require("text")
  28. local drive = component.drive
  29. local pal = {}
  30. local quad = {}
  31. local strs = {}
  32. quad[0] = " "
  33. for i=1,255 do
  34. local dat = (i & 0x01) << 7
  35. dat = dat | (i & 0x02) >> 1 << 6
  36. dat = dat | (i & 0x04) >> 2 << 5
  37. dat = dat | (i & 0x08) >> 3 << 2
  38. dat = dat | (i & 0x10) >> 4 << 4
  39. dat = dat | (i & 0x20) >> 5 << 1
  40. dat = dat | (i & 0x40) >> 6 << 3
  41. dat = dat | (i & 0x80) >> 7
  42. quad[i] = unicode.char(0x2800 | dat)
  43. end
  44. strs[1] = {}
  45. strs[1][0] = quad[0]
  46. strs[1][1] = quad[255]
  47. for i=2,160 do
  48. strs[i] = {}
  49. strs[i][0] = strs[i-1][0] .. strs[1][0]
  50. strs[i][1] = strs[i-1][1] .. strs[1][1]
  51. end
  52. for i=0,255 do
  53. if (i < 16) then
  54. pal[i] = (i * 15) << 16 | (i * 15) << 8 | (i * 15)
  55. gpu.setPaletteColor(i, pal[i])
  56. else
  57. local j = i - 16
  58. local b = math.floor((j % 5) * 255 / 4.0)
  59. local g = math.floor((math.floor(j / 5.0) % 8) * 255 / 7.0)
  60. local r = math.floor((math.floor(j / 40.0) % 6) * 255 / 5.0)
  61. pal[i] = r << 16 | g << 8 | b
  62. end
  63. end
  64. local maxBufSize = 1536+256
  65. local buf = {}
  66. local sec = 1
  67. local sectorsReadTick = 0
  68. local drawcallsTick = 0
  69. local bufi = 1
  70. local function addToBuf()
  71. table.insert(buf, drive.readSector(sec))
  72. sec = sec + 1
  73. sectorsReadTick = sectorsReadTick + 1
  74. end
  75. local function r8()
  76. if (#buf > 0) and (bufi > #(buf[1])) then
  77. table.remove(buf, 1)
  78. bufi = 1
  79. end
  80. if (#buf == 0) then
  81. addToBuf()
  82. if (#buf == 0) then
  83. return 0
  84. end
  85. end
  86. local v = string.byte(buf[1], bufi, bufi) & 255
  87. bufi = bufi + 1
  88. return v
  89. end
  90. local function r16()
  91. local x = r8()
  92. return x | (r8() << 8)
  93. end
  94. for i=1,maxBufSize do
  95. addToBuf()
  96. end
  97. local curr_bg = 0
  98. local curr_fg = 0
  99. local frame = 0
  100. r8()
  101. local frame_w = r8()
  102. local frame_h = r8()
  103. local frame_offset = computer.uptime()
  104. local r_player = component.record_player
  105. gpu.setResolution(frame_w, frame_h)
  106. local function set_bg(v)
  107. if curr_bg ~= v then
  108. drawcallsTick = drawcallsTick + 2
  109. gpu.setBackground(pal[v], false)
  110. curr_bg = v
  111. end
  112. end
  113. local function set_fg(v)
  114. if curr_fg ~= v then
  115. drawcallsTick = drawcallsTick + 2
  116. gpu.setForeground(pal[v], false)
  117. curr_fg = v
  118. end
  119. end
  120. local function cmd_fill(x,y,w,h,c)
  121. local chr = 0
  122. if curr_fg == c then
  123. chr = 1
  124. elseif curr_bg == c then
  125. chr = 0
  126. else
  127. set_bg(c)
  128. end
  129. if w >= 2 and h >= 2 then
  130. drawcallsTick = drawcallsTick + 2
  131. gpu.fill(x+1,y+1,w,h,quad[chr*255])
  132. elseif w > 1 then
  133. drawcallsTick = drawcallsTick + 1
  134. gpu.set(x+1,y+1,strs[w][chr])
  135. else
  136. drawcallsTick = drawcallsTick + 1
  137. gpu.set(x+1,y+1,strs[h][chr],true)
  138. end
  139. end
  140. local function cmd_set(vertical,x,y,bg,fg,qs)
  141. local invert = 0
  142. if bg == curr_bg and fg == curr_fg then
  143. -- ok
  144. elseif bg == curr_fg and fg == curr_bg then
  145. invert = 255
  146. elseif bg == curr_bg then
  147. set_fg(fg)
  148. elseif fg == curr_bg then
  149. set_fg(bg)
  150. invert = 255
  151. elseif fg == curr_fg then
  152. set_bg(bg)
  153. elseif bg == curr_fg then
  154. set_bg(fg)
  155. invert = 255
  156. else
  157. set_bg(bg)
  158. set_fg(fg)
  159. end
  160. local qso = {}
  161. for i=1,#qs do
  162. qso[i] = quad[qs[i] ~ invert]
  163. end
  164. gpu.set(x+1,y+1,table.concat(qso),vertical)
  165. drawcallsTick = drawcallsTick + 1
  166. end
  167. while true do
  168. local cmd = r8(file)
  169. if cmd == 0x10 then
  170. local x = r8(file)
  171. local y = r8(file)
  172. local w = r8(file)
  173. local h = r8(file)
  174. local c = r8(file)
  175. cmd_fill(x,y,w,h,c)
  176. elseif cmd == 0x18 then
  177. local x = r8(file)
  178. local y = r8(file)
  179. local w = r8(file)
  180. local c = r8(file)
  181. cmd_fill(x,y,w,1,c)
  182. elseif cmd == 0x19 then
  183. local x = r8(file)
  184. local y = r8(file)
  185. local h = r8(file)
  186. local c = r8(file)
  187. cmd_fill(x,y,1,h,c)
  188. elseif cmd == 0x12 or cmd == 0x13 then
  189. local vertical = (cmd == 0x13)
  190. local x = r8(file)
  191. local y = r8(file)
  192. local w = r8(file)
  193. local bg = r8(file)
  194. local fg = r8(file)
  195. local qs = {}
  196. for i=1,w do
  197. qs[i] = r8(file)
  198. end
  199. cmd_set(vertical,x,y,bg,fg,qs)
  200. elseif cmd == 0x22 or cmd == 0x23 then
  201. local vertical = (cmd == 0x23)
  202. local x = r8(file)
  203. local y = r8(file)
  204. local bg = r8(file)
  205. local fg = r8(file)
  206. local qs = {}
  207. local adding = true
  208. while adding do
  209. local cmd = r8(file)
  210. if cmd == 0x00 then adding = false
  211. elseif cmd >= 0xA1 and cmd <= 0xFF then
  212. local v = r8(file)
  213. for i=1,(cmd-0xA0) do table.insert(qs,v) end
  214. elseif cmd >= 0x01 and cmd <= 0xA0 then
  215. for i=1,cmd do
  216. table.insert(qs,r8(file))
  217. end
  218. end
  219. end
  220. cmd_set(vertical,x,y,bg,fg,qs)
  221. elseif cmd == 0x01 then
  222. if frame == 1 then
  223. if r_player ~= nil then
  224. r_player.stop()
  225. os.sleep(0.1)
  226. r_player.play()
  227. os.sleep(0.25)
  228. end
  229. frame_offset = computer.uptime() + 0.05
  230. else
  231. frame_offset = frame_offset + 0.05
  232. end
  233. frame = frame + 1
  234. --print(drawcallsTick)
  235. while computer.uptime() <= frame_offset do
  236. if (sectorsReadTick == 0) and (#buf < maxBufSize) then
  237. local bufAddCost = 10
  238. while drawcallsTick < (255-bufAddCost) do
  239. addToBuf()
  240. drawcallsTick = drawcallsTick + bufAddCost
  241. end
  242. end
  243. os.sleep(0.05)
  244. sectorsReadTick = 0
  245. drawcallsTick = 0
  246. end
  247. else
  248. error("unknown opcode " .. cmd)
  249. end
  250. end