// File: /workspace/github_c_makefile_star2_O0/leiradel[P]zx48k-libretro/src/zx.h
// Function: zx_decode_scanline
static bool _zx_decode_scanline(zx_t* sys) {
    /* this is called by the timer callback for every PAL line, controlling
        the vidmem decoding and vblank interrupt

        detailed information about frame timings is here:
        for 48K:    http://rk.nvg.ntnu.no/sinclair/faq/tech_48.html#48K
        for 128K:   http://rk.nvg.ntnu.no/sinclair/faq/tech_128.html

        one PAL line takes 224 T-states on 48K, and 228 T-states on 128K
        one PAL frame is 312 lines on 48K, and 311 lines on 128K

        decode the next videomem line into the emulator framebuffer,
        the border area of a real Spectrum is bigger than the emulator
        (the emu has 32 pixels border on each side, the hardware has:

        63 or 64 lines top border
        56 border lines bottom border
        48 pixels on each side horizontal border
    */
    const int top_decode_line = sys->top_border_scanlines - 32;
    const int btm_decode_line = sys->top_border_scanlines + 192 + 32;
    if ((sys->scanline_y >= top_decode_line) && (sys->scanline_y < btm_decode_line)) {
        const uint16_t y = sys->scanline_y - top_decode_line;
        uint32_t* dst = &sys->pixel_buffer[y * _ZX_DISPLAY_WIDTH];
        const uint8_t* vidmem_bank = sys->ram[sys->display_ram_bank];
        const bool blink = 0 != (sys->blink_counter & 0x10);
        uint32_t fg, bg;
        if ((y < 32) || (y >= 224)) {
            /* upper/lower border */
            for (int x = 0; x < _ZX_DISPLAY_WIDTH; x++) {
                *dst++ = sys->border_color;
            }
        }
        else {
            /* compute video memory Y offset (inside 256x192 area)
                this is how the 16-bit video memory address is computed
                from X and Y coordinates:
                | 0| 1| 0|Y7|Y6|Y2|Y1|Y0|Y5|Y4|Y3|X4|X3|X2|X1|X0|
            */
            const uint16_t yy = y-32;
            const uint16_t y_offset = ((yy & 0xC0)<<5) | ((yy & 0x07)<<8) | ((yy & 0x38)<<2);

            /* left border */
            for (int x = 0; x < (4*8); x++) {
                *dst++ = sys->border_color;
            }

            /* valid 256x192 vidmem area */
            for (uint16_t x = 0; x < 32; x++) {
                const uint16_t pix_offset = y_offset | x;
                const uint16_t clr_offset = 0x1800 + (((yy & ~0x7)<<2) | x);

                /* pixel mask and color attribute bytes */
                const uint8_t pix = vidmem_bank[pix_offset];
                const uint8_t clr = vidmem_bank[clr_offset];

                /* foreground and background color */
                if ((clr & (1<<7)) && blink) {
                    fg = _zx_palette[(clr>>3) & 7];
                    bg = _zx_palette[clr & 7];
                }
                else {
                    fg = _zx_palette[clr & 7];
                    bg = _zx_palette[(clr>>3) & 7];
                }
                if (0 == (clr & (1<<6))) {
                    // standard brightness
                    fg &= 0xFFD7D7D7;
                    bg &= 0xFFD7D7D7;
                }
                for (int px = 7; px >=0; px--) {
                    *dst++ = pix & (1<<px) ? fg : bg;
                }
            }

            /* right border */
            for (int x = 0; x < (4*8); x++) {
                *dst++ = sys->border_color;
            }
        }
    }

    if (sys->scanline_y++ >= sys->frame_scan_lines) {
        /* start new frame, request vblank interrupt */
        sys->scanline_y = 0;
        sys->blink_counter++;
        return true;
    }
    else {
        return false;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0x112c(%rax), %eax
subl $0x20, %eax
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movl 0x112c(%rax), %eax
addl $0xc0, %eax
addl $0x20, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movl 0x1138(%rax), %eax
cmpl -0x14(%rbp), %eax
jl 0x23541
movq -0x10(%rbp), %rax
movl 0x1138(%rax), %eax
cmpl -0x18(%rbp), %eax
jge 0x23541
movq -0x10(%rbp), %rax
movl 0x1138(%rax), %eax
subl -0x14(%rbp), %eax
movw %ax, -0x1a(%rbp)
movq -0x10(%rbp), %rax
movq 0x3210(%rax), %rax
movzwl -0x1a(%rbp), %ecx
imull $0x140, %ecx, %ecx      # imm = 0x140
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x4230, %rax           # imm = 0x4230
movq -0x10(%rbp), %rcx
movl 0x113c(%rcx), %ecx
shlq $0xe, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x1126(%rax), %ecx
andl $0x10, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
setne %al
andb $0x1, %al
movb %al, -0x31(%rbp)
movzwl -0x1a(%rbp), %eax
cmpl $0x20, %eax
jl 0x23314
movzwl -0x1a(%rbp), %eax
cmpl $0xe0, %eax
jl 0x2334f
movl $0x0, -0x40(%rbp)
cmpl $0x140, -0x40(%rbp)     # imm = 0x140
jge 0x2334a
movq -0x10(%rbp), %rax
movl 0x1140(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2331b
jmp 0x2353f
movzwl -0x1a(%rbp), %eax
subl $0x20, %eax
movw %ax, -0x42(%rbp)
movzwl -0x42(%rbp), %eax
andl $0xc0, %eax
shll $0x5, %eax
movzwl -0x42(%rbp), %ecx
andl $0x7, %ecx
shll $0x8, %ecx
orl %ecx, %eax
movzwl -0x42(%rbp), %ecx
andl $0x38, %ecx
shll $0x2, %ecx
orl %ecx, %eax
movw %ax, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
cmpl $0x20, -0x48(%rbp)
jge 0x233b5
movq -0x10(%rbp), %rax
movl 0x1140(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x23389
movw $0x0, -0x4a(%rbp)
movzwl -0x4a(%rbp), %eax
cmpl $0x20, %eax
jge 0x2350a
movzwl -0x44(%rbp), %eax
movzwl -0x4a(%rbp), %ecx
orl %ecx, %eax
movw %ax, -0x4c(%rbp)
movzwl -0x42(%rbp), %eax
andl $-0x8, %eax
shll $0x2, %eax
movzwl -0x4a(%rbp), %ecx
orl %ecx, %eax
addl $0x1800, %eax           # imm = 0x1800
movw %ax, -0x4e(%rbp)
movq -0x30(%rbp), %rax
movzwl -0x4c(%rbp), %ecx
movb (%rax,%rcx), %al
movb %al, -0x4f(%rbp)
movq -0x30(%rbp), %rax
movzwl -0x4e(%rbp), %ecx
movb (%rax,%rcx), %al
movb %al, -0x50(%rbp)
movzbl -0x50(%rbp), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x23452
testb $0x1, -0x31(%rbp)
je 0x23452
movzbl -0x50(%rbp), %eax
sarl $0x3, %eax
andl $0x7, %eax
movslq %eax, %rcx
leaq 0x5f9d(%rip), %rax      # 0x293d0
movl (%rax,%rcx,4), %eax
movl %eax, -0x38(%rbp)
movzbl -0x50(%rbp), %eax
andl $0x7, %eax
movslq %eax, %rcx
leaq 0x5f86(%rip), %rax      # 0x293d0
movl (%rax,%rcx,4), %eax
movl %eax, -0x3c(%rbp)
jmp 0x23483
movzbl -0x50(%rbp), %eax
andl $0x7, %eax
movslq %eax, %rcx
leaq 0x5f6d(%rip), %rax      # 0x293d0
movl (%rax,%rcx,4), %eax
movl %eax, -0x38(%rbp)
movzbl -0x50(%rbp), %eax
sarl $0x3, %eax
andl $0x7, %eax
movslq %eax, %rcx
leaq 0x5f53(%rip), %rax      # 0x293d0
movl (%rax,%rcx,4), %eax
movl %eax, -0x3c(%rbp)
movzbl -0x50(%rbp), %ecx
andl $0x40, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0x234a6
movl -0x38(%rbp), %eax
andl $0xffd7d7d7, %eax       # imm = 0xFFD7D7D7
movl %eax, -0x38(%rbp)
movl -0x3c(%rbp), %eax
andl $0xffd7d7d7, %eax       # imm = 0xFFD7D7D7
movl %eax, -0x3c(%rbp)
movl $0x7, -0x54(%rbp)
cmpl $0x0, -0x54(%rbp)
jl 0x234f7
movzbl -0x4f(%rbp), %eax
movl -0x54(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x234d2
movl -0x38(%rbp), %eax
movl %eax, -0x5c(%rbp)
jmp 0x234d8
movl -0x3c(%rbp), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
movl -0x54(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x234ad
jmp 0x234f9
movw -0x4a(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x4a(%rbp)
jmp 0x233bb
movl $0x0, -0x58(%rbp)
cmpl $0x20, -0x58(%rbp)
jge 0x2353d
movq -0x10(%rbp), %rax
movl 0x1140(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x23511
jmp 0x2353f
jmp 0x23541
movq -0x10(%rbp), %rcx
movl 0x1138(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x1138(%rcx)
movq -0x10(%rbp), %rcx
cmpl 0x1128(%rcx), %eax
jl 0x23589
movq -0x10(%rbp), %rax
movl $0x0, 0x1138(%rax)
movq -0x10(%rbp), %rax
movb 0x1126(%rax), %cl
addb $0x1, %cl
movb %cl, 0x1126(%rax)
movb $0x1, -0x1(%rbp)
jmp 0x2358d
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
popq %rbp
retq
nopw %cs:(%rax,%rax)