swf2js에서 swf를 직접 분해하여 canvas로 출력

swf의 바이너리를 JavaScript로 읽고 바이너리 분해하여 canvas에 출력하고 싶습니다.

완제품



ienaga/swf2js

SWF 사양서



SWF의 사양서가 공개되어 있으므로 사양서를 보면서 분해한다.

SWF File Format Specification

SWF Investigator



분해된 상태를 확인할 수 있다. 편리.

Adobe SWF Investigator

swf 로드


var xmlHttpRequest = new XMLHttpRequest();

xmlHttpRequest.open('GET', url);

// XMLHttpRequest2が使えるなら使う
isXHR2 = typeof xmlHttpRequest.responseType != 'undefined';

if (isXHR2) {
    xmlHttpRequest.responseType = 'arraybuffer';
} else {
    xmlHttpRequest.overrideMimeType(
        'text/plain; charset=x-user-defined'
    );
}

xmlHttpRequest.send(null);

xmlHttpRequest.onreadystatechange = function()
{

    var readyState = xmlHttpRequest.readyState;

    if (readyState == 4) {

        var status = xmlHttpRequest.status;

        switch (status) {

            case 200:

                // 分解の実装
                parse(isXHR2 ? xmlHttpRequest.response : xmlHttpRequest.responseText, player.parent);
                ...省略
                break;

            case 404:
                alert('Swf Data Not Found');
                break;

            case 500:
                alert('Internal Server Error');
                break;

        }
    }
}

바이너리 분해



취득한 바이너리를 분해・・・

아니, 이런 무지한 상태에서 공부 시작해도 전혀 의미 불명 너무・・・

라는 일로, 바이너리의 달인 yoya씨의 「swfpl」의 「bitio.js」를 사용해 공부하겠습니다!

yoya/swfpl

XMLHttpRequest2를 지원하지 않으면 이진 데이터를 0에서 255 사이의 숫자로 변환합니다.
타입 첨부 배열(Typed Array)에 대응하고 있는 단말이라면Typed Array를 사용한다.

bitio.js
    /**
     * BitIO
     * @constructor
     */
    var BitIO = function()
    {
        this.data = null;
        this.bit_offset = 0;
        this.byte_offset = 0;
        this.bit_buffer = null;
    };

    /**
     * init
     * @param binary
     */
    BitIO.prototype.init = function(binary)
    {
        var _this = this;
        var length = binary.length;
        var array = _this.createArray(length);
        var key = 0;
        for (; length--;) {
            array[key] = binary.charCodeAt(key++) & 0xff;
        }
        this.data = array;
    };

    /**
     * createArray
     * @param length
     * @returns {Array}
     */
    BitIO.prototype.createArray = function(length)
    {
        return (window.ArrayBuffer) ? new Uint8Array(length) : [];
    };

    ...省略

모르는 곳은 사용하면서 코네코네하면서 오로지 배울 수밖에 없다. . .

SwfTag



바이너리의 공부를 진행하면서, SWF 사양서에 써 있는 대로 분해해 간다.

tag의 분해는 SWF Investigator의 소스가 매우 도움이 되었습니다.

sourceforge/SWFInvestigator

벡터 분해 및 그리기



개인적으로 가장 고생한 것은 벡터의 분해와 그리기.

SWF의 벡터의 묘화는 1회의 묘화로 2색 도포한다고 하는 실장이 되고 있다.



참고 자료

canvas라면 그렇게 무리가 아닐까・・・orz

그래서 한 번 그리기의 데이터를 2개로 분해하여 그리기 좌표를 결합하기로 했다.



※ s=시작점, e=종점

다음에 부딪힌 문제는 중추의 그리기



하지만...



하테? ? ?

non-zero rule



여러가지 조사한 결과, 중추하기 위해서는 non-zero rule을 사용할 수밖에 없다.

참고 페이지

처럼 0의 부분은 그리지 않는 것 같다.

전제로 시계 방향 그리기를 +1
반시계 방향을 -1로 한다.

시계 방향(+1)의 데이터가 겹치는 부분은 2가 되어 그려진다.



시계 방향(+1)의 묘화와 반시계 방향(-1)의 묘화가 겹치는 분은 0이 되어 묘화되지 않는다



개인적으로는 이 부분에 빠져 몇번이나 만드는 것을 포기할 것 같았다. . .

Action Script



[2015/08/10-추기]
h tp : // 쿠이타. 이 m/아이나가/있어 ms/fc5b25df3b3f2b2f191d

타임라인의 MovieClip가 만든 순서대로 액션을 실행해 간다.

실행중의 액션으로 프레임의 이동이 있으면 이동처의 액션을 예약.

대상을 그리기 전에 작업 수행

이것을 반복한다.

대체로 SWF 사양서대로 ActionScript는 실행되고 있다.

하지만, 반드시 예외적인 거동도 있다고 생각하므로, 그 때는 꼭 코멘트해 주세요.

WebGL



아직 공부중・・・

그중 대응할 예정・・・

flash lite 2.x



현재, 꾸준히 실장중☆彡

목표로서 버전 8에는 대응하고 싶다.

※현재는 버전 5나 6까지라면 대응 할 수 있을 것・・・

데모 사이트는 이쪽으로부터

좋은 웹페이지 즐겨찾기