// File: /workspace/github_c_makefile_star2_O2/leiradel[P]zx48k-libretro/src/zx.h
// Function: zx_tick
static uint64_t _zx_tick(int num_ticks, uint64_t pins, void* user_data) {
    zx_t* sys = (zx_t*) user_data;
    /* video decoding and vblank interrupt */
    sys->scanline_counter -= num_ticks;
    if (sys->scanline_counter <= 0) {
        sys->scanline_counter += sys->scanline_period;
        /* decode next video scanline */
        if (_zx_decode_scanline(sys)) {
            /* request vblank interrupt */
            pins |= Z80_INT;
        }
    }

    /* tick audio systems */
    for (int i = 0; i < num_ticks; i++) {
        sys->tick_count++;
        bool sample_ready = beeper_tick(&sys->beeper);
        /* the AY-3-8912 chip runs at half CPU frequency */
        if (sys->type == ZX_TYPE_128) {
            if (sys->tick_count & 1) {
                ay38910_tick(&sys->ay);
            }
        }
        if (sample_ready) {
            float sample = sys->beeper.sample;
            if (sys->type == ZX_TYPE_128) {
                sample += sys->ay.sample;
            }
            sys->sample_buffer[sys->sample_pos++] = sample;
            if (sys->sample_pos == sys->num_samples) {
                if (sys->audio_cb) {
                    sys->audio_cb(sys->sample_buffer, sys->num_samples, sys->user_data);
                }
                sys->sample_pos = 0;
            }
        }
    }

    /* memory and IO requests */
    if (pins & Z80_MREQ) {
        /* a memory request machine cycle
            FIXME: 'contended memory' accesses should inject wait states
        */
        const uint16_t addr = Z80_GET_ADDR(pins);
        if (pins & Z80_RD) {
            Z80_SET_DATA(pins, mem_rd(&sys->mem, addr));
        }
        else if (pins & Z80_WR) {
            mem_wr(&sys->mem, addr, Z80_GET_DATA(pins));
        }
    }
    else if (pins & Z80_IORQ) {
        /* an IO request machine cycle
            see http://problemkaputt.de/zxdocs.htm#zxspectrum for address decoding
        */
        if (pins & Z80_RD) {
            /* an IO read
                FIXME: reading from port xxFF should return 'current VRAM data'
            */
            if ((pins & Z80_A0) == 0) {
                /* Spectrum ULA (...............0)
                    Bits 5 and 7 as read by INning from Port 0xfe are always one
                */
                uint8_t data = (1<<7)|(1<<5);
                /* MIC/EAR flags -> bit 6 */
                if (sys->last_fe_out & (1<<3|1<<4)) {
                    data |= (1<<6);
                }
                /* keyboard matrix bits are encoded in the upper 8 bit of the port address */
                uint16_t column_mask = (~(Z80_GET_ADDR(pins)>>8)) & 0x00FF;
                const uint16_t kbd_lines = kbd_test_lines(&sys->kbd, column_mask);
                data |= (~kbd_lines) & 0x1F;
                Z80_SET_DATA(pins, data);
            }
            else if ((pins & (Z80_A7|Z80_A6|Z80_A5)) == 0) {
                /* Kempston Joystick (........000.....) */
                Z80_SET_DATA(pins, sys->kbd_joymask | sys->joy_joymask);
            }
            else if (sys->type == ZX_TYPE_128){
                /* read from AY-3-8912 (11............0.) */
                if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == (Z80_A15|Z80_A14)) {
                    pins = ay38910_iorq(&sys->ay, AY38910_BC1|pins) & Z80_PIN_MASK;
                }
            }
        }
        else if (pins & Z80_WR) {
            // an IO write
            const uint8_t data = Z80_GET_DATA(pins);
            if ((pins & Z80_A0) == 0) {
                /* Spectrum ULA (...............0)
                    "every even IO port addresses the ULA but to avoid
                    problems with other I/O devices, only FE should be used"
                    FIXME:
                        bit 3: MIC output (CAS SAVE, 0=On, 1=Off)
                */
                sys->border_color = _zx_palette[data & 7] & 0xFFD7D7D7;
                sys->last_fe_out = data;
                beeper_set(&sys->beeper, 0 != (data & (1<<4)));
            }
            else if (sys->type == ZX_TYPE_128) {
                /* Spectrum 128 memory control (0.............0.)
                    http://8bit.yarek.pl/computer/zx.128/
                */
                if ((pins & (Z80_A15|Z80_A1)) == 0) {
                    if (!sys->memory_paging_disabled) {
                        sys->last_mem_config = data;
                        /* bit 3 defines the video scanout memory bank (5 or 7) */
                        sys->display_ram_bank = (data & (1<<3)) ? 7 : 5;
                        /* only last memory bank is mappable */
                        mem_map_ram(&sys->mem, 0, 0xC000, 0x4000, sys->ram[data & 0x7]);

                        /* ROM0 or ROM1 */
                        if (data & (1<<4)) {
                            /* bit 4 set: ROM1 */
                            mem_map_rom(&sys->mem, 0, 0x0000, 0x4000, sys->rom[1]);
                        }
                        else {
                            /* bit 4 clear: ROM0 */
                            mem_map_rom(&sys->mem, 0, 0x0000, 0x4000, sys->rom[0]);
                        }
                    }
                    if (data & (1<<5)) {
                        /* bit 5 prevents further changes to memory pages
                            until computer is reset, this is used when switching
                            to the 48k ROM
                        */
                        sys->memory_paging_disabled = true;
                    }
                }
                else if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == (Z80_A15|Z80_A14)) {
                    /* select AY-3-8912 register (11............0.) */
                    ay38910_iorq(&sys->ay, AY38910_BDIR|AY38910_BC1|pins);
                }
                else if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == Z80_A15) {
                    /* write to AY-3-8912 (10............0.) */
                    ay38910_iorq(&sys->ay, AY38910_BDIR|pins);
                }
            }
        }
    }
    return pins;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, %r14
