aboutsummaryrefslogtreecommitdiff
path: root/advtrains_train_track/models/advtrains_track_cr.b3d
blob: b0f5e4b247497b66dd8eefbb2942b39ae40cd108 (plain)
ofshex dumpascii
0000 42 42 33 44 4f 1f 00 00 01 00 00 00 54 45 58 53 25 00 00 00 72 61 69 6c 2e 70 6e 67 00 01 00 00 BB3DO.......TEXS%...rail.png....
0020 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3f 00 00 80 3f 00 00 00 00 42 52 55 53 2e 00 00 ................?...?....BRUS...
0040 00 01 00 00 00 42 72 75 73 68 2e 30 30 31 00 00 00 80 3f 00 00 80 3f 00 00 80 3f 00 00 80 3f 00 .....Brush.001....?...?...?...?.
0060 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 4e 4f 44 45 e0 1e 00 00 72 61 69 6c 5f 34 35 5f 39 ...............NODE....rail_45_9
0080 30 69 00 00 00 e0 c0 00 00 80 be 00 00 80 40 ce cc cc 3e cd cc cc 3e 02 00 00 3f 5e 1c 7c 3f 00 0i............@...>...>...?^.|?.
00a0 00 00 00 d4 d0 31 3e 00 00 00 00 4d 45 53 48 a4 1e 00 00 ff ff ff ff 56 52 54 53 0c 1a 00 00 01 .....1>....MESH........VRTS.....
00c0 00 00 00 01 00 00 00 02 00 00 00 69 90 a7 3f 00 00 c0 be e3 1e 03 40 cd a3 66 3f fc c1 fd bd aa ...........i..?.......@..f?.....
00e0 e9 d4 be 0d 41 34 3f f6 b3 30 3f e2 29 da 3f 00 00 c0 be 20 bd c7 bf 80 df 3f 3f 20 11 10 be 4b ....A4?..0?.).?..........??....K
0100 97 25 bf bc fb 2e 3e f4 b3 30 3f c3 fe 91 3f 00 00 c0 be 9d b9 b2 bf bd 79 5e bf 85 b1 42 be d4 .%....>..0?...?.........y^...B..
0120 d1 e9 be c0 fb 2e 3e 1c c0 07 3f 99 eb 43 3f 00 00 c0 be 87 46 ec 3f 89 79 44 bf cb 51 65 be 34 ......>...?..C?.....F.?.yD..Qe.4
0140 c3 19 bf 0f 41 34 3f 20 c0 07 3f 8b ec 7d 3f cc cc 8c be 34 18 f7 3f 5b 95 2d bf fd b9 fe 3e 15 ....A4?...?..}?....4..?[.-....>.
0160 7f 0a bf 0e 41 34 3f bc be ea 3e b7 10 b0 3f cc cc 8c be 13 7b bb bf 2b 5b 15 bf 97 71 4b 3e 93 ....A4?...>...?.....{..+[...qK>.
0180 97 49 bf c8 fb 2e 3e b0 be ea 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f .I....>...>...?.....{...q....S..
01a0 65 4f bf ce fb 2e 3e 26 9e c8 3e 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b eO....>&..>..}?....4..?B.!..Iu.{
01c0 47 3d 3f 0f 41 34 3f 36 9e c8 3e e8 17 bc 3f cc cc 8c be a9 fb be bf 03 89 81 3e 9f b1 cf 3e c2 G=?.A4?6..>...?...........>...>.
01e0 d7 60 bf ca fb 2e 3e a0 21 c7 3d e2 29 da 3f 00 00 c0 be 20 bd c7 bf 80 df 3f 3f 20 11 10 be 4b .`....>.!.=.).?..........??....K
0200 97 25 bf de fb 2e 3e 00 6e d0 3c 69 90 a7 3f 00 00 c0 be e3 1e 03 40 cd a3 66 3f fc c1 fd bd aa .%....>.n.<i..?.......@..f?.....
0220 e9 d4 be 16 41 34 3f c0 6e d0 3c 13 90 8a 3f cc cc 8c be 0a 6c fb 3f a4 19 52 3f 04 2f 02 3f 0b ....A4?.n.<...?.....l.?..R?./.?.
0240 51 85 be 12 41 34 3f e0 21 c7 3d e2 29 da 3f 00 00 c0 be 20 bd c7 bf 80 df 3f 3f 20 11 10 be 4b Q...A4?.!.=.).?..........??....K
0260 97 25 bf f8 e6 19 3d 2c 9f 4a 3e e8 17 bc 3f cc cc 8c be a9 fb be bf 03 89 81 3e 9f b1 cf 3e c2 .%....=,.J>...?...........>...>.
0280 d7 60 bf c4 8d 83 3d 28 70 87 3e b7 10 b0 3f cc cc 8c be 13 7b bb bf 2b 5b 15 bf 97 71 4b 3e 93 .`....=(p.>...?.....{..+[...qK>.
02a0 97 49 bf b8 8d 83 3d c6 16 95 3e c3 fe 91 3f 00 00 c0 be 9d b9 b2 bf bd 79 5e bf 85 b1 42 be d4 .I....=...>...?.........y^...B..
02c0 d1 e9 be 10 e6 19 3d 4c 37 b7 3e c3 fe 91 3f 00 00 c0 be 9d b9 b2 bf bd 79 5e bf 85 b1 42 be d4 ......=L7.>...?.........y^...B..
02e0 d1 e9 be c0 fb 2e 3e 1c c0 07 3f b7 10 b0 3f cc cc 8c be 13 7b bb bf 2b 5b 15 bf 97 71 4b 3e 93 ......>...?...?.....{..+[...qK>.
0300 97 49 bf c8 fb 2e 3e b0 be ea 3e 8b ec 7d 3f cc cc 8c be 34 18 f7 3f 5b 95 2d bf fd b9 fe 3e 15 .I....>...>..}?....4..?[.-....>.
0320 7f 0a bf 0e 41 34 3f bc be ea 3e 99 eb 43 3f 00 00 c0 be 87 46 ec 3f 89 79 44 bf cb 51 65 be 34 ....A4?...>..C?.....F.?.yD..Qe.4
0340 c3 19 bf 0f 41 34 3f 20 c0 07 3f 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b ....A4?...?..}?....4..?B.!..Iu.{
0360 47 3d 3f 06 7e 3e 3f f4 16 95 3e 13 90 8a 3f c0 cc cc bc 0a 6c fb 3f 34 01 9a 3d 78 f5 bb be db G=?.~>?...>...?.....l.?4..=x....
0380 57 6d 3f 06 7e 3e 3f 56 70 87 3e 13 90 8a 3f cc cc 8c be 0a 6c fb 3f a4 19 52 3f 04 2f 02 3f 0b Wm?.~>?Vp.>...?.....l.?..R?./.?.
03a0 51 85 be 4a 8e 4f 3f 5c 70 87 3e 8b ec 7d 3f cc cc 8c be 34 18 f7 3f 5b 95 2d bf fd b9 fe 3e 15 Q..J.O?\p.>..}?....4..?[.-....>.
03c0 7f 0a bf 4a 8e 4f 3f f8 16 95 3e 13 90 8a 3f cc cc 8c be 0a 6c fb 3f a4 19 52 3f 04 2f 02 3f 0b ...J.O?...>...?.....l.?..R?./.?.
03e0 51 85 be 12 41 34 3f e0 21 c7 3d 13 90 8a 3f c0 cc cc bc 0a 6c fb 3f 34 01 9a 3d 78 f5 bb be db Q...A4?.!.=...?.....l.?4..=x....
0400 57 6d 3f 11 41 34 3f 00 d2 27 3e 6c 75 bb 3f c0 cc cc bc 59 cc be bf 39 91 1c 3e a6 f5 d2 be cc Wm?.A4?..'>lu.?....Y...9..>.....
0420 f1 65 bf c8 fb 2e 3e e4 d1 27 3e e8 17 bc 3f cc cc 8c be a9 fb be bf 03 89 81 3e 9f b1 cf 3e c2 .e....>..'>...?...........>...>.
0440 d7 60 bf ca fb 2e 3e a0 21 c7 3d b7 10 b0 3f cc cc 8c be 13 7b bb bf 2b 5b 15 bf 97 71 4b 3e 93 .`....>.!.=...?.....{..+[...qK>.
0460 97 49 bf b8 8d 83 3d c6 16 95 3e e8 17 bc 3f cc cc 8c be a9 fb be bf 03 89 81 3e 9f b1 cf 3e c2 .I....=...>...?...........>...>.
0480 d7 60 bf c4 8d 83 3d 28 70 87 3e 6c 75 bb 3f c0 cc cc bc 59 cc be bf 39 91 1c 3e a6 f5 d2 be cc .`....=(p.>lu.?....Y...9..>.....
04a0 f1 65 bf f8 07 06 3e 36 70 87 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f .e....>6p.>...?.....{...q....S..
04c0 65 4f bf f0 07 06 3e d0 16 95 3e 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b eO....>...>..}?....4..?B.!..Iu.{
04e0 47 3d 3f 0f 41 34 3f 36 9e c8 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f G=?.A4?6..>...?.....{...q....S..
0500 65 4f bf ce fb 2e 3e 26 9e c8 3e bc 07 a1 3f 00 00 00 00 57 1a b7 bf 58 2f 2c bf 0b 85 05 bf 0d eO....>&..>...?....W...X/,......
0520 5f 06 bf ce fb 2e 3e 60 37 b7 3e 12 ec 60 3f 00 00 c0 32 5e af f1 3f 7e 39 3f bf 08 eb 03 bf ae _.....>`7.>..`?...2^..?~9?......
0540 11 d7 3e 10 41 34 3f 74 37 b7 3e 6c 75 bb 3f c0 cc cc bc 59 cc be bf 39 91 1c 3e a6 f5 d2 be cc ..>.A4?t7.>lu.?....Y...9..>.....
0560 f1 65 bf c8 fb 2e 3e e4 d1 27 3e 13 90 8a 3f c0 cc cc bc 0a 6c fb 3f 34 01 9a 3d 78 f5 bb be db .e....>..'>...?.....l.?4..=x....
0580 57 6d 3f 11 41 34 3f 00 d2 27 3e 50 10 99 3f 00 00 c0 32 70 6a 00 40 e3 65 f1 3e 02 0d 01 bf 72 Wm?.A4?..'>P..?...2pj.@.e.>....r
05a0 3b 39 3f 11 41 34 3f 8c 9f 4a 3e e3 20 cb 3f 00 00 00 00 64 5c c3 bf 24 03 12 3f 02 e1 00 bf 4c ;9?.A4?..J>...?....d\..$..?....L
05c0 23 26 bf c8 fb 2e 3e 6c 9f 4a 3e 12 ec 60 3f 00 00 c0 32 5e af f1 3f 7e 39 3f bf 08 eb 03 bf ae #&....>l.J>..`?...2^..?~9?......
05e0 11 d7 3e 10 41 34 3f 74 37 b7 3e bc 07 a1 3f 00 00 00 00 57 1a b7 bf 58 2f 2c bf 0b 85 05 bf 0d ..>.A4?t7.>...?....W...X/,......
0600 5f 06 bf ce fb 2e 3e 60 37 b7 3e bc 07 a1 3f ff ff ff 3d 57 1a b7 bf 39 61 1c bf 34 e5 19 3f 08 _.....>`7.>...?...=W...9a..4..?.
0620 e3 03 bf be fb 2e 3e 18 27 a6 3e 1e ec 60 3f 02 00 00 3e 57 af f1 3f 60 05 30 bf 2f 59 17 3f b0 ......>.'.>..`?...>W..?`.0./Y.?.
0640 cd d7 3e 0e 41 34 3f 36 27 a6 3e e3 20 cb 3f 00 00 00 00 64 5c c3 bf 24 03 12 3f 02 e1 00 bf 4c ..>.A4?6'.>...?....d\..$..?....L
0660 23 26 bf c8 fb 2e 3e 6c 9f 4a 3e 50 10 99 3f 00 00 c0 32 70 6a 00 40 e3 65 f1 3e 02 0d 01 bf 72 #&....>l.J>P..?...2pj.@.e.>....r
0680 3b 39 3f 11 41 34 3f 8c 9f 4a 3e 4d 10 99 3f 02 00 00 3e 74 6a 00 40 bb 55 dd 3e 22 c1 10 3f 68 ;9?.A4?..J>M..?...>tj.@.U.>"..?h
06a0 cf 33 3f 13 41 34 3f 1c c0 6c 3e e5 20 cb 3f 00 00 00 3e 64 5c c3 bf 11 83 08 3f 1e 35 0f 3f 45 .3?.A4?..l>...?...>d\.....?.5.?E
06c0 71 22 bf da fb 2e 3e e8 bf 6c 3e bc 07 a1 3f ff ff ff 3d 57 1a b7 bf 39 61 1c bf 34 e5 19 3f 08 q"....>..l>...?...=W...9a..4..?.
06e0 e3 03 bf be fb 2e 3e 18 27 a6 3e e5 20 cb 3f 00 00 00 3e 64 5c c3 bf 11 83 08 3f 1e 35 0f 3f 45 ......>.'.>...?...>d\.....?.5.?E
0700 71 22 bf da fb 2e 3e e8 bf 6c 3e 4d 10 99 3f 02 00 00 3e 74 6a 00 40 bb 55 dd 3e 22 c1 10 3f 68 q"....>..l>M..?...>tj.@.U.>"..?h
0720 cf 33 3f 13 41 34 3f 1c c0 6c 3e 1e ec 60 3f 02 00 00 3e 57 af f1 3f 60 05 30 bf 2f 59 17 3f b0 .3?.A4?..l>..`?...>W..?`.0./Y.?.
0740 cd d7 3e 0e 41 34 3f 36 27 a6 3e 13 90 8a 3f c0 cc cc bc 0a 6c fb 3f 34 01 9a 3d 78 f5 bb be db ..>.A4?6'.>...?.....l.?4..=x....
0760 57 6d 3f 06 7e 3e 3f 56 70 87 3e 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b Wm?.~>?Vp.>..}?....4..?B.!..Iu.{
0780 47 3d 3f 06 7e 3e 3f f4 16 95 3e 50 10 99 3f 00 00 c0 32 70 6a 00 40 e3 65 f1 3e 02 0d 01 bf 72 G=?.~>?...>P..?...2pj.@.e.>....r
07a0 3b 39 3f 35 c9 3c 3f 20 c0 6c 3e 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b ;9?5.<?..l>..}?....4..?B.!..Iu.{
07c0 47 3d 3f 06 7e 3e 3f f4 16 95 3e 12 ec 60 3f 00 00 c0 32 5e af f1 3f 7e 39 3f bf 08 eb 03 bf ae G=?.~>?...>..`?...2^..?~9?......
07e0 11 d7 3e 31 c9 3c 3f 38 27 a6 3e 1e ec 60 3f 02 00 00 3e 57 af f1 3f 60 05 30 bf 2f 59 17 3f b0 ..>1.<?8'.>..`?...>W..?`.0./Y.?.
0800 cd d7 3e 0e 41 34 3f 36 27 a6 3e 1e ec 60 3f 02 00 00 3e 57 af f1 3f 60 05 30 bf 2f 59 17 3f b0 ..>.A4?6'.>..`?...>W..?`.0./Y.?.
0820 cd d7 3e 0e 41 34 3f 36 27 a6 3e 4d 10 99 3f 02 00 00 3e 74 6a 00 40 bb 55 dd 3e 22 c1 10 3f 68 ..>.A4?6'.>M..?...>tj.@.U.>"..?h
0840 cf 33 3f 13 41 34 3f 1c c0 6c 3e 50 10 99 3f 00 00 c0 32 70 6a 00 40 e3 65 f1 3e 02 0d 01 bf 72 .3?.A4?..l>P..?...2pj.@.e.>....r
0860 3b 39 3f 35 c9 3c 3f 20 c0 6c 3e 8b ec 7d 3f c0 cc cc bc 34 18 f7 3f 42 13 21 bf eb 49 75 be 7b ;9?5.<?..l>..}?....4..?B.!..Iu.{
0880 47 3d 3f 06 7e 3e 3f f4 16 95 3e 1e ec 60 3f 02 00 00 3e 57 af f1 3f 60 05 30 bf 2f 59 17 3f b0 G=?.~>?...>..`?...>W..?`.0./Y.?.
08a0 cd d7 3e 0e 41 34 3f 36 27 a6 3e 50 10 99 3f 00 00 c0 32 70 6a 00 40 e3 65 f1 3e 02 0d 01 bf 72 ..>.A4?6'.>P..?...2pj.@.e.>....r
08c0 3b 39 3f 35 c9 3c 3f 20 c0 6c 3e 6c 75 bb 3f c0 cc cc bc 59 cc be bf 39 91 1c 3e a6 f5 d2 be cc ;9?5.<?..l>lu.?....Y...9..>.....
08e0 f1 65 bf f8 07 06 3e 36 70 87 3e e3 20 cb 3f 00 00 00 00 64 5c c3 bf 24 03 12 3f 02 e1 00 bf 4c .e....>6p.>...?....d\..$..?....L
0900 23 26 bf 52 db 0c 3e e0 bf 6c 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f #&.R..>..l>...?.....{...q....S..
0920 65 4f bf f0 07 06 3e d0 16 95 3e e3 20 cb 3f 00 00 00 00 64 5c c3 bf 24 03 12 3f 02 e1 00 bf 4c eO....>...>...?....d\..$..?....L
0940 23 26 bf 52 db 0c 3e e0 bf 6c 3e e5 20 cb 3f 00 00 00 3e 64 5c c3 bf 11 83 08 3f 1e 35 0f 3f 45 #&.R..>..l>...?...>d\.....?.5.?E
0960 71 22 bf da fb 2e 3e e8 bf 6c 3e bc 07 a1 3f ff ff ff 3d 57 1a b7 bf 39 61 1c bf 34 e5 19 3f 08 q"....>..l>...?...=W...9a..4..?.
0980 e3 03 bf be fb 2e 3e 18 27 a6 3e bc 07 a1 3f ff ff ff 3d 57 1a b7 bf 39 61 1c bf 34 e5 19 3f 08 ......>.'.>...?...=W...9a..4..?.
09a0 e3 03 bf be fb 2e 3e 18 27 a6 3e bc 07 a1 3f 00 00 00 00 57 1a b7 bf 58 2f 2c bf 0b 85 05 bf 0d ......>.'.>...?....W...X/,......
09c0 5f 06 bf 34 db 0c 3e 18 27 a6 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f _..4..>.'.>...?.....{...q....S..
09e0 65 4f bf f0 07 06 3e d0 16 95 3e e3 20 cb 3f 00 00 00 00 64 5c c3 bf 24 03 12 3f 02 e1 00 bf 4c eO....>...>...?....d\..$..?....L
0a00 23 26 bf 52 db 0c 3e e0 bf 6c 3e bc 07 a1 3f ff ff ff 3d 57 1a b7 bf 39 61 1c bf 34 e5 19 3f 08 #&.R..>..l>...?...=W...9a..4..?.
0a20 e3 03 bf be fb 2e 3e 18 27 a6 3e b8 10 b0 3f c0 cc cc bc 12 7b bb bf 19 71 0c bf a7 81 53 be 9f ......>.'.>...?.....{...q....S..
0a40 65 4f bf f0 07 06 3e d0 16 95 3e 75 9b 10 c0 00 00 c0 be d6 ae 37 3f 4a cd 24 3f 57 a1 2b be 7e eO....>...>u.........7?J.$?W.+.~
0a60 21 3f 3f 18 41 34 3f 17 c0 07 3f 09 71 ff bf 00 00 c0 be 51 58 f7 be 87 bf 43 3f 03 a9 01 be 44 !??.A4?...?.q......QX....C?....D
0a80 c1 21 bf c8 fb 2e 3e 1b c0 07 3f 12 ce 23 c0 00 00 c0 be 3b 4a a3 be a6 05 53 bf 9d 99 4e be 0f .!....>...?..#.....;J....S...N..
0aa0 69 07 bf d0 fb 2e 3e f6 b3 30 3f d5 68 33 c0 00 00 c0 be 6b c0 03 3f e9 79 74 bf 71 59 38 be e3 i.....>..0?.h3.....k..?.yt.qY8..
0ac0 49 71 3e 1b 41 34 3f ee b3 30 3f 98 e8 24 c0 cc cc 8c be c5 63 19 3f 63 7f 31 bf 09 49 84 3e 58 Iq>.A4?..0?..$......c.?c.1..I.>X
0ae0 33 2c 3f 15 41 34 3f 50 21 c7 3d 18 c5 14 c0 cc cc 8c be 1e 50 c6 be 1b 6b 0d bf 62 01 31 3e a1 3,?.A4?P!.=.........P...k..b.1>.
0b00 bf 50 bf c0 fb 2e 3e 60 21 c7 3d 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa .P....>`!.=.........P......n.6..
0b20 41 55 bf c2 fb 2e 3e cc d1 27 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d AU....>..'>..$......c.?K.%..%..m
0b40 7b 36 3f 15 41 34 3f c0 d1 27 3e 75 9b 10 c0 00 00 c0 be d6 ae 37 3f 4a cd 24 3f 57 a1 2b be 7e {6?.A4?..'>u.........7?J.$?W.+.~
0b60 21 3f 3f 18 41 34 3f 17 c0 07 3f b1 1b 1f c0 cc cc 8c be 72 0b 22 3f 1c 41 0e 3e 43 85 a1 3e e1 !??.A4?...?........r."?.A.>C..>.
0b80 4d 70 3f 16 41 34 3f a2 be ea 3e 81 c1 0e c0 cc cc 8c be 86 52 d4 be 12 c5 88 3e c9 61 e4 3e b5 Mp?.A4?...>.........R.....>.a.>.
0ba0 ab 5a bf b8 fb 2e 3e a8 be ea 3e 09 71 ff bf 00 00 c0 be 51 58 f7 be 87 bf 43 3f 03 a9 01 be 44 .Z....>...>.q......QX....C?....D
0bc0 c1 21 bf c8 fb 2e 3e 1b c0 07 3f 09 71 ff bf 00 00 c0 be 51 58 f7 be 87 bf 43 3f 03 a9 01 be 44 .!....>...?.q......QX....C?....D
0be0 c1 21 bf 10 e6 19 3d 58 37 b7 3e 81 c1 0e c0 cc cc 8c be 86 52 d4 be 12 c5 88 3e c9 61 e4 3e b5 .!....=X7.>.........R.....>.a.>.
0c00 ab 5a bf 94 8d 83 3d cc 16 95 3e 18 c5 14 c0 cc cc 8c be 1e 50 c6 be 1b 6b 0d bf 62 01 31 3e a1 .Z....=...>.........P...k..b.1>.
0c20 bf 50 bf a0 8d 83 3d 2e 70 87 3e 12 ce 23 c0 00 00 c0 be 3b 4a a3 be a6 05 53 bf 9d 99 4e be 0f .P....=.p.>..#.....;J....S...N..
0c40 69 07 bf 60 e6 19 3d 40 9f 4a 3e 12 ce 23 c0 00 00 c0 be 3b 4a a3 be a6 05 53 bf 9d 99 4e be 0f i..`..=@.J>..#.....;J....S...N..
0c60 69 07 bf bc fb 2e 3e c0 6c d0 3c 18 c5 14 c0 cc cc 8c be 1e 50 c6 be 1b 6b 0d bf 62 01 31 3e a1 i.....>.l.<.........P...k..b.1>.
0c80 bf 50 bf c0 fb 2e 3e 60 21 c7 3d 98 e8 24 c0 cc cc 8c be c5 63 19 3f 63 7f 31 bf 09 49 84 3e 58 .P....>`!.=..$......c.?c.1..I.>X
0ca0 33 2c 3f 15 41 34 3f 50 21 c7 3d d5 68 33 c0 00 00 c0 be 6b c0 03 3f e9 79 74 bf 71 59 38 be e3 3,?.A4?P!.=.h3.....k..?.yt.qY8..
0cc0 49 71 3e 16 41 34 3f c0 6c d0 3c b1 1b 1f c0 cc cc 8c be 72 0b 22 3f 1c 41 0e 3e 43 85 a1 3e e1 Iq>.A4?.l.<........r."?.A.>C..>.
0ce0 4d 70 3f 50 8e 4f 3f c8 16 95 3e 75 9b 10 c0 00 00 c0 be d6 ae 37 3f 4a cd 24 3f 57 a1 2b be 7e Mp?P.O?...>u.........7?J.$?W.+.~
0d00 21 3f 3f 9e 61 56 3f 54 37 b7 3e d5 68 33 c0 00 00 c0 be 6b c0 03 3f e9 79 74 bf 71 59 38 be e3 !??.aV?T7.>.h3.....k..?.yt.qY8..
0d20 49 71 3e 9e 61 56 3f 40 9f 4a 3e 98 e8 24 c0 cc cc 8c be c5 63 19 3f 63 7f 31 bf 09 49 84 3e 58 Iq>.aV?@.J>..$......c.?c.1..I.>X
0d40 33 2c 3f 50 8e 4f 3f 28 70 87 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d 3,?P.O?(p.>..$......c.?K.%..%..m
0d60 7b 36 3f 0b 7e 3e 3f 26 70 87 3e b1 1b 1f c0 c0 cc cc bc 72 0b 22 3f f5 81 7a 3d 53 95 a9 be e2 {6?.~>?&p.>........r."?..z=S....
0d80 09 71 3f 0b 7e 3e 3f c6 16 95 3e b1 1b 1f c0 cc cc 8c be 72 0b 22 3f 1c 41 0e 3e 43 85 a1 3e e1 .q?.~>?...>........r."?.A.>C..>.
0da0 4d 70 3f 50 8e 4f 3f c8 16 95 3e 98 e8 24 c0 cc cc 8c be c5 63 19 3f 63 7f 31 bf 09 49 84 3e 58 Mp?P.O?...>..$......c.?c.1..I.>X
0dc0 33 2c 3f 50 8e 4f 3f 28 70 87 3e b1 1b 1f c0 cc cc 8c be 72 0b 22 3f 1c 41 0e 3e 43 85 a1 3e e1 3,?P.O?(p.>........r."?.A.>C..>.
0de0 4d 70 3f 16 41 34 3f a2 be ea 3e b1 1b 1f c0 c0 cc cc bc 72 0b 22 3f f5 81 7a 3d 53 95 a9 be e2 Mp?.A4?...>........r."?..z=S....
0e00 09 71 3f 15 41 34 3f 18 9e c8 3e 81 c1 0e c0 c0 cc cc bc 86 52 d4 be 46 c9 22 3e d8 c1 eb be bf .q?.A4?...>.........R..F.">.....
0e20 8f 5f bf b8 fb 2e 3e 1c 9e c8 3e 81 c1 0e c0 cc cc 8c be 86 52 d4 be 12 c5 88 3e c9 61 e4 3e b5 ._....>...>.........R.....>.a.>.
0e40 ab 5a bf b8 fb 2e 3e a8 be ea 3e 18 c5 14 c0 cc cc 8c be 1e 50 c6 be 1b 6b 0d bf 62 01 31 3e a1 .Z....>...>.........P...k..b.1>.
0e60 bf 50 bf a0 8d 83 3d 2e 70 87 3e 81 c1 0e c0 cc cc 8c be 86 52 d4 be 12 c5 88 3e c9 61 e4 3e b5 .P....=.p.>.........R.....>.a.>.
0e80 ab 5a bf 94 8d 83 3d cc 16 95 3e 81 c1 0e c0 c0 cc cc bc 86 52 d4 be 46 c9 22 3e d8 c1 eb be bf .Z....=...>.........R..F.">.....
0ea0 8f 5f bf de 07 06 3e d0 16 95 3e 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa ._....>...>.........P......n.6..
0ec0 41 55 bf e4 07 06 3e 32 70 87 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d AU....>2p.>..$......c.?K.%..%..m
0ee0 7b 36 3f 15 41 34 3f c0 d1 27 3e 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa {6?.A4?..'>.........P......n.6..
0f00 41 55 bf c2 fb 2e 3e cc d1 27 3e 96 49 1c c0 00 00 c0 32 31 cd b4 be 42 e7 20 bf 0e fb 06 bf 25 AU....>..'>.I.....21...B.......%
0f20 5d 12 bf c0 fb 2e 3e 58 9f 4a 3e b7 28 2c c0 00 00 c0 32 19 92 0e 3f 8f b7 47 bf 05 4b 02 bf 74 ].....>X.J>.(,....2...?..G..K..t
0f40 39 ba 3e 15 41 34 3f 44 9f 4a 3e 81 c1 0e c0 c0 cc cc bc 86 52 d4 be 46 c9 22 3e d8 c1 eb be bf 9.>.A4?D.J>.........R..F.">.....
0f60 8f 5f bf b8 fb 2e 3e 1c 9e c8 3e b1 1b 1f c0 c0 cc cc bc 72 0b 22 3f f5 81 7a 3d 53 95 a9 be e2 ._....>...>........r."?..z=S....
0f80 09 71 3f 15 41 34 3f 18 9e c8 3e 93 db 17 c0 00 00 c0 32 1e dd 2c 3f bc 1d de 3e 02 0b 01 bf 7e .q?.A4?...>.......2..,?...>....~
0fa0 2b 3f 3f 15 41 34 3f 4e 37 b7 3e 03 3d 07 c0 00 00 c0 32 73 d5 e5 be 35 7b 1a 3f 01 51 00 bf 3e +??.A4?N7.>.=.....2s...5{.?.Q..>
0fc0 c3 1e bf b6 fb 2e 3e 5a 37 b7 3e b7 28 2c c0 00 00 c0 32 19 92 0e 3f 8f b7 47 bf 05 4b 02 bf 74 ......>Z7.>.(,....2...?..G..K..t
0fe0 39 ba 3e 15 41 34 3f 44 9f 4a 3e 96 49 1c c0 00 00 c0 32 31 cd b4 be 42 e7 20 bf 0e fb 06 bf 25 9.>.A4?D.J>.I.....21...B.......%
1000 5d 12 bf c0 fb 2e 3e 58 9f 4a 3e 96 49 1c c0 02 00 00 3e 31 cd b4 be 21 69 10 bf 39 a3 1c 3f 1c ].....>X.J>.I.....>1...!i..9..?.
1020 ef 0d bf c0 fb 2e 3e e4 bf 6c 3e b7 28 2c c0 02 00 00 3e 19 92 0e 3f 72 2f 39 bf 2a 0f 15 3f 7c ......>..l>.(,....>...?r/9.*..?|
1040 ed bd 3e 16 41 34 3f c4 bf 6c 3e 03 3d 07 c0 00 00 c0 32 73 d5 e5 be 35 7b 1a 3f 01 51 00 bf 3e ..>.A4?..l>.=.....2s...5{.?.Q..>
1060 c3 1e bf b6 fb 2e 3e 5a 37 b7 3e 93 db 17 c0 00 00 c0 32 1e dd 2c 3f bc 1d de 3e 02 0b 01 bf 7e ......>Z7.>.......2..,?...>....~
1080 2b 3f 3f 15 41 34 3f 4e 37 b7 3e 93 db 17 c0 02 00 00 3e 1e dd 2c 3f 8e 15 c7 3e 24 21 12 3f 72 +??.A4?N7.>.......>..,?...>$!.?r
10a0 1f 39 3f 15 41 34 3f 08 27 a6 3e 03 3d 07 c0 02 00 00 3e 73 d5 e5 be 25 43 12 3f 1c 1d 0e 3f 35 .9?.A4?.'.>.=.....>s...%C.?...?5
10c0 bd 1a bf b6 fb 2e 3e 18 27 a6 3e 96 49 1c c0 02 00 00 3e 31 cd b4 be 21 69 10 bf 39 a3 1c 3f 1c ......>.'.>.I.....>1...!i..9..?.
10e0 ef 0d bf c0 fb 2e 3e e4 bf 6c 3e 03 3d 07 c0 02 00 00 3e 73 d5 e5 be 25 43 12 3f 1c 1d 0e 3f 35 ......>..l>.=.....>s...%C.?...?5
1100 bd 1a bf b6 fb 2e 3e 18 27 a6 3e 93 db 17 c0 02 00 00 3e 1e dd 2c 3f 8e 15 c7 3e 24 21 12 3f 72 ......>.'.>.......>..,?...>$!.?r
1120 1f 39 3f 15 41 34 3f 08 27 a6 3e b7 28 2c c0 02 00 00 3e 19 92 0e 3f 72 2f 39 bf 2a 0f 15 3f 7c .9?.A4?.'.>.(,....>...?r/9.*..?|
1140 ed bd 3e 16 41 34 3f c4 bf 6c 3e b1 1b 1f c0 c0 cc cc bc 72 0b 22 3f f5 81 7a 3d 53 95 a9 be e2 ..>.A4?..l>........r."?..z=S....
1160 09 71 3f 0b 7e 3e 3f c6 16 95 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d .q?.~>?...>..$......c.?K.%..%..m
1180 7b 36 3f 0b 7e 3e 3f 26 70 87 3e 93 db 17 c0 00 00 c0 32 1e dd 2c 3f bc 1d de 3e 02 0b 01 bf 7e {6?.~>?&p.>.......2..,?...>....~
11a0 2b 3f 3f 36 c9 3c 3f 08 27 a6 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d +??6.<?.'.>..$......c.?K.%..%..m
11c0 7b 36 3f 0b 7e 3e 3f 26 70 87 3e b7 28 2c c0 00 00 c0 32 19 92 0e 3f 8f b7 47 bf 05 4b 02 bf 74 {6?.~>?&p.>.(,....2...?..G..K..t
11e0 39 ba 3e 38 c9 3c 3f c4 bf 6c 3e b7 28 2c c0 02 00 00 3e 19 92 0e 3f 72 2f 39 bf 2a 0f 15 3f 7c 9.>8.<?..l>.(,....>...?r/9.*..?|
1200 ed bd 3e 16 41 34 3f c4 bf 6c 3e b7 28 2c c0 02 00 00 3e 19 92 0e 3f 72 2f 39 bf 2a 0f 15 3f 7c ..>.A4?..l>.(,....>...?r/9.*..?|
1220 ed bd 3e 16 41 34 3f c4 bf 6c 3e 93 db 17 c0 02 00 00 3e 1e dd 2c 3f 8e 15 c7 3e 24 21 12 3f 72 ..>.A4?..l>.......>..,?...>$!.?r
1240 1f 39 3f 15 41 34 3f 08 27 a6 3e 93 db 17 c0 00 00 c0 32 1e dd 2c 3f bc 1d de 3e 02 0b 01 bf 7e .9?.A4?.'.>.......2..,?...>....~
1260 2b 3f 3f 36 c9 3c 3f 08 27 a6 3e 98 e8 24 c0 c0 cc cc bc c5 63 19 3f 4b 83 25 bf 16 25 8b be 6d +??6.<?.'.>..$......c.?K.%..%..m
1280 7b 36 3f 0b 7e 3e 3f 26 70 87 3e b7 28 2c c0 02 00 00 3e 19 92 0e 3f 72 2f 39 bf 2a 0f 15 3f 7c {6?.~>?&p.>.(,....>...?r/9.*..?|
12a0 ed bd 3e 16 41 34 3f c4 bf 6c 3e 93 db 17 c0 00 00 c0 32 1e dd 2c 3f bc 1d de 3e 02 0b 01 bf 7e ..>.A4?..l>.......2..,?...>....~
12c0 2b 3f 3f 36 c9 3c 3f 08 27 a6 3e 81 c1 0e c0 c0 cc cc bc 86 52 d4 be 46 c9 22 3e d8 c1 eb be bf +??6.<?.'.>.........R..F.">.....
12e0 8f 5f bf de 07 06 3e d0 16 95 3e 03 3d 07 c0 00 00 c0 32 73 d5 e5 be 35 7b 1a 3f 01 51 00 bf 3e ._....>...>.=.....2s...5{.?.Q..>
1300 c3 1e bf 2a db 0c 3e 18 27 a6 3e 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa ...*..>.'.>.........P......n.6..
1320 41 55 bf e4 07 06 3e 32 70 87 3e 03 3d 07 c0 00 00 c0 32 73 d5 e5 be 35 7b 1a 3f 01 51 00 bf 3e AU....>2p.>.=.....2s...5{.?.Q..>
1340 c3 1e bf 2a db 0c 3e 18 27 a6 3e 03 3d 07 c0 02 00 00 3e 73 d5 e5 be 25 43 12 3f 1c 1d 0e 3f 35 ...*..>.'.>.=.....>s...%C.?...?5
1360 bd 1a bf b6 fb 2e 3e 18 27 a6 3e 96 49 1c c0 02 00 00 3e 31 cd b4 be 21 69 10 bf 39 a3 1c 3f 1c ......>.'.>.I.....>1...!i..9..?.
1380 ef 0d bf c0 fb 2e 3e e4 bf 6c 3e 96 49 1c c0 02 00 00 3e 31 cd b4 be 21 69 10 bf 39 a3 1c 3f 1c ......>..l>.I.....>1...!i..9..?.
13a0 ef 0d bf c0 fb 2e 3e e4 bf 6c 3e 96 49 1c c0 00 00 c0 32 31 cd b4 be 42 e7 20 bf 0e fb 06 bf 25 ......>..l>.I.....21...B.......%
13c0 5d 12 bf 38 db 0c 3e e0 bf 6c 3e 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa ]..8..>..l>.........P......n.6..
13e0 41 55 bf e4 07 06 3e 32 70 87 3e 03 3d 07 c0 00 00 c0 32 73 d5 e5 be 35 7b 1a 3f 01 51 00 bf 3e AU....>2p.>.=.....2s...5{.?.Q..>
1400 c3 1e bf 2a db 0c 3e 18 27 a6 3e 96 49 1c c0 02 00 00 3e 31 cd b4 be 21 69 10 bf 39 a3 1c 3f 1c ...*..>.'.>.I.....>1...!i..9..?.
1420 ef 0d bf c0 fb 2e 3e e4 bf 6c 3e 18 c5 14 c0 c0 cc cc bc 1e 50 c6 be 0c 07 06 bf 6e d9 36 be aa ......>..l>.........P......n.6..
1440 41 55 bf e4 07 06 3e 32 70 87 3e 69 90 a7 3f 00 00 c0 be e3 1e 03 40 cd a3 66 3f fc c1 fd bd aa AU....>2p.>i..?.......@..f?.....
1460 e9 d4 be f8 e6 19 3d 2c 9f 4a 3e 13 90 8a 3f cc cc 8c be 0a 6c fb 3f a4 19 52 3f 04 2f 02 3f 0b ......=,.J>...?.....l.?..R?./.?.
1480 51 85 be c4 8d 83 3d 28 70 87 3e 8b ec 7d 3f cc cc 8c be 34 18 f7 3f 5b 95 2d bf fd b9 fe 3e 15 Q.....=(p.>..}?....4..?[.-....>.
14a0 7f 0a bf b8 8d 83 3d c6 16 95 3e 99 eb 43 3f 00 00 c0 be 87 46 ec 3f 89 79 44 bf cb 51 65 be 34 ......=...>..C?.....F.?.yD..Qe.4
14c0 c3 19 bf 10 e6 19 3d 4c 37 b7 3e ec 6a 53 c0 00 00 20 bf c8 75 47 3d 21 93 10 bf 27 63 13 bf 2f ......=L7.>.jS......uG=!...'c../
14e0 5b 17 3f c9 b7 1d 3d f8 64 59 3f 46 20 25 40 00 00 20 bf 4c d8 34 be 23 bd 11 3f 2a 1f 15 bf 29 [.?...=.dY?F.%@....L.4.#..?*...)
1500 83 14 3f 7e 24 76 3f fa 64 59 3f 0d 07 27 40 00 00 20 bf 2c 31 32 bf 27 45 13 3f 24 19 12 bf 2c ..?~$v?.dY?..'@....,12.'E.?$...,
1520 01 16 bf 7e 24 76 3f d9 7d 46 3f b8 8f 53 c0 00 00 20 bf 14 96 7e be 33 51 19 bf 29 bb 14 bf 1a ...~$v?.}F?..S.......~.3Q..)....
1540 15 0d bf 8e b7 1d 3d d6 7d 46 3f e8 6a 53 c0 00 00 c0 be 48 75 47 3d 21 93 10 bf 27 63 13 3f 2f ......=.}F?.jS.....HuG=!...'c.?/
1560 5b 17 3f 05 b8 1d 3d 59 3d 63 3f b8 8f 53 c0 00 00 c0 be 34 96 7e be 33 51 19 bf 29 bb 14 3f 1a [.?...=Y=c?..S.....4.~.3Q..)..?.
1580 15 0d bf c9 b7 1d 3d 7a 24 76 3f 0d 07 27 40 00 00 c0 be 28 31 32 bf 27 45 13 3f 24 17 12 3f 2c ......=z$v?..'@....(12.'E.?$..?,
15a0 01 16 bf 7b 24 76 3f 84 24 76 3f 4e 20 25 40 00 00 c0 be 7c d8 34 be 23 bd 11 3f 2a 1f 15 3f 29 ...{$v?.$v?N.%@....|.4.#..?*..?)
15c0 83 14 3f 83 24 76 3f 62 3d 63 3f ec 6a 53 c0 00 00 20 bf c8 75 47 3d 21 93 10 bf 27 63 13 bf 2f ..?.$v?b=c?.jS......uG=!...'c../
15e0 5b 17 3f c9 b7 1d 3d f8 64 59 3f e8 6a 53 c0 00 00 c0 be 48 75 47 3d 21 93 10 bf 27 63 13 3f 2f [.?...=.dY?.jS.....HuG=!...'c.?/
1600 5b 17 3f 05 b8 1d 3d 59 3d 63 3f 4e 20 25 40 00 00 c0 be 7c d8 34 be 23 bd 11 3f 2a 1f 15 3f 29 [.?...=Y=c?N.%@....|.4.#..?*..?)
1620 83 14 3f 83 24 76 3f 62 3d 63 3f 46 20 25 40 00 00 20 bf 4c d8 34 be 23 bd 11 3f 2a 1f 15 bf 29 ..?.$v?b=c?F.%@....L.4.#..?*...)
1640 83 14 3f 7e 24 76 3f fa 64 59 3f 46 20 25 40 00 00 20 bf 4c d8 34 be 23 bd 11 3f 2a 1f 15 bf 29 ..?~$v?.dY?F.%@....L.4.#..?*...)
1660 83 14 3f e4 fc 7f 3f 66 3d 63 3f 4e 20 25 40 00 00 c0 be 7c d8 34 be 23 bd 11 3f 2a 1f 15 3f 29 ..?...?f=c?N.%@....|.4.#..?*..?)
1680 83 14 3f 83 24 76 3f 62 3d 63 3f 0d 07 27 40 00 00 c0 be 28 31 32 bf 27 45 13 3f 24 17 12 3f 2c ..?.$v?b=c?..'@....(12.'E.?$..?,
16a0 01 16 bf 7b 24 76 3f 84 24 76 3f 0d 07 27 40 00 00 20 bf 2c 31 32 bf 27 45 13 3f 24 19 12 bf 2c ...{$v?.$v?..'@....,12.'E.?$...,
16c0 01 16 bf dd fc 7f 3f 88 24 76 3f 0d 07 27 40 00 00 20 bf 2c 31 32 bf 27 45 13 3f 24 19 12 bf 2c ......?.$v?..'@....,12.'E.?$...,
16e0 01 16 bf 7b 24 76 3f e5 fc 7f 3f 0d 07 27 40 00 00 c0 be 28 31 32 bf 27 45 13 3f 24 17 12 3f 2c ...{$v?...?..'@....(12.'E.?$..?,
1700 01 16 bf 7b 24 76 3f 84 24 76 3f b8 8f 53 c0 00 00 c0 be 34 96 7e be 33 51 19 bf 29 bb 14 3f 1a ...{$v?.$v?..S.....4.~.3Q..)..?.
1720 15 0d bf c9 b7 1d 3d 7a 24 76 3f b8 8f 53 c0 00 00 20 bf 14 96 7e be 33 51 19 bf 29 bb 14 bf 1a ......=z$v?..S.......~.3Q..)....
1740 15 0d bf 8e b7 1d 3d e3 fc 7f 3f e8 6a 53 c0 00 00 c0 be 48 75 47 3d 21 93 10 bf 27 63 13 3f 2f ......=...?.jS.....HuG=!...'c.?/
1760 5b 17 3f 05 b8 1d 3d 59 3d 63 3f ec 6a 53 c0 00 00 20 bf c8 75 47 3d 21 93 10 bf 27 63 13 bf 2f [.?...=Y=c?.jS......uG=!...'c../
1780 5b 17 3f 0c b1 47 38 56 3d 63 3f b8 8f 53 c0 00 00 20 bf 14 96 7e be 33 51 19 bf 29 bb 14 bf 1a [.?..G8V=c?..S.......~.3Q..)....
17a0 15 0d bf c7 c3 46 38 77 24 76 3f b8 8f 53 c0 00 00 c0 be 34 96 7e be 33 51 19 bf 29 bb 14 3f 1a .....F8w$v?..S.....4.~.3Q..)..?.
17c0 15 0d bf c9 b7 1d 3d 7a 24 76 3f 88 3e 5a c0 00 00 20 bf cb 4a cc 3e 61 ab 30 bf 29 9b 14 bf ba ......=z$v?.>Z......J.>a.0.)....
17e0 3d dd 3e c9 b7 1d 3d f8 64 59 3f 99 33 0b 40 00 00 20 bf 9a ad ed 3f 66 ed b2 3e 2c 2f 16 bf 76 =.>...=.dY?.3.@.......?f..>,/..v
1800 01 3b 3f 7e 24 76 3f fa 64 59 3f 5b 23 1c 40 00 00 20 bf 96 6e a2 3f 76 fb 3a 3f 22 d5 10 bf 88 .;?~$v?.dY?[#.@.....n.?v.:?"....
1820 e5 c3 be 7e 24 76 3f d9 7d 46 3f df a6 57 c0 00 00 20 bf 89 5b 48 3e d5 69 ea be 28 fd 13 bf 5a ...~$v?.}F?..W......[H>.i..(...Z
1840 e7 2c bf 8e b7 1d 3d d6 7d 46 3f 84 3e 5a c0 00 00 c0 be bb 4a cc 3e 61 ab 30 bf 29 9b 14 3f ba .,....=.}F?.>Z......J.>a.0.)..?.
1860 3d dd 3e 05 b8 1d 3d 59 3d 63 3f df a6 57 c0 00 00 c0 be 69 5b 48 3e d5 69 ea be 28 fd 13 3f 5a =.>...=Y=c?..W.....i[H>.i..(..?Z
1880 e7 2c bf c9 b7 1d 3d 7a 24 76 3f 5b 23 1c 40 00 00 c0 be 98 6e a2 3f 76 fb 3a 3f 22 d5 10 3f 88 .,....=z$v?[#.@.....n.?v.:?"..?.
18a0 e5 c3 be 7b 24 76 3f 84 24 76 3f a1 33 0b 40 00 00 c0 be 94 ad ed 3f 66 f1 b2 3e 2c 2f 16 3f 76 ...{$v?.$v?.3.@.......?f..>,/.?v
18c0 01 3b 3f 83 24 76 3f 62 3d 63 3f 88 3e 5a c0 00 00 20 bf cb 4a cc 3e 61 ab 30 bf 29 9b 14 bf ba .;?.$v?b=c?.>Z......J.>a.0.)....
18e0 3d dd 3e c9 b7 1d 3d f8 64 59 3f 84 3e 5a c0 00 00 c0 be bb 4a cc 3e 61 ab 30 bf 29 9b 14 3f ba =.>...=.dY?.>Z......J.>a.0.)..?.
1900 3d dd 3e 05 b8 1d 3d 59 3d 63 3f a1 33 0b 40 00 00 c0 be 94 ad ed 3f 66 f1 b2 3e 2c 2f 16 3f 76 =.>...=Y=c?.3.@.......?f..>,/.?v
1920 01 3b 3f 83 24 76 3f 62 3d 63 3f 99 33 0b 40 00 00 20 bf 9a ad ed 3f 66 ed b2 3e 2c 2f 16 bf 76 .;?.$v?b=c?.3.@.......?f..>,/..v
1940 01 3b 3f 7e 24 76 3f fa 64 59 3f 99 33 0b 40 00 00 20 bf 9a ad ed 3f 66 ed b2 3e 2c 2f 16 bf 76 .;?~$v?.dY?.3.@.......?f..>,/..v
1960 01 3b 3f e4 fc 7f 3f 66 3d 63 3f a1 33 0b 40 00 00 c0 be 94 ad ed 3f 66 f1 b2 3e 2c 2f 16 3f 76 .;?...?f=c?.3.@.......?f..>,/.?v
1980 01 3b 3f 83 24 76 3f 62 3d 63 3f 5b 23 1c 40 00 00 c0 be 98 6e a2 3f 76 fb 3a 3f 22 d5 10 3f 88 .;?.$v?b=c?[#.@.....n.?v.:?"..?.
19a0 e5 c3 be 7b 24 76 3f 84 24 76 3f 5b 23 1c 40 00 00 20 bf 96 6e a2 3f 76 fb 3a 3f 22 d5 10 bf 88 ...{$v?.$v?[#.@.....n.?v.:?"....
19c0 e5 c3 be dd fc 7f 3f 88 24 76 3f 5b 23 1c 40 00 00 20 bf 96 6e a2 3f 76 fb 3a 3f 22 d5 10 bf 88 ......?.$v?[#.@.....n.?v.:?"....
19e0 e5 c3 be 7b 24 76 3f e5 fc 7f 3f 5b 23 1c 40 00 00 c0 be 98 6e a2 3f 76 fb 3a 3f 22 d5 10 3f 88 ...{$v?...?[#.@.....n.?v.:?"..?.
1a00 e5 c3 be 7b 24 76 3f 84 24 76 3f df a6 57 c0 00 00 c0 be 69 5b 48 3e d5 69 ea be 28 fd 13 3f 5a ...{$v?.$v?..W.....i[H>.i..(..?Z
1a20 e7 2c bf c9 b7 1d 3d 7a 24 76 3f df a6 57 c0 00 00 20 bf 89 5b 48 3e d5 69 ea be 28 fd 13 bf 5a .,....=z$v?..W......[H>.i..(...Z
1a40 e7 2c bf 8e b7 1d 3d e3 fc 7f 3f 84 3e 5a c0 00 00 c0 be bb 4a cc 3e 61 ab 30 bf 29 9b 14 3f ba .,....=...?.>Z......J.>a.0.)..?.
1a60 3d dd 3e 05 b8 1d 3d 59 3d 63 3f 88 3e 5a c0 00 00 20 bf cb 4a cc 3e 61 ab 30 bf 29 9b 14 bf ba =.>...=Y=c?.>Z......J.>a.0.)....
1a80 3d dd 3e 0c b1 47 38 56 3d 63 3f df a6 57 c0 00 00 20 bf 89 5b 48 3e d5 69 ea be 28 fd 13 bf 5a =.>..G8V=c?..W......[H>.i..(...Z
1aa0 e7 2c bf c7 c3 46 38 77 24 76 3f df a6 57 c0 00 00 c0 be 69 5b 48 3e d5 69 ea be 28 fd 13 3f 5a .,...F8w$v?..W.....i[H>.i..(..?Z
1ac0 e7 2c bf c9 b7 1d 3d 7a 24 76 3f 54 52 49 53 84 04 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 .,....=z$v?TRIS.................
1ae0 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 06 00 00 00 05 00 00 00 04 00 00 00 07 00 00 00 06 ................................
1b00 00 00 00 04 00 00 00 0a 00 00 00 09 00 00 00 08 00 00 00 0b 00 00 00 0a 00 00 00 08 00 00 00 0e ................................
1b20 00 00 00 0d 00 00 00 0c 00 00 00 0f 00 00 00 0e 00 00 00 0c 00 00 00 12 00 00 00 11 00 00 00 10 ................................
1b40 00 00 00 13 00 00 00 12 00 00 00 10 00 00 00 16 00 00 00 15 00 00 00 14 00 00 00 17 00 00 00 16 ................................
1b60 00 00 00 14 00 00 00 1a 00 00 00 19 00 00 00 18 00 00 00 1b 00 00 00 1a 00 00 00 18 00 00 00 1e ................................
1b80 00 00 00 1d 00 00 00 1c 00 00 00 1f 00 00 00 1e 00 00 00 1c 00 00 00 22 00 00 00 21 00 00 00 20 ......................."...!....
1ba0 00 00 00 23 00 00 00 22 00 00 00 20 00 00 00 26 00 00 00 25 00 00 00 24 00 00 00 27 00 00 00 26 ...#...".......&...%...$...'...&
1bc0 00 00 00 24 00 00 00 2a 00 00 00 29 00 00 00 28 00 00 00 2b 00 00 00 2a 00 00 00 28 00 00 00 2e ...$...*...)...(...+...*...(....
1be0 00 00 00 2d 00 00 00 2c 00 00 00 2f 00 00 00 2e 00 00 00 2c 00 00 00 32 00 00 00 31 00 00 00 30 ...-...,.../.......,...2...1...0
1c00 00 00 00 33 00 00 00 32 00 00 00 30 00 00 00 36 00 00 00 35 00 00 00 34 00 00 00 39 00 00 00 38 ...3...2...0...6...5...4...9...8
1c20 00 00 00 37 00 00 00 3c 00 00 00 3b 00 00 00 3a 00 00 00 3f 00 00 00 3e 00 00 00 3d 00 00 00 42 ...7...<...;...:...?...>...=...B
1c40 00 00 00 41 00 00 00 40 00 00 00 45 00 00 00 44 00 00 00 43 00 00 00 48 00 00 00 47 00 00 00 46 ...A...@...E...D...C...H...G...F
1c60 00 00 00 4b 00 00 00 4a 00 00 00 49 00 00 00 4e 00 00 00 4d 00 00 00 4c 00 00 00 4f 00 00 00 4e ...K...J...I...N...M...L...O...N
1c80 00 00 00 4c 00 00 00 52 00 00 00 51 00 00 00 50 00 00 00 53 00 00 00 52 00 00 00 50 00 00 00 56 ...L...R...Q...P...S...R...P...V
1ca0 00 00 00 55 00 00 00 54 00 00 00 57 00 00 00 56 00 00 00 54 00 00 00 5a 00 00 00 59 00 00 00 58 ...U...T...W...V...T...Z...Y...X
1cc0 00 00 00 5b 00 00 00 5a 00 00 00 58 00 00 00 5e 00 00 00 5d 00 00 00 5c 00 00 00 5f 00 00 00 5e ...[...Z...X...^...]...\..._...^
1ce0 00 00 00 5c 00 00 00 62 00 00 00 61 00 00 00 60 00 00 00 63 00 00 00 62 00 00 00 60 00 00 00 66 ...\...b...a...`...c...b...`...f
1d00 00 00 00 65 00 00 00 64 00 00 00 67 00 00 00 66 00 00 00 64 00 00 00 6a 00 00 00 69 00 00 00 68 ...e...d...g...f...d...j...i...h
1d20 00 00 00 6b 00 00 00 6a 00 00 00 68 00 00 00 6e 00 00 00 6d 00 00 00 6c 00 00 00 6f 00 00 00 6e ...k...j...h...n...m...l...o...n
1d40 00 00 00 6c 00 00 00 72 00 00 00 71 00 00 00 70 00 00 00 73 00 00 00 72 00 00 00 70 00 00 00 76 ...l...r...q...p...s...r...p...v
1d60 00 00 00 75 00 00 00 74 00 00 00 77 00 00 00 76 00 00 00 74 00 00 00 7a 00 00 00 79 00 00 00 78 ...u...t...w...v...t...z...y...x
1d80 00 00 00 7b 00 00 00 7a 00 00 00 78 00 00 00 7e 00 00 00 7d 00 00 00 7c 00 00 00 7f 00 00 00 7e ...{...z...x...~...}...|.......~
1da0 00 00 00 7c 00 00 00 82 00 00 00 81 00 00 00 80 00 00 00 83 00 00 00 82 00 00 00 80 00 00 00 86 ...|............................
1dc0 00 00 00 85 00 00 00 84 00 00 00 89 00 00 00 88 00 00 00 87 00 00 00 8c 00 00 00 8b 00 00 00 8a ................................
1de0 00 00 00 8f 00 00 00 8e 00 00 00 8d 00 00 00 92 00 00 00 91 00 00 00 90 00 00 00 95 00 00 00 94 ................................
1e00 00 00 00 93 00 00 00 98 00 00 00 97 00 00 00 96 00 00 00 9b 00 00 00 9a 00 00 00 99 00 00 00 9e ................................
1e20 00 00 00 9d 00 00 00 9c 00 00 00 9f 00 00 00 9e 00 00 00 9c 00 00 00 a2 00 00 00 a1 00 00 00 a0 ................................
1e40 00 00 00 a3 00 00 00 a2 00 00 00 a0 00 00 00 a6 00 00 00 a5 00 00 00 a4 00 00 00 a7 00 00 00 a6 ................................
1e60 00 00 00 a4 00 00 00 aa 00 00 00 a9 00 00 00 a8 00 00 00 ab 00 00 00 aa 00 00 00 a8 00 00 00 ae ................................
1e80 00 00 00 ad 00 00 00 ac 00 00 00 af 00 00 00 ae 00 00 00 ac 00 00 00 b2 00 00 00 b1 00 00 00 b0 ................................
1ea0 00 00 00 b3 00 00 00 b2 00 00 00 b0 00 00 00 b6 00 00 00 b5 00 00 00 b4 00 00 00 b7 00 00 00 b6 ................................
1ec0 00 00 00 b4 00 00 00 ba 00 00 00 b9 00 00 00 b8 00 00 00 bb 00 00 00 ba 00 00 00 b8 00 00 00 be ................................
1ee0 00 00 00 bd 00 00 00 bc 00 00 00 bf 00 00 00 be 00 00 00 bc 00 00 00 c2 00 00 00 c1 00 00 00 c0 ................................
1f00 00 00 00 c3 00 00 00 c2 00 00 00 c0 00 00 00 c6 00 00 00 c5 00 00 00 c4 00 00 00 c7 00 00 00 c6 ................................
1f20 00 00 00 c4 00 00 00 ca 00 00 00 c9 00 00 00 c8 00 00 00 cb 00 00 00 ca 00 00 00 c8 00 00 00 ce ................................
1f40 00 00 00 cd 00 00 00 cc 00 00 00 cf 00 00 00 ce 00 00 00 cc 00 00 00 .......................
='#n1586'>1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "tile.h"

#include <ICameraSceneNode.h>
#include "util/string.h"
#include "util/container.h"
#include "util/thread.h"
#include "filesys.h"
#include "settings.h"
#include "mesh.h"
#include "gamedef.h"
#include "util/strfnd.h"
#include "imagefilters.h"
#include "guiscalingfilter.h"
#include "renderingengine.h"


#ifdef __ANDROID__
#include <GLES/gl.h>
#endif

/*
	A cache from texture name to texture path
*/
MutexedMap<std::string, std::string> g_texturename_to_path_cache;

/*
	Replaces the filename extension.
	eg:
		std::string image = "a/image.png"
		replace_ext(image, "jpg")
		-> image = "a/image.jpg"
	Returns true on success.
*/
static bool replace_ext(std::string &path, const char *ext)
{
	if (ext == NULL)
		return false;
	// Find place of last dot, fail if \ or / found.
	s32 last_dot_i = -1;
	for (s32 i=path.size()-1; i>=0; i--)
	{
		if (path[i] == '.')
		{
			last_dot_i = i;
			break;
		}

		if (path[i] == '\\' || path[i] == '/')
			break;
	}
	// If not found, return an empty string
	if (last_dot_i == -1)
		return false;
	// Else make the new path
	path = path.substr(0, last_dot_i+1) + ext;
	return true;
}

/*
	Find out the full path of an image by trying different filename
	extensions.

	If failed, return "".
*/
std::string getImagePath(std::string path)
{
	// A NULL-ended list of possible image extensions
	const char *extensions[] = {
		"png", "jpg", "bmp", "tga",
		"pcx", "ppm", "psd", "wal", "rgb",
		NULL
	};
	// If there is no extension, add one
	if (removeStringEnd(path, extensions).empty())
		path = path + ".png";
	// Check paths until something is found to exist
	const char **ext = extensions;
	do{
		bool r = replace_ext(path, *ext);
		if (!r)
			return "";
		if (fs::PathExists(path))
			return path;
	}
	while((++ext) != NULL);

	return "";
}

/*
	Gets the path to a texture by first checking if the texture exists
	in texture_path and if not, using the data path.

	Checks all supported extensions by replacing the original extension.

	If not found, returns "".

	Utilizes a thread-safe cache.
*/
std::string getTexturePath(const std::string &filename)
{
	std::string fullpath;
	/*
		Check from cache
	*/
	bool incache = g_texturename_to_path_cache.get(filename, &fullpath);
	if (incache)
		return fullpath;

	/*
		Check from texture_path
	*/
	const std::string &texture_path = g_settings->get("texture_path");
	if (!texture_path.empty()) {
		std::string testpath = texture_path + DIR_DELIM + filename;
		// Check all filename extensions. Returns "" if not found.
		fullpath = getImagePath(testpath);
	}

	/*
		Check from default data directory
	*/
	if (fullpath.empty())
	{
		std::string base_path = porting::path_share + DIR_DELIM + "textures"
				+ DIR_DELIM + "base" + DIR_DELIM + "pack";
		std::string testpath = base_path + DIR_DELIM + filename;
		// Check all filename extensions. Returns "" if not found.
		fullpath = getImagePath(testpath);
	}

	// Add to cache (also an empty result is cached)
	g_texturename_to_path_cache.set(filename, fullpath);

	// Finally return it
	return fullpath;
}

void clearTextureNameCache()
{
	g_texturename_to_path_cache.clear();
}

/*
	Stores internal information about a texture.
*/

struct TextureInfo
{
	std::string name;
	video::ITexture *texture;

	TextureInfo(
			const std::string &name_,
			video::ITexture *texture_=NULL
		):
		name(name_),
		texture(texture_)
	{
	}
};

/*
	SourceImageCache: A cache used for storing source images.
*/

class SourceImageCache
{
public:
	~SourceImageCache() {
		for (auto &m_image : m_images) {
			m_image.second->drop();
		}
		m_images.clear();
	}
	void insert(const std::string &name, video::IImage *img, bool prefer_local)
	{
		assert(img); // Pre-condition
		// Remove old image
		std::map<std::string, video::IImage*>::iterator n;
		n = m_images.find(name);
		if (n != m_images.end()){
			if (n->second)
				n->second->drop();
		}

		video::IImage* toadd = img;
		bool need_to_grab = true;

		// Try to use local texture instead if asked to
		if (prefer_local){
			std::string path = getTexturePath(name);
			if (!path.empty()) {
				video::IImage *img2 = RenderingEngine::get_video_driver()->
					createImageFromFile(path.c_str());
				if (img2){
					toadd = img2;
					need_to_grab = false;
				}
			}
		}

		if (need_to_grab)
			toadd->grab();
		m_images[name] = toadd;
	}
	video::IImage* get(const std::string &name)
	{
		std::map<std::string, video::IImage*>::iterator n;
		n = m_images.find(name);
		if (n != m_images.end())
			return n->second;
		return NULL;
	}
	// Primarily fetches from cache, secondarily tries to read from filesystem
	video::IImage *getOrLoad(const std::string &name)
	{
		std::map<std::string, video::IImage*>::iterator n;
		n = m_images.find(name);
		if (n != m_images.end()){
			n->second->grab(); // Grab for caller
			return n->second;
		}
		video::IVideoDriver *driver = RenderingEngine::get_video_driver();
		std::string path = getTexturePath(name);
		if (path.empty()) {
			infostream<<"SourceImageCache::getOrLoad(): No path found for \""
					<<name<<"\""<<std::endl;
			return NULL;
		}
		infostream<<"SourceImageCache::getOrLoad(): Loading path \""<<path
				<<"\""<<std::endl;
		video::IImage *img = driver->createImageFromFile(path.c_str());

		if (img){
			m_images[name] = img;
			img->grab(); // Grab for caller
		}
		return img;
	}
private:
	std::map<std::string, video::IImage*> m_images;
};

/*
	TextureSource
*/

class TextureSource : public IWritableTextureSource
{
public:
	TextureSource();
	virtual ~TextureSource();

	/*
		Example case:
		Now, assume a texture with the id 1 exists, and has the name
		"stone.png^mineral1".
		Then a random thread calls getTextureId for a texture called
		"stone.png^mineral1^crack0".
		...Now, WTF should happen? Well:
		- getTextureId strips off stuff recursively from the end until
		  the remaining part is found, or nothing is left when
		  something is stripped out

		But it is slow to search for textures by names and modify them
		like that?
		- ContentFeatures is made to contain ids for the basic plain
		  textures
		- Crack textures can be slow by themselves, but the framework
		  must be fast.

		Example case #2:
		- Assume a texture with the id 1 exists, and has the name
		  "stone.png^mineral_coal.png".
		- Now getNodeTile() stumbles upon a node which uses
		  texture id 1, and determines that MATERIAL_FLAG_CRACK
		  must be applied to the tile
		- MapBlockMesh::animate() finds the MATERIAL_FLAG_CRACK and
		  has received the current crack level 0 from the client. It
		  finds out the name of the texture with getTextureName(1),
		  appends "^crack0" to it and gets a new texture id with
		  getTextureId("stone.png^mineral_coal.png^crack0").

	*/

	/*
		Gets a texture id from cache or
		- if main thread, generates the texture, adds to cache and returns id.
		- if other thread, adds to request queue and waits for main thread.

		The id 0 points to a NULL texture. It is returned in case of error.
	*/
	u32 getTextureId(const std::string &name);

	// Finds out the name of a cached texture.
	std::string getTextureName(u32 id);

	/*
		If texture specified by the name pointed by the id doesn't
		exist, create it, then return the cached texture.

		Can be called from any thread. If called from some other thread
		and not found in cache, the call is queued to the main thread
		for processing.
	*/
	video::ITexture* getTexture(u32 id);

	video::ITexture* getTexture(const std::string &name, u32 *id = NULL);

	/*
		Get a texture specifically intended for mesh
		application, i.e. not HUD, compositing, or other 2D
		use.  This texture may be a different size and may
		have had additional filters applied.
	*/
	video::ITexture* getTextureForMesh(const std::string &name, u32 *id);

	virtual Palette* getPalette(const std::string &name);

	bool isKnownSourceImage(const std::string &name)
	{
		bool is_known = false;
		bool cache_found = m_source_image_existence.get(name, &is_known);
		if (cache_found)
			return is_known;
		// Not found in cache; find out if a local file exists
		is_known = (!getTexturePath(name).empty());
		m_source_image_existence.set(name, is_known);
		return is_known;
	}

	// Processes queued texture requests from other threads.
	// Shall be called from the main thread.
	void processQueue();

	// Insert an image into the cache without touching the filesystem.
	// Shall be called from the main thread.
	void insertSourceImage(const std::string &name, video::IImage *img);

	// Rebuild images and textures from the current set of source images
	// Shall be called from the main thread.
	void rebuildImagesAndTextures();

	// Render a mesh to a texture.
	// Returns NULL if render-to-texture failed.
	// Shall be called from the main thread.
	video::ITexture* generateTextureFromMesh(
			const TextureFromMeshParams &params);

	video::ITexture* getNormalTexture(const std::string &name);
	video::SColor getTextureAverageColor(const std::string &name);
	video::ITexture *getShaderFlagsTexture(bool normamap_present);

private:

	// The id of the thread that is allowed to use irrlicht directly
	std::thread::id m_main_thread;

	// Cache of source images
	// This should be only accessed from the main thread
	SourceImageCache m_sourcecache;

	// Generate a texture
	u32 generateTexture(const std::string &name);

	// Generate image based on a string like "stone.png" or "[crack:1:0".
	// if baseimg is NULL, it is created. Otherwise stuff is made on it.
	bool generateImagePart(std::string part_of_name, video::IImage *& baseimg);

	/*! Generates an image from a full string like
	 * "stone.png^mineral_coal.png^[crack:1:0".
	 * Shall be called from the main thread.
	 * The returned Image should be dropped.
	 */
	video::IImage* generateImage(const std::string &name);

	// Thread-safe cache of what source images are known (true = known)
	MutexedMap<std::string, bool> m_source_image_existence;

	// A texture id is index in this array.
	// The first position contains a NULL texture.
	std::vector<TextureInfo> m_textureinfo_cache;
	// Maps a texture name to an index in the former.
	std::map<std::string, u32> m_name_to_id;
	// The two former containers are behind this mutex
	std::mutex m_textureinfo_cache_mutex;

	// Queued texture fetches (to be processed by the main thread)
	RequestQueue<std::string, u32, u8, u8> m_get_texture_queue;

	// Textures that have been overwritten with other ones
	// but can't be deleted because the ITexture* might still be used
	std::vector<video::ITexture*> m_texture_trash;

	// Maps image file names to loaded palettes.
	std::unordered_map<std::string, Palette> m_palettes;

	// Cached settings needed for making textures from meshes
	bool m_setting_trilinear_filter;
	bool m_setting_bilinear_filter;
	bool m_setting_anisotropic_filter;
};

IWritableTextureSource *createTextureSource()
{
	return new TextureSource();
}

TextureSource::TextureSource()
{
	m_main_thread = std::this_thread::get_id();

	// Add a NULL TextureInfo as the first index, named ""
	m_textureinfo_cache.emplace_back("");
	m_name_to_id[""] = 0;

	// Cache some settings
	// Note: Since this is only done once, the game must be restarted
	// for these settings to take effect
	m_setting_trilinear_filter = g_settings->getBool("trilinear_filter");
	m_setting_bilinear_filter = g_settings->getBool("bilinear_filter");
	m_setting_anisotropic_filter = g_settings->getBool("anisotropic_filter");
}

TextureSource::~TextureSource()
{
	video::IVideoDriver *driver = RenderingEngine::get_video_driver();

	unsigned int textures_before = driver->getTextureCount();

	for (const auto &iter : m_textureinfo_cache) {
		//cleanup texture
		if (iter.texture)
			driver->removeTexture(iter.texture);
	}
	m_textureinfo_cache.clear();

	for (auto t : m_texture_trash) {
		//cleanup trashed texture
		driver->removeTexture(t);
	}

	infostream << "~TextureSource() "<< textures_before << "/"
			<< driver->getTextureCount() << std::endl;
}

u32 TextureSource::getTextureId(const std::string &name)
{
	//infostream<<"getTextureId(): \""<<name<<"\""<<std::endl;

	{
		/*
			See if texture already exists
		*/
		MutexAutoLock lock(m_textureinfo_cache_mutex);
		std::map<std::string, u32>::iterator n;
		n = m_name_to_id.find(name);
		if (n != m_name_to_id.end())
		{
			return n->second;
		}
	}

	/*
		Get texture
	*/
	if (std::this_thread::get_id() == m_main_thread) {
		return generateTexture(name);
	}


	infostream<<"getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;

	// We're gonna ask the result to be put into here
	static ResultQueue<std::string, u32, u8, u8> result_queue;

	// Throw a request in
	m_get_texture_queue.add(name, 0, 0, &result_queue);

	try {
		while(true) {
			// Wait result for a second
			GetResult<std::string, u32, u8, u8>
				result = result_queue.pop_front(1000);

			if (result.key == name) {
				return result.item;
			}
		}
	} catch(ItemNotFoundException &e) {
		errorstream << "Waiting for texture " << name << " timed out." << std::endl;
		return 0;
	}

	infostream << "getTextureId(): Failed" << std::endl;

	return 0;
}

// Draw an image on top of an another one, using the alpha channel of the
// source image
static void blit_with_alpha(video::IImage *src, video::IImage *dst,
		v2s32 src_pos, v2s32 dst_pos, v2u32 size);

// Like blit_with_alpha, but only modifies destination pixels that
// are fully opaque
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
		v2s32 src_pos, v2s32 dst_pos, v2u32 size);

// Apply a color to an image.  Uses an int (0-255) to calculate the ratio.
// If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
// color alpha with the destination alpha.
// Otherwise, any pixels that are not fully transparent get the color alpha.
static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
		const video::SColor &color, int ratio, bool keep_alpha);

// paint a texture using the given color
static void apply_multiplication(video::IImage *dst, v2u32 dst_pos, v2u32 size,
		const video::SColor &color);

// Apply a mask to an image
static void apply_mask(video::IImage *mask, video::IImage *dst,
		v2s32 mask_pos, v2s32 dst_pos, v2u32 size);

// Draw or overlay a crack
static void draw_crack(video::IImage *crack, video::IImage *dst,
		bool use_overlay, s32 frame_count, s32 progression,
		video::IVideoDriver *driver);

// Brighten image
void brighten(video::IImage *image);
// Parse a transform name
u32 parseImageTransform(const std::string& s);
// Apply transform to image dimension
core::dimension2d<u32> imageTransformDimension(u32 transform, core::dimension2d<u32> dim);
// Apply transform to image data
void imageTransform(u32 transform, video::IImage *src, video::IImage *dst);

/*
	This method generates all the textures
*/
u32 TextureSource::generateTexture(const std::string &name)
{
	//infostream << "generateTexture(): name=\"" << name << "\"" << std::endl;

	// Empty name means texture 0
	if (name.empty()) {
		infostream<<"generateTexture(): name is empty"<<std::endl;
		return 0;
	}

	{
		/*
			See if texture already exists
		*/
		MutexAutoLock lock(m_textureinfo_cache_mutex);
		std::map<std::string, u32>::iterator n;
		n = m_name_to_id.find(name);
		if (n != m_name_to_id.end()) {
			return n->second;
		}
	}

	/*
		Calling only allowed from main thread
	*/
	if (std::this_thread::get_id() != m_main_thread) {
		errorstream<<"TextureSource::generateTexture() "
				"called not from main thread"<<std::endl;
		return 0;
	}

	video::IVideoDriver *driver = RenderingEngine::get_video_driver();
	sanity_check(driver);

	video::IImage *img = generateImage(name);

	video::ITexture *tex = NULL;

	if (img != NULL) {
#ifdef __ANDROID__
		img = Align2Npot2(img, driver);
#endif
		// Create texture from resulting image
		tex = driver->addTexture(name.c_str(), img);
		guiScalingCache(io::path(name.c_str()), driver, img);
		img->drop();
	}

	/*
		Add texture to caches (add NULL textures too)
	*/

	MutexAutoLock lock(m_textureinfo_cache_mutex);

	u32 id = m_textureinfo_cache.size();
	TextureInfo ti(name, tex);
	m_textureinfo_cache.push_back(ti);
	m_name_to_id[name] = id;

	return id;
}

std::string TextureSource::getTextureName(u32 id)
{
	MutexAutoLock lock(m_textureinfo_cache_mutex);

	if (id >= m_textureinfo_cache.size())
	{
		errorstream<<"TextureSource::getTextureName(): id="<<id
				<<" >= m_textureinfo_cache.size()="
				<<m_textureinfo_cache.size()<<std::endl;
		return "";
	}

	return m_textureinfo_cache[id].name;
}

video::ITexture* TextureSource::getTexture(u32 id)
{
	MutexAutoLock lock(m_textureinfo_cache_mutex);

	if (id >= m_textureinfo_cache.size())
		return NULL;

	return m_textureinfo_cache[id].texture;
}

video::ITexture* TextureSource::getTexture(const std::string &name, u32 *id)
{
	u32 actual_id = getTextureId(name);
	if (id){
		*id = actual_id;
	}
	return getTexture(actual_id);
}

video::ITexture* TextureSource::getTextureForMesh(const std::string &name, u32 *id)
{
	return getTexture(name + "^[applyfiltersformesh", id);
}

Palette* TextureSource::getPalette(const std::string &name)
{
	// Only the main thread may load images
	sanity_check(std::this_thread::get_id() == m_main_thread);

	if (name.empty())
		return NULL;

	auto it = m_palettes.find(name);
	if (it == m_palettes.end()) {
		// Create palette
		video::IImage *img = generateImage(name);
		if (!img) {
			warningstream << "TextureSource::getPalette(): palette \"" << name
				<< "\" could not be loaded." << std::endl;
			return NULL;
		}
		Palette new_palette;
		u32 w = img->getDimension().Width;
		u32 h = img->getDimension().Height;
		// Real area of the image
		u32 area = h * w;
		if (area == 0)
			return NULL;
		if (area > 256) {
			warningstream << "TextureSource::getPalette(): the specified"
				<< " palette image \"" << name << "\" is larger than 256"
				<< " pixels, using the first 256." << std::endl;
			area = 256;
		} else if (256 % area != 0)
			warningstream << "TextureSource::getPalette(): the "
				<< "specified palette image \"" << name << "\" does not "
				<< "contain power of two pixels." << std::endl;
		// We stretch the palette so it will fit 256 values
		// This many param2 values will have the same color
		u32 step = 256 / area;
		// For each pixel in the image
		for (u32 i = 0; i < area; i++) {
			video::SColor c = img->getPixel(i % w, i / w);
			// Fill in palette with 'step' colors
			for (u32 j = 0; j < step; j++)
				new_palette.push_back(c);
		}
		img->drop();
		// Fill in remaining elements
		while (new_palette.size() < 256)
			new_palette.emplace_back(0xFFFFFFFF);
		m_palettes[name] = new_palette;
		it = m_palettes.find(name);
	}
	if (it != m_palettes.end())
		return &((*it).second);
	return NULL;
}

void TextureSource::processQueue()
{
	/*
		Fetch textures
	*/
	//NOTE this is only thread safe for ONE consumer thread!
	if (!m_get_texture_queue.empty())
	{
		GetRequest<std::string, u32, u8, u8>
				request = m_get_texture_queue.pop();

		/*infostream<<"TextureSource::processQueue(): "
				<<"got texture request with "
				<<"name=\""<<request.key<<"\""
				<<std::endl;*/

		m_get_texture_queue.pushResult(request, generateTexture(request.key));
	}
}

void TextureSource::insertSourceImage(const std::string &name, video::IImage *img)
{
	//infostream<<"TextureSource::insertSourceImage(): name="<<name<<std::endl;

	sanity_check(std::this_thread::get_id() == m_main_thread);

	m_sourcecache.insert(name, img, true);
	m_source_image_existence.set(name, true);
}

void TextureSource::rebuildImagesAndTextures()
{
	MutexAutoLock lock(m_textureinfo_cache_mutex);

	video::IVideoDriver *driver = RenderingEngine::get_video_driver();
	sanity_check(driver);

	// Recreate textures
	for (TextureInfo &ti : m_textureinfo_cache) {
		video::IImage *img = generateImage(ti.name);
#ifdef __ANDROID__
		img = Align2Npot2(img, driver);
#endif
		// Create texture from resulting image
		video::ITexture *t = NULL;
		if (img) {
			t = driver->addTexture(ti.name.c_str(), img);
			guiScalingCache(io::path(ti.name.c_str()), driver, img);
			img->drop();
		}
		video::ITexture *t_old = ti.texture;
		// Replace texture
		ti.texture = t;

		if (t_old)
			m_texture_trash.push_back(t_old);
	}
}

video::ITexture* TextureSource::generateTextureFromMesh(
		const TextureFromMeshParams &params)
{
	video::IVideoDriver *driver = RenderingEngine::get_video_driver();
	sanity_check(driver);

#ifdef __ANDROID__
	const GLubyte* renderstr = glGetString(GL_RENDERER);
	std::string renderer((char*) renderstr);

	// use no render to texture hack
	if (
		(renderer.find("Adreno") != std::string::npos) ||
		(renderer.find("Mali") != std::string::npos) ||
		(renderer.find("Immersion") != std::string::npos) ||
		(renderer.find("Tegra") != std::string::npos) ||
		g_settings->getBool("inventory_image_hack")
		) {
		// Get a scene manager
		scene::ISceneManager *smgr_main = m_device->getSceneManager();
		sanity_check(smgr_main);
		scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
		sanity_check(smgr);

		const float scaling = 0.2;

		scene::IMeshSceneNode* meshnode =
				smgr->addMeshSceneNode(params.mesh, NULL,
						-1, v3f(0,0,0), v3f(0,0,0),
						v3f(1.0 * scaling,1.0 * scaling,1.0 * scaling), true);
		meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
		meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
		meshnode->setMaterialFlag(video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
		meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, m_setting_bilinear_filter);
		meshnode->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, m_setting_anisotropic_filter);

		scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
				params.camera_position, params.camera_lookat);
		// second parameter of setProjectionMatrix (isOrthogonal) is ignored
		camera->setProjectionMatrix(params.camera_projection_matrix, false);

		smgr->setAmbientLight(params.ambient_light);
		smgr->addLightSceneNode(0,
				params.light_position,
				params.light_color,
				params.light_radius*scaling);

		core::dimension2d<u32> screen = driver->getScreenSize();

		// Render scene
		driver->beginScene(true, true, video::SColor(0,0,0,0));
		driver->clearZBuffer();
		smgr->drawAll();

		core::dimension2d<u32> partsize(screen.Width * scaling,screen.Height * scaling);

		irr::video::IImage* rawImage =
				driver->createImage(irr::video::ECF_A8R8G8B8, partsize);

		u8* pixels = static_cast<u8*>(rawImage->lock());
		if (!pixels)
		{
			rawImage->drop();
			return NULL;
		}

		core::rect<s32> source(
				screen.Width /2 - (screen.Width  * (scaling / 2)),
				screen.Height/2 - (screen.Height * (scaling / 2)),
				screen.Width /2 + (screen.Width  * (scaling / 2)),
				screen.Height/2 + (screen.Height * (scaling / 2))
			);

		glReadPixels(source.UpperLeftCorner.X, source.UpperLeftCorner.Y,
				partsize.Width, partsize.Height, GL_RGBA,
				GL_UNSIGNED_BYTE, pixels);

		driver->endScene();

		// Drop scene manager
		smgr->drop();

		unsigned int pixelcount = partsize.Width*partsize.Height;

		u8* runptr = pixels;
		for (unsigned int i=0; i < pixelcount; i++) {

			u8 B = *runptr;
			u8 G = *(runptr+1);
			u8 R = *(runptr+2);
			u8 A = *(runptr+3);

			//BGRA -> RGBA
			*runptr = R;
			runptr ++;
			*runptr = G;
			runptr ++;
			*runptr = B;
			runptr ++;
			*runptr = A;
			runptr ++;
		}

		video::IImage* inventory_image =
				driver->createImage(irr::video::ECF_A8R8G8B8, params.dim);

		rawImage->copyToScaling(inventory_image);
		rawImage->drop();

		guiScalingCache(io::path(params.rtt_texture_name.c_str()), driver, inventory_image);

		video::ITexture *rtt = driver->addTexture(params.rtt_texture_name.c_str(), inventory_image);
		inventory_image->drop();

		if (rtt == NULL) {
			errorstream << "TextureSource::generateTextureFromMesh(): failed to recreate texture from image: " << params.rtt_texture_name << std::endl;
			return NULL;
		}

		driver->makeColorKeyTexture(rtt, v2s32(0,0));

		if (params.delete_texture_on_shutdown)
			m_texture_trash.push_back(rtt);

		return rtt;
	}
#endif

	if (!driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) {
		static bool warned = false;
		if (!warned)
		{
			errorstream<<"TextureSource::generateTextureFromMesh(): "
				<<"EVDF_RENDER_TO_TARGET not supported."<<std::endl;
			warned = true;
		}
		return NULL;
	}

	// Create render target texture
	video::ITexture *rtt = driver->addRenderTargetTexture(
			params.dim, params.rtt_texture_name.c_str(),
			video::ECF_A8R8G8B8);
	if (rtt == NULL)
	{
		errorstream<<"TextureSource::generateTextureFromMesh(): "
			<<"addRenderTargetTexture returned NULL."<<std::endl;
		return NULL;
	}

	// Set render target
	if (!driver->setRenderTarget(rtt, false, true, video::SColor(0,0,0,0))) {
		driver->removeTexture(rtt);
		errorstream<<"TextureSource::generateTextureFromMesh(): "
			<<"failed to set render target"<<std::endl;
		return NULL;
	}

	// Get a scene manager
	scene::ISceneManager *smgr_main = RenderingEngine::get_scene_manager();
	assert(smgr_main);
	scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
	assert(smgr);

	scene::IMeshSceneNode* meshnode =
			smgr->addMeshSceneNode(params.mesh, NULL,
					-1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
	meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
	meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
	meshnode->setMaterialFlag(video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
	meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, m_setting_bilinear_filter);
	meshnode->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, m_setting_anisotropic_filter);

	scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
			params.camera_position, params.camera_lookat);
	// second parameter of setProjectionMatrix (isOrthogonal) is ignored
	camera->setProjectionMatrix(params.camera_projection_matrix, false);

	smgr->setAmbientLight(params.ambient_light);
	smgr->addLightSceneNode(0,
			params.light_position,
			params.light_color,
			params.light_radius);

	// Render scene
	driver->beginScene(true, true, video::SColor(0,0,0,0));
	smgr->drawAll();
	driver->endScene();

	// Drop scene manager
	smgr->drop();

	// Unset render target
	driver->setRenderTarget(0, false, true, video::SColor(0,0,0,0));

	if (params.delete_texture_on_shutdown)
		m_texture_trash.push_back(rtt);

	return rtt;
}

video::IImage* TextureSource::generateImage(const std::string &name)
{
	// Get the base image

	const char separator = '^';
	const char escape = '\\';
	const char paren_open = '(';
	const char paren_close = ')';

	// Find last separator in the name
	s32 last_separator_pos = -1;
	u8 paren_bal = 0;
	for (s32 i = name.size() - 1; i >= 0; i--) {
		if (i > 0 && name[i-1] == escape)
			continue;
		switch (name[i]) {
		case separator:
			if (paren_bal == 0) {
				last_separator_pos = i;
				i = -1; // break out of loop
			}
			break;
		case paren_open:
			if (paren_bal == 0) {
				errorstream << "generateImage(): unbalanced parentheses"
						<< "(extranous '(') while generating texture \""
						<< name << "\"" << std::endl;
				return NULL;
			}
			paren_bal--;
			break;
		case paren_close:
			paren_bal++;
			break;
		default:
			break;
		}
	}
	if (paren_bal > 0) {
		errorstream << "generateImage(): unbalanced parentheses"
				<< "(missing matching '(') while generating texture \""
				<< name << "\"" << std::endl;
		return NULL;
	}


	video::IImage *baseimg = NULL;

	/*
		If separator was found, make the base image
		using a recursive call.
	*/
	if (last_separator_pos != -1) {
		baseimg = generateImage(name.substr(0, last_separator_pos));
	}

	/*
		Parse out the last part of the name of the image and act
		according to it
	*/

	std::string last_part_of_name = name.substr(last_separator_pos + 1);

	/*
		If this name is enclosed in parentheses, generate it
		and blit it onto the base image
	*/
	if (last_part_of_name[0] == paren_open
			&& last_part_of_name[last_part_of_name.size() - 1] == paren_close) {
		std::string name2 = last_part_of_name.substr(1,
				last_part_of_name.size() - 2);
		video::IImage *tmp = generateImage(name2);
		if (!tmp) {
			errorstream << "generateImage(): "
				"Failed to generate \"" << name2 << "\""
				<< std::endl;
			return NULL;
		}
		core::dimension2d<u32> dim = tmp->getDimension();
		if (baseimg) {
			blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
			tmp->drop();
		} else {
			baseimg = tmp;
		}
	} else if (!generateImagePart(last_part_of_name, baseimg)) {
		// Generate image according to part of name
		errorstream << "generateImage(): "
				"Failed to generate \"" << last_part_of_name << "\""
				<< std::endl;
	}

	// If no resulting image, print a warning
	if (baseimg == NULL) {
		errorstream << "generateImage(): baseimg is NULL (attempted to"
				" create texture \"" << name << "\")" << std::endl;
	}

	return baseimg;
}

#ifdef __ANDROID__
#include <GLES/gl.h>
/**
 * Check and align image to npot2 if required by hardware
 * @param image image to check for npot2 alignment
 * @param driver driver to use for image operations
 * @return image or copy of image aligned to npot2
 */

inline u16 get_GL_major_version()
{
	const GLubyte *gl_version = glGetString(GL_VERSION);
	return (u16) (gl_version[0] - '0');
}

video::IImage * Align2Npot2(video::IImage * image,
		video::IVideoDriver* driver)
{
	if (image == NULL) {
		return image;
	}

	core::dimension2d<u32> dim = image->getDimension();

	std::string extensions = (char*) glGetString(GL_EXTENSIONS);

	// Only GLES2 is trusted to correctly report npot support
	if (get_GL_major_version() > 1 &&
			extensions.find("GL_OES_texture_npot") != std::string::npos) {
		return image;
	}

	unsigned int height = npot2(dim.Height);
	unsigned int width  = npot2(dim.Width);

	if ((dim.Height == height) &&
			(dim.Width == width)) {
		return image;
	}

	if (dim.Height > height) {
		height *= 2;
	}

	if (dim.Width > width) {
		width *= 2;
	}

	video::IImage *targetimage =
			driver->createImage(video::ECF_A8R8G8B8,
					core::dimension2d<u32>(width, height));

	if (targetimage != NULL) {
		image->copyToScaling(targetimage);
	}
	image->drop();
	return targetimage;
}

#endif

static std::string unescape_string(const std::string &str, const char esc = '\\')
{
	std::string out;
	size_t pos = 0, cpos;
	out.reserve(str.size());
	while (1) {
		cpos = str.find_first_of(esc, pos);
		if (cpos == std::string::npos) {
			out += str.substr(pos);
			break;
		}
		out += str.substr(pos, cpos - pos) + str[cpos + 1];
		pos = cpos + 2;
	}
	return out;
}

bool TextureSource::generateImagePart(std::string part_of_name,
		video::IImage *& baseimg)
{
	const char escape = '\\'; // same as in generateImage()
	video::IVideoDriver *driver = RenderingEngine::get_video_driver();
	sanity_check(driver);

	// Stuff starting with [ are special commands
	if (part_of_name.empty() || part_of_name[0] != '[') {
		video::IImage *image = m_sourcecache.getOrLoad(part_of_name);
#ifdef __ANDROID__
		image = Align2Npot2(image, driver);
#endif
		if (image == NULL) {
			if (!part_of_name.empty()) {

				// Do not create normalmap dummies
				if (part_of_name.find("_normal.png") != std::string::npos) {
					warningstream << "generateImage(): Could not load normal map \""
						<< part_of_name << "\"" << std::endl;
					return true;
				}

				errorstream << "generateImage(): Could not load image \""
					<< part_of_name << "\" while building texture; "
					"Creating a dummy image" << std::endl;
			}

			// Just create a dummy image
			//core::dimension2d<u32> dim(2,2);
			core::dimension2d<u32> dim(1,1);
			image = driver->createImage(video::ECF_A8R8G8B8, dim);
			sanity_check(image != NULL);
			/*image->setPixel(0,0, video::SColor(255,255,0,0));
			image->setPixel(1,0, video::SColor(255,0,255,0));
			image->setPixel(0,1, video::SColor(255,0,0,255));
			image->setPixel(1,1, video::SColor(255,255,0,255));*/
			image->setPixel(0,0, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			/*image->setPixel(1,0, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			image->setPixel(0,1, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			image->setPixel(1,1, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));*/
		}

		// If base image is NULL, load as base.
		if (baseimg == NULL)
		{
			//infostream<<"Setting "<<part_of_name<<" as base"<<std::endl;
			/*
				Copy it this way to get an alpha channel.
				Otherwise images with alpha cannot be blitted on
				images that don't have alpha in the original file.
			*/
			core::dimension2d<u32> dim = image->getDimension();
			baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
			image->copyTo(baseimg);
		}
		// Else blit on base.
		else
		{
			//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
			// Size of the copied area
			core::dimension2d<u32> dim = image->getDimension();
			//core::dimension2d<u32> dim(16,16);
			// Position to copy the blitted to in the base image
			core::position2d<s32> pos_to(0,0);
			// Position to copy the blitted from in the blitted image
			core::position2d<s32> pos_from(0,0);
			// Blit
			/*image->copyToWithAlpha(baseimg, pos_to,
					core::rect<s32>(pos_from, dim),
					video::SColor(255,255,255,255),
					NULL);*/

			core::dimension2d<u32> dim_dst = baseimg->getDimension();
			if (dim == dim_dst) {
				blit_with_alpha(image, baseimg, pos_from, pos_to, dim);
			} else if (dim.Width * dim.Height < dim_dst.Width * dim_dst.Height) {
				// Upscale overlying image
				video::IImage *scaled_image = RenderingEngine::get_video_driver()->
					createImage(video::ECF_A8R8G8B8, dim_dst);
				image->copyToScaling(scaled_image);

				blit_with_alpha(scaled_image, baseimg, pos_from, pos_to, dim_dst);
				scaled_image->drop();
			} else {
				// Upscale base image
				video::IImage *scaled_base = RenderingEngine::get_video_driver()->
					createImage(video::ECF_A8R8G8B8, dim);
				baseimg->copyToScaling(scaled_base);
				baseimg->drop();
				baseimg = scaled_base;

				blit_with_alpha(image, baseimg, pos_from, pos_to, dim);
			}
		}
		//cleanup
		image->drop();
	}
	else
	{
		// A special texture modification

		/*infostream<<"generateImage(): generating special "
				<<"modification \""<<part_of_name<<"\""
				<<std::endl;*/

		/*
			[crack:N:P
			[cracko:N:P
			Adds a cracking texture
			N = animation frame count, P = crack progression
		*/
		if (str_starts_with(part_of_name, "[crack"))
		{
			if (baseimg == NULL) {
				errorstream<<"generateImagePart(): baseimg == NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			// Crack image number and overlay option
			bool use_overlay = (part_of_name[6] == 'o');
			Strfnd sf(part_of_name);
			sf.next(":");
			s32 frame_count = stoi(sf.next(":"));
			s32 progression = stoi(sf.next(":"));

			if (progression >= 0) {
				/*
					Load crack image.

					It is an image with a number of cracking stages
					horizontally tiled.
				*/
				video::IImage *img_crack = m_sourcecache.getOrLoad(
					"crack_anylength.png");

				if (img_crack) {
					draw_crack(img_crack, baseimg,
						use_overlay, frame_count,
						progression, driver);
					img_crack->drop();
				}
			}
		}
		/*
			[combine:WxH:X,Y=filename:X,Y=filename2
			Creates a bigger texture from any amount of smaller ones
		*/
		else if (str_starts_with(part_of_name, "[combine"))
		{
			Strfnd sf(part_of_name);
			sf.next(":");
			u32 w0 = stoi(sf.next("x"));
			u32 h0 = stoi(sf.next(":"));
			core::dimension2d<u32> dim(w0,h0);
			if (baseimg == NULL) {
				baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
				baseimg->fill(video::SColor(0,0,0,0));
			}
			while (!sf.at_end()) {
				u32 x = stoi(sf.next(","));
				u32 y = stoi(sf.next("="));
				std::string filename = unescape_string(sf.next_esc(":", escape), escape);
				infostream<<"Adding \""<<filename
						<<"\" to combined ("<<x<<","<<y<<")"
						<<std::endl;
				video::IImage *img = generateImage(filename);
				if (img) {
					core::dimension2d<u32> dim = img->getDimension();
					infostream<<"Size "<<dim.Width
							<<"x"<<dim.Height<<std::endl;
					core::position2d<s32> pos_base(x, y);
					video::IImage *img2 =
							driver->createImage(video::ECF_A8R8G8B8, dim);
					img->copyTo(img2);
					img->drop();
					/*img2->copyToWithAlpha(baseimg, pos_base,
							core::rect<s32>(v2s32(0,0), dim),
							video::SColor(255,255,255,255),
							NULL);*/
					blit_with_alpha(img2, baseimg, v2s32(0,0), pos_base, dim);
					img2->drop();
				} else {
					errorstream << "generateImagePart(): Failed to load image \""
						<< filename << "\" for [combine" << std::endl;
				}
			}
		}
		/*
			[brighten
		*/
		else if (str_starts_with(part_of_name, "[brighten"))
		{
			if (baseimg == NULL) {
				errorstream<<"generateImagePart(): baseimg==NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			brighten(baseimg);
		}
		/*
			[noalpha
			Make image completely opaque.
			Used for the leaves texture when in old leaves mode, so
			that the transparent parts don't look completely black
			when simple alpha channel is used for rendering.
		*/
		else if (str_starts_with(part_of_name, "[noalpha"))
		{
			if (baseimg == NULL){
				errorstream<<"generateImagePart(): baseimg==NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;