Цитата Сообщение от ivagor Посмотреть сообщение
То 16 битное финальное, в других случаях добавляется 2.
Архитектурный косяк, конечно. Из-за этого приходится заводить отдельный признак для 16-битных значений и делать лишнюю проверку. Итого, две лишние инструкции.
В общем, поборол я chipdale.rom, распаковщик работает корректно. Размер 254 байта (244 байт для неперемещаемого варианта). И чуть быстрей исполняется (на 6% быстрей твоего оригинального).
Оптимизация привела к тому, что появляется один артефакт: рандомный байт в памяти после распакованного файла. Это мешает, если данные выводятся сразу на экран. В таком случае после распаковки надо очищать содержимое байта, на который указывает R2. Чуть сложней случай - распаковка впритык к границе ПЗУ - тогда лишний байт попытается записать себя в ПЗУ и произойдёт прерывание (впрочем, означающее конец распаковки).

Код:
; LZSA2 PDP-11 decompressor by Manwe/SandS
; Thanks to Ivan Gorodetsky
; Usage:
; MOV #src_adr,R1
; MOV #dst_adr,R2
; CALL Unpack


Unpack: MOV PC,Table+2      ; correct table address
        ADD #XYZ-Unpack-2,Table+2
        CLR R4              ; no nibbles sign
Token:  MOVB (R1)+,R3       ; read token

Liter:  MOV R3,R0
        ASR R0
        ASR R0
        ASR R0
        BIC #177774,R0      ; get 2 bits
        BEQ Decode
        CMP R0,#3           ; literals length
        BNE Copy
            MOVB #239.,(R2) ; set limit
            CALL Extend
Copy:   MOVB (R1)+,(R2)+    ; literals length in R0
        SOB R0,Copy

Decode: MOV R3,-(SP)    
        COM R3              ; invert for faster detect
        ROLB R3             ; get 2 bits
        ROL R0
        ROLB R3
        ROL R0
Table:  MOVB XYZ(R0),R0
        ADD R0,PC           ; run subroutine
Save:   MOV R0,(PC)+        ; save offset for future
Offset: .WORD 0

Match:  MOV (SP)+,R0
        BIC #177770,R0      ; get 3 bits
        CMP R0,#7
        BNE Clone
            MOVB #233.,(R2) ; set limit
            CALL Extend
            BCS Clone+4     ; skip minimal match length
Clone:  ADD #2,R0           ; match length
        TSTB R0
        BEQ Exit

        MOV R2,R3
        ADD Offset,R3
1:      MOVB (R3)+,(R2)+
        SOB R0,1
        BR Token


XYZ:    .BYTE oOther-Save, o13bit-Save, o9bit-Save, o5bit-Save

o5bit:  CALL Nibble         ; get nibble in R0
        ROLB R3
        ROL R0
        BIS #177740,R0      ; set bits 5-15
        BR Save

o9bit:  ROLB R3
        ROL R0
        SWAB R0
        BISB (R1)+,R0
        BIS #177000,R0      ; set bits 9-15
        BR Save

o13bit: CALL Nibble         ; get nibble in R0
        ROLB R3
        ROL R0
        SWAB R0
        BISB (R1)+,R0       ; 8 bits
        BIS #160000,R0      ; set bits 13-15
        SUB #512.,R0
        BR Save

oOther: ROLB R3
        BCS 1
            MOV Offset,R0   ; reuse offset
            BR Match
1:      MOVB (R1)+,R0
        SWAB R0
        CLRB R0
        BISB (R1)+,R0
        BR Save

Nibble: COM R4
        BNE 1
            MOV R5,R0
            BR 2
1:      MOVB (R1)+,R5       ; read 2 nibbles
        MOV R5,R0
        ASR R0
        ASR R0
        ASR R0
        ASR R0
2:      BIC #177760,R0      ; leave 4 low bits
        RET

Extend: MOV R0,-(SP)        ; save original value
        CALL Nibble         ; get nibble in R0
        CMP R0,#15.
        BNE Ext2
            CLR R0
            BISB (R1)+,R0
            CMPB R0,(R2)    ; compare with limit
            BNE Ext1
                ; unnecessary for short files
                MOVB (R1)+,R0   ; read low byte
                SWAB R0
                CLRB R0
                BISB (R1)+,R0   ; read high byte
                SWAB R0
                TST (SP)+       ; skip saved R0
                SEC             ; set sign of 16 bit vslue
                RET
Ext1:       ADD #15.,R0
Ext2:   ADD (SP)+,R0        ; add original value
Exit:   RET

.END
Если интересно как я проверяю скорость: пишу такой код, он замеряет сколько тиков таймера распаковывается файл и выводит 10-чное число на экран (средствами MKDOS, в других операционных системах не выведет). Чем меньше число, тем быстрей исполнение. Один тик таймера равен 128-и тактам процессора.
Код:
        TimerCommand    = 177712    ; timer port address
        TimerCounter    = 177710
        TimerInitial    = 177706
        DecOut          = 120060    ; MKDOS subroutine

        MOV #1,@#TimerInitial
        MOV #1,@#TimerCommand       ; stop and init timer   
        MOV #TimerCounter,R4
        MTPS #340                   ; disable all interruptions
        MOV #32,@#TimerCommand      ; start timer
1:      TST (R4)                    ; wait till it's really started
        BNE 1

    MOV #File,R1
    MOV #40000,R2
    CALL Unpack

        MOV @#TimerCounter,R0       ; get timer value
        NEG R0
        MTPS #0                     ; enable all interruptions
        CALL   @DecOut

    HALT
- - - Добавлено - - -

Цитата Сообщение от ivagor Посмотреть сообщение
Да, только я не помню, какой версией сжимал. Сейчас уже есть 1.3.7, а там была или 1.3.5 или 1.3.6. На всякий случай размер сжатого файла 7965 байт
7963 байт выдаёт последняя версия упаковщика