// File: /workspace/github_c_makefile_star2_O2/leiradel[P]zx48k-libretro/src/zx.h
// Function: zx_quickload
bool zx_quickload(zx_t* sys, const uint8_t* ptr, int num_bytes) {
    const uint8_t* end_ptr = ptr + num_bytes;
    if (_zx_overflow(ptr, sizeof(_zx_z80_header), end_ptr)) {
        return false;
    }
    const _zx_z80_header* hdr = (const _zx_z80_header*) ptr;
    ptr += sizeof(_zx_z80_header);
    const _zx_z80_ext_header* ext_hdr = 0;
    uint16_t pc = (hdr->PC_h<<8 | hdr->PC_l) & 0xFFFF;
    const bool is_version1 = 0 != pc;
    if (!is_version1) {
        if (_zx_overflow(ptr, sizeof(_zx_z80_ext_header), end_ptr)) {
            return false;
        }
        ext_hdr = (_zx_z80_ext_header*) ptr;
        int ext_hdr_len = (ext_hdr->len_h<<8)|ext_hdr->len_l;
        ptr += 2 + ext_hdr_len;
        if (ext_hdr->hw_mode < 3) {
            if (sys->type != ZX_TYPE_48K) {
                return false;
            }
        }
        else {
            if (sys->type != ZX_TYPE_128) {
                return false;
            }
        }
    }
    else {
        if (sys->type != ZX_TYPE_48K) {
            return false;
        }
    }
    const bool v1_compr = 0 != (hdr->flags0 & (1<<5));
    while (ptr < end_ptr) {
        int page_index = 0;
        int src_len = 0;
        if (is_version1) {
            src_len = num_bytes - sizeof(_zx_z80_header);
        }
        else {
            _zx_z80_page_header* phdr = (_zx_z80_page_header*) ptr;
            if (_zx_overflow(ptr, sizeof(_zx_z80_page_header), end_ptr)) {
                return false;
            }
            ptr += sizeof(_zx_z80_page_header);
            src_len = (phdr->len_h<<8 | phdr->len_l) & 0xFFFF;
            page_index = phdr->page_nr - 3;
            if ((sys->type == ZX_TYPE_48K) && (page_index == 5)) {
                page_index = 0;
            }
            if ((page_index < 0) || (page_index > 7)) {
                page_index = -1;
            }
        }
        uint8_t* dst_ptr;
        if (-1 == page_index) {
            dst_ptr = sys->junk;
        }
        else {
            dst_ptr = sys->ram[page_index];
        }
        if (0xFFFF == src_len) {
            /* FIXME: uncompressed not supported yet */
            return false;
        }
        else {
            /* compressed */
            int src_pos = 0;
            bool v1_done = false;
            uint8_t val[4];
            while ((src_pos < src_len) && !v1_done) {
                val[0] = ptr[src_pos];
                val[1] = ptr[src_pos+1];
                val[2] = ptr[src_pos+2];
                val[3] = ptr[src_pos+3];
                /* check for version 1 end marker */
                if (v1_compr && (0==val[0]) && (0xED==val[1]) && (0xED==val[2]) && (0==val[3])) {
                    v1_done = true;
                    src_pos += 4;
                }
                else if (0xED == val[0]) {
                    if (0xED == val[1]) {
                        uint8_t count = val[2];
                        CHIPS_ASSERT(0 != count);
                        uint8_t data = val[3];
                        src_pos += 4;
                        for (int i = 0; i < count; i++) {
                            *dst_ptr++ = data;
                        }
                    }
                    else {
                        /* single ED */
                        *dst_ptr++ = val[0];
                        src_pos++;
                    }
                }
                else {
                    /* any value */
                    *dst_ptr++ = val[0];
                    src_pos++;
                }
            }
            CHIPS_ASSERT(src_pos == src_len);
        }
        if (0xFFFF == src_len) {
            ptr += 0x4000;
        }
        else {
            ptr += src_len;
        }
    }

    /* start loaded image */
    z80_reset(&sys->cpu);
    z80_set_a(&sys->cpu, hdr->A); z80_set_f(&sys->cpu, hdr->F);
    z80_set_b(&sys->cpu, hdr->B); z80_set_c(&sys->cpu, hdr->C);
    z80_set_d(&sys->cpu, hdr->D); z80_set_e(&sys->cpu, hdr->E);
    z80_set_h(&sys->cpu, hdr->H); z80_set_l(&sys->cpu, hdr->L);
    z80_set_ix(&sys->cpu, hdr->IX_h<<8|hdr->IX_l);
    z80_set_iy(&sys->cpu, hdr->IY_h<<8|hdr->IY_l);
    z80_set_af_(&sys->cpu, hdr->A_<<8|hdr->F_);
    z80_set_bc_(&sys->cpu, hdr->B_<<8|hdr->C_);
    z80_set_de_(&sys->cpu, hdr->D_<<8|hdr->E_);
    z80_set_hl_(&sys->cpu, hdr->H_<<8|hdr->L_);
    z80_set_sp(&sys->cpu, hdr->SP_h<<8|hdr->SP_l);
    z80_set_i(&sys->cpu, hdr->I);
    z80_set_r(&sys->cpu, (hdr->R & 0x7F) | ((hdr->flags0 & 1)<<7));
    z80_set_iff2(&sys->cpu, hdr->IFF2 != 0);
    z80_set_ei_pending(&sys->cpu, hdr->EI != 0);
    if (hdr->flags1 != 0xFF) {
        z80_set_im(&sys->cpu, hdr->flags1 & 3);
    }
    else {
        z80_set_im(&sys->cpu, 1);
    }
    if (ext_hdr) {
        z80_set_pc(&sys->cpu, ext_hdr->PC_h<<8|ext_hdr->PC_l);
        if (sys->type == ZX_TYPE_128) {
            for (int i = 0; i < 16; i++) {
                /* latch AY-3-8912 register address */
                ay38910_iorq(&sys->ay, AY38910_BDIR|AY38910_BC1|(i<<16));
                /* write AY-3-8912 register value */
                ay38910_iorq(&sys->ay, AY38910_BDIR|(ext_hdr->audio[i]<<16));
            }
        }
        /* simulate an out of port 0xFFFD and 0x7FFD */
        uint64_t pins = Z80_IORQ|Z80_WR;
        Z80_SET_ADDR(pins, 0xFFFD);
        Z80_SET_DATA(pins, ext_hdr->out_fffd);
        _zx_tick(4, pins, sys);
        Z80_SET_ADDR(pins, 0x7FFD);
        Z80_SET_DATA(pins, ext_hdr->out_7ffd);
        _zx_tick(4, pins, sys);
    }
    else {
        z80_set_pc(&sys->cpu, hdr->PC_h<<8|hdr->PC_l);
    }
    sys->border_color = _zx_palette[(hdr->flags0>>1) & 7] & 0xFFD7D7D7;
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
cmpl $0x1e, %edx
jge 0x113b6
xorl %eax, %eax
jmp 0x11813
movl %edx, %r9d
leaq 0x1e(%rsi), %rdx
movzwl 0x6(%rsi), %eax
movw %ax, -0x2a(%rbp)
testw %ax, %ax
je 0x11570
xorl %eax, %eax
cmpl $0x0, 0x1114(%rdi)
jne 0x11813
movq %rdx, %r8
movq %rax, -0x48(%rbp)
movslq %r9d, %rdx
addq %rsi, %rdx
movq %rsi, -0x40(%rbp)
movb 0xc(%rsi), %sil
addl $-0x1e, %r9d
movl %r9d, -0x4c(%rbp)
leaq 0x4230(%rdi), %rax
movq %rax, -0x60(%rbp)
movq %rdi, -0x38(%rbp)
leaq 0x2c230(%rdi), %rax
movq %rax, -0x58(%rbp)
andb $0x20, %sil
shrb $0x5, %sil
cmpq %rdx, %r8
jae 0x115a6
xorl %edi, %edi
cmpw $0x0, -0x2a(%rbp)
je 0x11437
movl -0x4c(%rbp), %r11d
movq %r8, %r10
jmp 0x11470
leaq 0x3(%r8), %r10
cmpq %rdx, %r10
ja 0x113af
movzwl (%r8), %r11d
movzbl 0x2(%r8), %edi
addl $-0x3, %edi
movl %edi, %eax
xorl $0x5, %eax
movq -0x38(%rbp), %rcx
orl 0x1114(%rcx), %eax
movl $0x0, %eax
cmovel %eax, %edi
movq -0x58(%rbp), %r12
cmpl $0x7, %edi
ja 0x1147b
movl %edi, %r12d
shlq $0xe, %r12
addq -0x60(%rbp), %r12
xorl %r15d, %r15d
cmpl $0xffff, %r11d          # imm = 0xFFFF
je 0x113af
xorl %r13d, %r13d
movslq %r15d, %rax
leaq (%r10,%rax), %r15
movl %eax, %r9d
xorl %r8d, %r8d
leal (%r9,%r8), %eax
cmpl %r11d, %eax
jge 0x11553
testb $0x1, %r13b
jne 0x11553
movb (%r15,%r8), %r14b
leal (%r9,%r8), %eax
incl %eax
cltq
movb (%r10,%rax), %al
leal 0x2(%r9,%r8), %edi
movslq %edi, %rdi
movb (%r10,%rdi), %cl
leal 0x3(%r9,%r8), %ebx
movslq %ebx, %rbx
movb (%r10,%rbx), %bl
movl %eax, %r13d
xorb $-0x13, %r13b
orb %r14b, %r13b
movl %ecx, %edi
xorb $-0x13, %dil
orb %r13b, %dil
orb %bl, %dil
sete %r13b
andb %sil, %r13b
cmpb $0x1, %r13b
jne 0x11503
addq $0x4, %r8
jmp 0x1149b
leaq (%r9,%r8), %r15
incq %r15
cmpb $-0x13, %r14b
jne 0x1152d
cmpb $-0x13, %al
jne 0x11539
movzbl %cl, %eax
testl %eax, %eax
je 0x11841
subl $0x1, %eax
jb 0x11546
movb %bl, (%r12)
incq %r12
jmp 0x1151f
movb %r14b, (%r12)
incq %r12
jmp 0x1148e
movb $-0x13, (%r12)
incq %r12
jmp 0x1148e
leal (%r9,%r8), %r15d
addl $0x4, %r15d
jmp 0x1148e
movl %r11d, %eax
subl %r9d, %eax
cmpl %r8d, %eax
jne 0x11822
movslq %r11d, %rax
addq %rax, %r10
movq %r10, %r8
jmp 0x1141c
cmpl $0x56, %r9d
jb 0x113af
movzwl 0x1e(%rsi), %ecx
leaq (%rdx,%rcx), %r8
addq $0x2, %r8
cmpb $0x2, 0x22(%rsi)
movl 0x1114(%rdi), %ecx
movq %rdx, %rax
ja 0x116fd
testl %ecx, %ecx
jne 0x113af
jmp 0x113e0
movabsq $-0xffff0001, %r12      # imm = 0xFFFFFFFF0000FFFF
movabsq $0xffffffffffff, %r13   # imm = 0xFFFFFFFFFFFF
movq -0x38(%rbp), %rbx
movq %rbx, %rdi
callq 0x3080
movq -0x40(%rbp), %rdi
movzwl (%rdi), %eax
movzbl 0x3(%rdi), %ecx
shlq $0x38, %rcx
orq %rax, %rcx
movzbl 0x2(%rdi), %eax
shlq $0x30, %rax
orq %rcx, %rax
movzbl 0xe(%rdi), %ecx
shlq $0x28, %rcx
orq %rax, %rcx
movzbl 0xd(%rdi), %eax
shlq $0x20, %rax
orq %rcx, %rax
movzbl 0x5(%rdi), %ecx
shll $0x18, %ecx
orq %rax, %rcx
movzbl 0x4(%rdi), %eax
shll $0x10, %eax
orq %rcx, %rax
movq %rax, 0x8(%rbx)
movzwl 0x19(%rdi), %edx
shlq $0x20, %rdx
movabsq $-0xffff00000001, %rax  # imm = 0xFFFF0000FFFFFFFF
movq 0x18(%rbx), %rcx
andq %rax, %rcx
orq %rdx, %rcx
movq %rcx, 0x18(%rbx)
movzwl 0x17(%rdi), %edx
shll $0x10, %edx
andq %r12, %rcx
orq %rdx, %rcx
movq %rcx, 0x18(%rbx)
movq 0x10(%rbx), %rdx
movw 0x15(%rdi), %dx
movq %rdx, 0x10(%rbx)
movzwl 0xf(%rdi), %esi
shlq $0x30, %rsi
andq %r13, %rdx
orq %rsi, %rdx
movq %rdx, 0x10(%rbx)
movzwl 0x11(%rdi), %esi
shlq $0x20, %rsi
andq %rax, %rdx
orq %rsi, %rdx
movq %rdx, 0x10(%rbx)
movzwl 0x13(%rdi), %esi
shll $0x10, %esi
andq %r12, %rdx
orq %rsi, %rdx
movq %rdx, 0x10(%rbx)
movw 0x8(%rdi), %cx
movq %rcx, 0x18(%rbx)
movzbl 0xa(%rdi), %ecx
addq $-0x18, %rax
andq 0x20(%rbx), %rax
shlq $0x28, %rcx
orq %rax, %rcx
movzbl 0xb(%rdi), %edx
andl $0x7f, %edx
movb 0xc(%rdi), %al
movl %eax, %esi
shlb $0x7, %sil
movzbl %sil, %esi
orl %edx, %esi
shlq $0x20, %rsi
orq %rcx, %rsi
xorl %ecx, %ecx
cmpb $0x0, 0x1c(%rdi)
setne %cl
leaq (%rsi,%rcx,8), %rcx
xorl %edx, %edx
cmpb $0x0, 0x1b(%rdi)
setne %dl
shll $0x4, %edx
orq %rcx, %rdx
movzbl 0x1d(%rdi), %ecx
cmpq $0xff, %rcx
je 0x1170b
andl $0x3, %ecx
movabsq $-0xff000000000001, %rsi # imm = 0xFF00FFFFFFFFFFFF
andq %rsi, %rdx
shlq $0x30, %rcx
orq %rdx, %rcx
jmp 0x1171f
cmpl $0x1, %ecx
jne 0x113af
jmp 0x113e0
movabsq $-0xff000000000001, %rcx # imm = 0xFF00FFFFFFFFFFFF
andq %rcx, %rdx
leaq (%rdx,%r13), %rcx
incq %rcx
movq -0x38(%rbp), %rsi
movq %rcx, 0x20(%rsi)
movq -0x48(%rbp), %rdx
testq %rdx, %rdx
je 0x117e0
movzwl 0x2(%rdx), %eax
shll $0x10, %eax
andq %r12, %rcx
orq %rax, %rcx
movq %rcx, 0x20(%rsi)
cmpl $0x1, 0x1114(%rsi)
jne 0x11797
leaq 0x870(%rsi), %r12
movabsq $0x30000000000, %r13    # imm = 0x30000000000
xorl %ebx, %ebx
cmpq $0x10, %rbx
je 0x11797
movq %r12, %rdi
movq %r13, %rsi
callq 0x30b0
movq -0x48(%rbp), %rax
movzbl 0x9(%rax,%rbx), %esi
shll $0x10, %esi
btsq $0x28, %rsi
movq %r12, %rdi
callq 0x30b0
incq %rbx
addq $0x10000, %r13          # imm = 0x10000
jmp 0x11761
movq -0x48(%rbp), %rbx
movzbl 0x8(%rbx), %esi
shll $0x10, %esi
orq $0x1400fffd, %rsi       # imm = 0x1400FFFD
pushq $0x4
popq %r12
movl %r12d, %edi
movq -0x38(%rbp), %rdx
callq 0x107d8
movzbl 0x5(%rbx), %esi
shll $0x10, %esi
orq $0x14007ffd, %rsi       # imm = 0x14007FFD
movl %r12d, %edi
movq -0x38(%rbp), %rdx
callq 0x107d8
movq -0x38(%rbp), %rsi
movq -0x40(%rbp), %rax
movb 0xc(%rax), %al
jmp 0x117f5
movq -0x40(%rbp), %rdx
movzwl 0x6(%rdx), %edx
shll $0x10, %edx
andq %r12, %rcx
orq %rdx, %rcx
movq %rcx, 0x20(%rsi)
shrb %al
andb $0x7, %al
movzbl %al, %eax
leaq 0x2ded(%rip), %rcx      # 0x145f0
movl $0xffd7d7d7, %edx       # imm = 0xFFD7D7D7
andl (%rcx,%rax,4), %edx
movl %edx, 0x1140(%rsi)
movb $0x1, %al
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2bcd(%rip), %rdi      # 0x143f6
leaq 0x293a(%rip), %rsi      # 0x1416a
leaq 0x2b8e(%rip), %rcx      # 0x143c5
movl $0x3b4, %edx            # imm = 0x3B4
callq 0x30d0
leaq 0x2b72(%rip), %rdi      # 0x143ba
leaq 0x291b(%rip), %rsi      # 0x1416a
leaq 0x2b6f(%rip), %rcx      # 0x143c5
movl $0x3a1, %edx            # imm = 0x3A1
callq 0x30d0