// File: atsidaev[P]trx2x/DiskImage.cpp
// Function: unpack_td0(unsigned char*, long&)
bool unpack_td0(unsigned char *data, long &size)
{
   if(size < 12) return false;
   if( (*(short*)data != WORD2('T','D'))&&(*(short*)data != WORD2('t','d')) )
      return false;             // non TD0
   if( TD0CRC(data,10) != *((uint16_t*)(data+0x0A)) ) 
      return false;             // CRC bad...
   if( data[4] > 21 ) 
      return false;             // version > 2.1...

   unsigned char *snbuf = (unsigned char*)new char[size*2+1500000];  // if compressed then UUUUFF ;-/
   if(!snbuf) return false;

   memcpy(snbuf, data, size);
   if( *(short*)snbuf == WORD2('t','d') ) // packed disk
   {
      if( snbuf[4] < 20 )    // unsupported Old Advanced compression
      {
         delete snbuf;
         return false;
      }
      unpack_lzh((unsigned char*)data+12, size-12, (unsigned char*)snbuf+12), *(short*)snbuf = WORD2('T','D');
   }

   td0_src = snbuf, td0_dst = data;
   td0_move(12);

   if(snbuf[7] & 0x80)  // additional info...
   {
      unsigned short *cs = (unsigned short*)(snbuf+12+2);

      if( TD0CRC(snbuf+12+2, 8+*cs) != cs[-1] )
      {
         delete snbuf;
         return false;
      }
      td0_move(10);
      td0_move( *((unsigned short*)(snbuf+12+2)) );
   }

   for(;;) 
   {
      unsigned char s = *td0_src;
      td0_move(4); 
      if(s == 0xFF) break;
      for(; s; s--) 
      {
//         unsigned char *sec = td0_src;
         unsigned size = 128; if(td0_src[3]) size <<= td0_src[3];
         td0_move(6); 
         *(unsigned short*)td0_dst = size+1; td0_dst += 2;
         *td0_dst++ = 0; 
         unsigned char *dst = td0_dst;
         unsigned src_size = *(unsigned short*)td0_src; td0_src += 2;
         unsigned char *end_packed_data = td0_src + src_size;
         memset(td0_dst, 0, size);
         switch (*td0_src++) 
         {
            case 0:
               memcpy(dst, td0_src, src_size-1); break;
            case 1:
            {
               unsigned n = *(unsigned short*)td0_src; 
               td0_src += 2;
               unsigned short data = *(unsigned short*)td0_src;
               for(; n; n--) *(unsigned short*)dst = data, dst += 2;
               break;
            }
            case 2:
            {
               unsigned short data; 
               unsigned char s;
               do 
               {
                  switch( *td0_src++ ) 
                  {
                     case 0:
                        for(s = *td0_src++; s; s--) *dst++ = *td0_src++;
                        break;
                     case 1:
                        s = *td0_src++;
                        data = *(unsigned short*)td0_src; 
                        td0_src += 2;
                        for( ; s; s--) *(unsigned short*)dst = data, dst += 2;
                        break;
                     default: shit:
                        delete snbuf;
                        return false;  // "bad TD0 file"
                  }
               } while( td0_src < end_packed_data );
               break;
            }
            default: goto shit;
         }
         td0_dst += size; 
         td0_src = end_packed_data;
      }
   }
   size = (unsigned int)(td0_dst - data);
   delete snbuf;
   return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x18(%rbp), %rax
cmpq $0xc, (%rax)
jge 0xc7c6
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x10(%rbp), %rax
movswl (%rax), %eax
cmpl $0x4454, %eax           # imm = 0x4454
je 0xc7eb
movq -0x10(%rbp), %rax
movswl (%rax), %eax
cmpl $0x6474, %eax           # imm = 0x6474
je 0xc7eb
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x10(%rbp), %rdi
movl $0xa, %esi
callq 0xc700
movzwl %ax, %eax
movq -0x10(%rbp), %rcx
movzwl 0xa(%rcx), %ecx
cmpl %ecx, %eax
je 0xc811
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x10(%rbp), %rax
movzbl 0x4(%rax), %eax
cmpl $0x15, %eax
jle 0xc827
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x18(%rbp), %rax
movq (%rax), %rdi
shlq %rdi
addq $0x16e360, %rdi         # imm = 0x16E360
callq 0x1030
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0xc851
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rax
movq (%rax), %rdx
callq 0x10c0
movq -0x20(%rbp), %rax
movswl (%rax), %eax
cmpl $0x6474, %eax           # imm = 0x6474
jne 0xc8d0
movq -0x20(%rbp), %rax
movzbl 0x4(%rax), %eax
cmpl $0x14, %eax
jge 0xc8a5
movq -0x20(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, %rax
je 0xc89c
movq -0x60(%rbp), %rdi
movl $0x1, %esi
callq 0x1130
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movq -0x10(%rbp), %rdi
addq $0xc, %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
subq $0xc, %rax
movl %eax, %esi
movq -0x20(%rbp), %rdx
addq $0xc, %rdx
callq 0xcd20
movq -0x20(%rbp), %rax
movw $0x4454, (%rax)         # imm = 0x4454
movq -0x20(%rbp), %rax
movq %rax, 0x4d15(%rip)      # 0x115f0
movq -0x10(%rbp), %rax
movq %rax, 0x4d02(%rip)      # 0x115e8
movl $0xc, %edi
callq 0xccc0
movq -0x20(%rbp), %rax
movzbl 0x7(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0xc978
movq -0x20(%rbp), %rax
addq $0xc, %rax
addq $0x2, %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
addq $0xc, %rdi
addq $0x2, %rdi
movq -0x28(%rbp), %rax
movzwl (%rax), %esi
addl $0x8, %esi
callq 0xc700
movzwl %ax, %eax
movq -0x28(%rbp), %rcx
movzwl -0x2(%rcx), %ecx
cmpl %ecx, %eax
je 0xc961
movq -0x20(%rbp), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, %rax
je 0xc958
movq -0x68(%rbp), %rdi
movl $0x1, %esi
callq 0x1130
movb $0x0, -0x1(%rbp)
jmp 0xcca9
movl $0xa, %edi
callq 0xccc0
movq -0x20(%rbp), %rax
movzwl 0xe(%rax), %edi
callq 0xccc0
jmp 0xc97a
movq 0x4c6f(%rip), %rax      # 0x115f0
movb (%rax), %al
movb %al, -0x29(%rbp)
movl $0x4, %edi
callq 0xccc0
movzbl -0x29(%rbp), %eax
cmpl $0xff, %eax
jne 0xc9a0
jmp 0xcc70
jmp 0xc9a2
cmpb $0x0, -0x29(%rbp)
je 0xcc6b
movl $0x80, -0x30(%rbp)
movq 0x4c36(%rip), %rax      # 0x115f0
cmpb $0x0, 0x3(%rax)
je 0xc9d3
movq 0x4c29(%rip), %rax      # 0x115f0
movzbl 0x3(%rax), %ecx
movl -0x30(%rbp), %eax
shll %cl, %eax
movl %eax, -0x30(%rbp)
movl $0x6, %edi
callq 0xccc0
movl -0x30(%rbp), %eax
incl %eax
movw %ax, %cx
movq 0x4bfc(%rip), %rax      # 0x115e8
movw %cx, (%rax)
movq 0x4bf2(%rip), %rax      # 0x115e8
addq $0x2, %rax
movq %rax, 0x4be7(%rip)      # 0x115e8
movq 0x4be0(%rip), %rax      # 0x115e8
movq %rax, %rcx
incq %rcx
movq %rcx, 0x4bd3(%rip)      # 0x115e8
movb $0x0, (%rax)
movq 0x4bc9(%rip), %rax      # 0x115e8
movq %rax, -0x38(%rbp)
movq 0x4bc6(%rip), %rax      # 0x115f0
movzwl (%rax), %eax
movl %eax, -0x3c(%rbp)
movq 0x4bb9(%rip), %rax      # 0x115f0
addq $0x2, %rax
movq %rax, 0x4bae(%rip)      # 0x115f0
movq 0x4ba7(%rip), %rax      # 0x115f0
movl -0x3c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq 0x4b8e(%rip), %rdi      # 0x115e8
movl -0x30(%rbp), %eax
movl %eax, %edx
xorl %esi, %esi
callq 0x1090
movq 0x4b83(%rip), %rax      # 0x115f0
movq %rax, %rcx
incq %rcx
movq %rcx, 0x4b76(%rip)      # 0x115f0
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
testl %eax, %eax
je 0xca9d
jmp 0xca86
movl -0x6c(%rbp), %eax
subl $0x1, %eax
je 0xcabc
jmp 0xca90
movl -0x6c(%rbp), %eax
subl $0x2, %eax
je 0xcb16
jmp 0xcc3b
movq -0x38(%rbp), %rdi
movq 0x4b48(%rip), %rsi      # 0x115f0
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl %eax, %edx
callq 0x10c0
jmp 0xcc3d
movq 0x4b2d(%rip), %rax      # 0x115f0
movzwl (%rax), %eax
movl %eax, -0x4c(%rbp)
movq 0x4b20(%rip), %rax      # 0x115f0
addq $0x2, %rax
movq %rax, 0x4b15(%rip)      # 0x115f0
movq 0x4b0e(%rip), %rax      # 0x115f0
movw (%rax), %ax
movw %ax, -0x4e(%rbp)
cmpl $0x0, -0x4c(%rbp)
je 0xcb11
movw -0x4e(%rbp), %cx
movq -0x38(%rbp), %rax
movw %cx, (%rax)
movq -0x38(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x38(%rbp)
movl -0x4c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0xcae9
jmp 0xcc3d
jmp 0xcb18
movq 0x4ad1(%rip), %rax      # 0x115f0
movq %rax, %rcx
incq %rcx
movq %rcx, 0x4ac4(%rip)      # 0x115f0
movzbl (%rax), %eax
movl %eax, -0x70(%rbp)
testl %eax, %eax
je 0xcb45
jmp 0xcb38
movl -0x70(%rbp), %eax
subl $0x1, %eax
je 0xcb9c
jmp 0xcbff
movq 0x4aa4(%rip), %rax      # 0x115f0
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x4a96(%rip)      # 0x115f0
movb (%rax), %al
movb %al, -0x51(%rbp)
cmpb $0x0, -0x51(%rbp)
je 0xcb97
movq 0x4a84(%rip), %rax      # 0x115f0
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x4a76(%rip)      # 0x115f0
movb (%rax), %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
movb -0x51(%rbp), %al
addb $-0x1, %al
movb %al, -0x51(%rbp)
jmp 0xcb5f
jmp 0xcc26
movq 0x4a4d(%rip), %rax      # 0x115f0
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x4a3f(%rip)      # 0x115f0
movb (%rax), %al
movb %al, -0x51(%rbp)
movq 0x4a33(%rip), %rax      # 0x115f0
movw (%rax), %ax
movw %ax, -0x50(%rbp)
movq 0x4a25(%rip), %rax      # 0x115f0
addq $0x2, %rax
movq %rax, 0x4a1a(%rip)      # 0x115f0
cmpb $0x0, -0x51(%rbp)
je 0xcbfd
movw -0x50(%rbp), %cx
movq -0x38(%rbp), %rax
movw %cx, (%rax)
movq -0x38(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x38(%rbp)
movb -0x51(%rbp), %al
addb $-0x1, %al
movb %al, -0x51(%rbp)
jmp 0xcbd6
jmp 0xcc26
jmp 0xcc01
movq -0x20(%rbp), %rax
movq %rax, -0x78(%rbp)
cmpq $0x0, %rax
je 0xcc1d
movq -0x78(%rbp), %rdi
movl $0x1, %esi
callq 0x1130
movb $0x0, -0x1(%rbp)
jmp 0xcca9
jmp 0xcc28
movq 0x49c1(%rip), %rax      # 0x115f0
cmpq -0x48(%rbp), %rax
jb 0xcb18
jmp 0xcc3d
jmp 0xcc01
movl -0x30(%rbp), %ecx
movq 0x49a1(%rip), %rax      # 0x115e8
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, 0x4995(%rip)      # 0x115e8
movq -0x48(%rbp), %rax
movq %rax, 0x4992(%rip)      # 0x115f0
movb -0x29(%rbp), %al
addb $-0x1, %al
movb %al, -0x29(%rbp)
jmp 0xc9a2
jmp 0xc97a
movq 0x4971(%rip), %rax      # 0x115e8
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movl %eax, %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, %rax
je 0xcca5
movq -0x80(%rbp), %rdi
movl $0x1, %esi
callq 0x1130
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x80, %rsp
popq %rbp
retq
nopw (%rax,%rax)