movl 0x1134(%rdx), %eax
subl %edi, %eax
movl %eax, 0x1134(%rdx)
jg 0x109f6
addl 0x1130(%r14), %eax
movl %eax, 0x1134(%r14)
movl 0x112c(%r14), %eax
movl 0x1138(%r14), %ecx
leal -0x20(%rax), %edx
movl %ecx, %r9d
subl %edx, %r9d
setge %dl
addl $0xe0, %eax
cmpl %eax, %ecx
setl %al
andb %dl, %al
cmpb $0x1, %al
jne 0x109bb
movzwl %r9w, %ecx
imull $0x500, %ecx, %eax      # imm = 0x500
addq 0x3210(%r14), %rax
addl $0xffffff20, %ecx       # imm = 0xFFFFFF20
cmpl $0xffffff3f, %ecx       # imm = 0xFFFFFF3F
ja 0x10878
xorl %ecx, %ecx
cmpl $0x140, %ecx            # imm = 0x140
je 0x109bb
movl 0x1140(%r14), %edx
movl %edx, (%rax,%rcx,4)
incq %rcx
jmp 0x1085d
movl %edi, -0x3c(%rbp)
movq %rsi, -0x30(%rbp)
movl 0x113c(%r14), %ecx
shlq $0xe, %rcx
addq %r14, %rcx
addq $0x4230, %rcx           # imm = 0x4230
movb 0x1126(%r14), %dl
movb %dl, -0x38(%rbp)
leal 0xffe0(%r9), %esi
movl %r9d, %r8d
shll $0x8, %r9d
leal 0x3ff80(,%r8,4), %r11d
xorl %r10d, %r10d
cmpl $0x80, %r10d
je 0x108d1
movl 0x1140(%r14), %r8d
movl %r8d, (%rax,%r10)
addq $0x4, %r10
jmp 0x108b7
movl %esi, %r8d
shll $0x5, %r8d
andl $0x700, %r9d            # imm = 0x700
andl $0xe0, %r11d
movl $0x1800, %ebx           # imm = 0x1800
andl %ebx, %r8d
orl %r9d, %r8d
orl %r11d, %r8d
shll $0x2, %esi
addl %ebx, %esi
andl $0xffe0, %esi           # imm = 0xFFE0
addq %r10, %rax
xorl %r9d, %r9d
leaq 0x3ce4(%rip), %r10      # 0x145f0
movl $0xffd7d7d7, %r11d      # imm = 0xFFD7D7D7
cmpq $0x20, %r9
je 0x1099e
testb $0x10, -0x38(%rbp)
sete %bl
movq %r9, %r15
orq %r8, %r15
movq %r9, %r12
orq %rsi, %r12
movzbl (%rcx,%r12), %edx
testb %dl, %dl
setns %r12b
orb %bl, %r12b
movl %edx, %ebx
shrl $0x3, %ebx
testb %r12b, %r12b
movl %edx, %r12d
cmovnel %ebx, %r12d
cmovnel %edx, %ebx
andl $0x7, %ebx
movl (%r10,%rbx,4), %ebx
andl $0x7, %r12d
movl (%r10,%r12,4), %edi
movl %ebx, %r12d
andl %r11d, %r12d
movl %edi, %r13d
andl %r11d, %r13d
testb $0x40, %dl
cmovnel %edi, %r13d
movzbl (%rcx,%r15), %r15d
cmovnel %ebx, %r12d
pushq $0x7
popq %rbx
testl %ebx, %ebx
js 0x10996
btl %ebx, %r15d
movl %r12d, %edx
cmovael %r13d, %edx
movl %edx, (%rax)
addq $0x4, %rax
decl %ebx
jmp 0x1097d
incq %r9
jmp 0x10912
xorl %ecx, %ecx
movq -0x30(%rbp), %rsi
movl -0x3c(%rbp), %edi
cmpl $0x20, %ecx
je 0x109bb
movl 0x1140(%r14), %edx
movl %edx, (%rax,%rcx,4)
incq %rcx
jmp 0x109a7
movl 0x1128(%r14), %eax
movl 0x1138(%r14), %ecx
leal 0x1(%rcx), %edx
movl %edx, 0x1138(%r14)
cmpl %eax, %ecx
jl 0x109e6
andl $0x0, 0x1138(%r14)
incb 0x1126(%r14)
movq %rsi, %rdx
orq $0x40000000, %rdx       # imm = 0x40000000
cmpl %eax, %ecx
cmovgeq %rdx, %rsi
movq %rsi, -0x30(%rbp)
leaq 0x50(%r14), %r12
leaq 0x870(%r14), %rax
movq %rax, -0x38(%rbp)
leaq 0x3230(%r14), %r13
xorl %r15d, %r15d
testl %edi, %edi
cmovgl %edi, %r15d
subl $0x1, %r15d
jb 0x10ab7
incl 0x1120(%r14)
movq %r12, %rdi
callq 0x31b0
movl %eax, %ebx
cmpl $0x1, 0x1114(%r14)
jne 0x10a51
testb $0x1, 0x1120(%r14)
je 0x10a51
movq -0x38(%rbp), %rdi
callq 0x30f0
testb %bl, %bl
je 0x10a19
movss 0x60(%r14), %xmm0
cmpl $0x1, 0x1114(%r14)
jne 0x10a6e
addss 0x904(%r14), %xmm0
movslq 0x322c(%r14), %rax
leal 0x1(%rax), %esi
movl %esi, 0x322c(%r14)
movss %xmm0, 0x3230(%r14,%rax,4)
cmpl 0x3228(%r14), %esi
jne 0x10a19
movq 0x3220(%r14), %rax
testq %rax, %rax
je 0x10aaa
movq 0x3218(%r14), %rdx
movq %r13, %rdi
callq *%rax
andl $0x0, 0x322c(%r14)
jmp 0x10a19
movq -0x30(%rbp), %rsi
btl $0x19, %esi
jb 0x10b21
btl $0x1a, %esi
jae 0x10b7e
btl $0x1b, %esi
jb 0x10b90
btl $0x1c, %esi
jae 0x10b7e
movq %rsi, %r15
shrq $0x10, %r15
testb $0x1, %sil
jne 0x10c24
movl %r15d, %eax
andl $0x7, %eax
leaq 0x3af3(%rip), %rcx      # 0x145f0
movl $0xffd7d7d7, %edx       # imm = 0xFFD7D7D7
andl (%rcx,%rax,4), %edx
movl %edx, 0x1140(%r14)
movb %r15b, 0x1125(%r14)
movl %esi, %eax
shrl $0x14, %eax
andl $0x1, %eax
movl %eax, 0x50(%r14)
jmp 0x10b7e
btl $0x1b, %esi
jb 0x10b52
btl $0x1c, %esi
jae 0x10b7e
movl %esi, %eax
shrl $0x10, %eax
movl %esi, %ecx
shrl $0x6, %ecx
andl $0x3f0, %ecx            # imm = 0x3F0
movq 0x2618(%r14,%rcx), %rcx
movl %esi, %edx
andl $0x3ff, %edx            # imm = 0x3FF
movb %al, (%rcx,%rdx)
jmp 0x10b7e
movq %rsi, %rax
andq $-0xff0001, %rax        # imm = 0xFF00FFFF
movl %esi, %ecx
shrl $0x6, %ecx
andl $0x3f0, %ecx            # imm = 0x3F0
movq 0x2610(%r14,%rcx), %rcx
andl $0x3ff, %esi            # imm = 0x3FF
movzbl (%rcx,%rsi), %esi
shll $0x10, %esi
orq %rax, %rsi
movq %rsi, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb $0x1, %sil
jne 0x10be2
xorl %ebx, %ebx
testb $0x18, 0x1125(%r14)
setne %bl
movl %esi, %eax
notl %eax
movzbl %ah, %esi
addq $0x1158, %r14           # imm = 0x1158
movq %r14, %rdi
callq 0x3200
movq -0x30(%rbp), %rsi
andl $0x1f, %eax
shll $0x10, %eax
shll $0x16, %ebx
orl %eax, %ebx
andq $-0x2ff0002, %rsi       # imm = 0xFD00FFFE
addq %rbx, %rsi
addq $0xa00000, %rsi         # imm = 0xA00000
xorq $0x1f0000, %rsi         # imm = 0x1F0000
jmp 0x10b7e
testb $-0x20, %sil
je 0x10c65
movl %esi, %eax
andl $0xc002, %eax           # imm = 0xC002
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x10b7e
cmpl $0x1, 0x1114(%r14)
jne 0x10b7e
btsq $0x29, %rsi
movq -0x38(%rbp), %rdi
callq 0x30b0
movabsq $0xffffffffff, %rsi     # imm = 0xFFFFFFFFFF
andq %rax, %rsi
jmp 0x10b7e
cmpl $0x1, 0x1114(%r14)
jne 0x10b7e
testw $0x8002, %si            # imm = 0x8002
je 0x10c85
movl %esi, %eax
andl $0xc002, %eax           # imm = 0xC002
movl %eax, %ecx
negw %cx
jo 0x10d17
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x10b7e
movabsq $0x30000000000, %rsi    # imm = 0x30000000000
jmp 0x10d24
movb 0x111e(%r14), %al
orb 0x111d(%r14), %al
andq $-0x2ff00e1, %rsi       # imm = 0xFD00FF1F
movzbl %al, %eax
shll $0x10, %eax
jmp 0x10b7b
cmpb $0x0, 0x111c(%r14)
jne 0x10d00
movb %r15b, 0x1124(%r14)
movl %r15d, %eax
andl $0x8, %eax
shrl $0x2, %eax
orl $0x5, %eax
movl %eax, 0x113c(%r14)
leaq 0x1610(%r14), %rbx
movl %r15d, %eax
andl $0x7, %eax
shll $0xe, %eax
leaq (%r14,%rax), %r8
addq $0x4230, %r8            # imm = 0x4230
movq %rbx, %rdi
xorl %esi, %esi
movl $0xc000, %edx           # imm = 0xC000
movl $0x4000, %ecx           # imm = 0x4000
callq 0x31d0
andl $0x10, %r15d
shll $0xa, %r15d
leaq (%r15,%r14), %r8
addq $0x24230, %r8           # imm = 0x24230
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x4000, %ecx           # imm = 0x4000
callq 0x3050
movq -0x30(%rbp), %rsi
btl $0x15, %esi
jae 0x10b7e
movb $0x1, 0x111c(%r14)
jmp 0x10b7e
movabsq $0xffffffffff, %rsi     # imm = 0xFFFFFFFFFF
incq %rsi
orq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdi
callq 0x30b0
movq -0x30(%rbp), %rsi
jmp 0x10b7e