// File: mmoanis[P]mpegts_demux/MpegTsDemux.cpp
// Function: MpegTsDemuxer::ReadPAT(unsigned char const*&, unsigned char const*)
bool MpegTsDemuxer::ReadPAT(Packet::const_iterator &p, Packet::const_iterator e)
{
    const uint8_t pointer = *p++;
    p += pointer; // Jump to table at pointer offset

    bool done = false; // Must get at least 1 Program

    // Tables can be repeated.
    while (p < e) {
        const uint8_t id = *p++;
        if (id == MPEGTS_STUFFING_BYTE) {
            if (!done) {
                cerr << "[ERROR]: PKT#" << m_pnum << " Empty PAT packet." << endl;
                return false;
            }
            // we are done, happy return
            return true;
        }
        else if (id == MPEGTS_TABLE_NIL) {
            if (!done) {
                cerr << "[ERROR]: PKT#" << m_pnum << " PAT packet has no associated PSI." << endl;
                return false;
            }
            return true;
        } else if (id != MPEGTS_TABLE_PAS) {
            cerr << "[ERROR]: PKT#" << m_pnum <<" Expected PAT SECTION=" << MPEGTS_TABLE_PAS << " found " << id << endl;
            return false;
        }

        const bool ssi = static_cast<bool> (*p&0x80); // PAT/PMT/CAT == 1
        if (!ssi) {
            cerr << "[ERROR]: PKT#" << m_pnum <<" PAT section syntax indicator not set." << endl;
            return false;
        }

        const bool pb = static_cast<bool> (*p&0x40); // PAT/PMT/CAT == 0
        if (pb) {
            cerr << "[ERROR]: PKT#" << m_pnum << " PAT private bit is set." << endl;
            return false;
        }

        if (((*p&0x30)>>4) != 0x03 ) {
            cerr << "[ERROR]: PKT#" << m_pnum <<" PAT PSI reserved bits not set." << endl;
            return false;
        }

        if (p + 1 >= e) {
            cerr << "[ERROR]: PKT#" << m_pnum << " PAT PSI not enough data." << endl;
            return false;
        }
        const uint16_t slength = uint16_t((p[0]&0x03)<<8) | uint16_t(p[1]);
        p += 2;
        if (p + slength >= e) {
            cerr << "[ERROR]: PKT#" << m_pnum <<" PAT bad section length." << endl;
            return false;
        }

        PacketSection section;
        if (!ReadSection(p, e, section))
            return false;

        // Read PAT, can be repeated
        if (!ReadPrograms(p, e))
            return false;

        // End of the section
        //uint32_t crc = uint32_t(p[0]<<24) | uint32_t(p[1]<<16) | uint32_t(p[2]<<8) | uint32_t(p[3]);
        //cout << "CRC: " << hex << crc << dec << endl;
        p += 4;
        done = true;
    }

    return done;
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movq %rdx, 0x18(%rsp)
movq 0x28(%rsp), %rax
movq %rax, (%rsp)
movq 0x20(%rsp), %rcx
movq (%rcx), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, (%rcx)
movb (%rax), %al
movb %al, 0x17(%rsp)
movzbl 0x17(%rsp), %edx
movq 0x20(%rsp), %rax
movq (%rax), %rcx
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, (%rax)
movb $0x0, 0x16(%rsp)
movq 0x20(%rsp), %rax
movq (%rax), %rax
cmpq 0x18(%rsp), %rax
jae 0x37af
movq 0x20(%rsp), %rcx
movq (%rcx), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, (%rcx)
movb (%rax), %al
movb %al, 0x15(%rsp)
movzbl 0x15(%rsp), %eax
cmpl $0xff, %eax
jne 0x3425
testb $0x1, 0x16(%rsp)
jne 0x341b
movq 0x9c1c(%rip), %rdi      # 0xcff0
leaq 0x5e9b(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5e87(%rip), %rsi      # 0x9284
callq 0x2140
movq %rax, %rdi
movq 0x9bb4(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movb $0x1, 0x37(%rsp)
jmp 0x37b9
movzbl 0x15(%rsp), %eax
cmpl $0xff, %eax
jne 0x3490
testb $0x1, 0x16(%rsp)
jne 0x3486
movq 0x9bb1(%rip), %rdi      # 0xcff0
leaq 0x5e30(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5e2f(%rip), %rsi      # 0x9297
callq 0x2140
movq %rax, %rdi
movq 0x9b49(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movb $0x1, 0x37(%rsp)
jmp 0x37b9
movzbl 0x15(%rsp), %eax
cmpl $0x0, %eax
je 0x350e
movq 0x9b4f(%rip), %rdi      # 0xcff0
leaq 0x5dce(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5df0(%rip), %rsi      # 0x92ba
callq 0x2140
movq %rax, %rdi
xorl %esi, %esi
callq 0x2210
movq %rax, %rdi
leaq 0x5ce0(%rip), %rsi      # 0x91c3
callq 0x2140
movq %rax, %rdi
movzbl 0x15(%rsp), %esi
callq 0x21c0
movq %rax, %rdi
movq 0x9ac1(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
jmp 0x3510
jmp 0x3512
movq 0x20(%rsp), %rax
movq (%rax), %rax
movzbl (%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x14(%rsp)
testb $0x1, 0x14(%rsp)
jne 0x3583
movq 0x9ab4(%rip), %rdi      # 0xcff0
leaq 0x5d33(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5d6c(%rip), %rsi      # 0x92d1
callq 0x2140
movq %rax, %rdi
movq 0x9a4c(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq 0x20(%rsp), %rax
movq (%rax), %rax
movzbl (%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x13(%rsp)
testb $0x1, 0x13(%rsp)
je 0x35f2
movq 0x9a45(%rip), %rdi      # 0xcff0
leaq 0x5cc4(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5d24(%rip), %rsi      # 0x92f8
callq 0x2140
movq %rax, %rdi
movq 0x99dd(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq 0x20(%rsp), %rax
movq (%rax), %rax
movzbl (%rax), %eax
andl $0x30, %eax
sarl $0x4, %eax
cmpl $0x3, %eax
je 0x3656
movq 0x99e1(%rip), %rdi      # 0xcff0
leaq 0x5c60(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5cd9(%rip), %rsi      # 0x9311
callq 0x2140
movq %rax, %rdi
movq 0x9979(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq 0x20(%rsp), %rax
movq (%rax), %rax
addq $0x1, %rax
cmpq 0x18(%rsp), %rax
jb 0x36b7
movq 0x9980(%rip), %rdi      # 0xcff0
leaq 0x5bff(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5c98(%rip), %rsi      # 0x9331
callq 0x2140
movq %rax, %rdi
movq 0x9918(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq 0x20(%rsp), %rax
movq (%rax), %rax
movzbl (%rax), %eax
andl $0x3, %eax
shll $0x8, %eax
movzwl %ax, %eax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movzbl 0x1(%rcx), %ecx
movzwl %cx, %ecx
orl %ecx, %eax
movw %ax, 0x10(%rsp)
movq 0x20(%rsp), %rax
movq (%rax), %rcx
addq $0x2, %rcx
movq %rcx, (%rax)
movq 0x20(%rsp), %rax
movq (%rax), %rax
movzwl 0x10(%rsp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
cmpq 0x18(%rsp), %rax
jb 0x3755
movq 0x98df(%rip), %rdi      # 0xcff0
leaq 0x5b5e(%rip), %rsi      # 0x9276
callq 0x2140
movq %rax, %rdi
movq (%rsp), %rax
movq 0x90(%rax), %rsi
callq 0x2040
movq %rax, %rdi
leaq 0x5c11(%rip), %rsi      # 0x934b
callq 0x2140
movq %rax, %rdi
movq 0x9877(%rip), %rsi      # 0xcfc0
callq 0x2180
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq (%rsp), %rdi
movq 0x20(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0xa(%rsp), %rcx
callq 0x44a0
testb $0x1, %al
jne 0x3778
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq (%rsp), %rdi
movq 0x20(%rsp), %rsi
movq 0x18(%rsp), %rdx
callq 0x4660
testb $0x1, %al
jne 0x3796
movb $0x0, 0x37(%rsp)
jmp 0x37b9
movq 0x20(%rsp), %rax
movq (%rax), %rcx
addq $0x4, %rcx
movq %rcx, (%rax)
movb $0x1, 0x16(%rsp)
jmp 0x338f
movb 0x16(%rsp), %al
andb $0x1, %al
movb %al, 0x37(%rsp)
movb 0x37(%rsp), %al
andb $0x1, %al
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)