// File: RegulusImpact[P]sadboy/src/Graphics/XGPU.cpp
// Function: XGPU::DumpTileset()
void XGPU::DumpTileset() {
    /*

    iterate through vram
    every 16 bytes is am 8x8 tile
    byte pairs read read low then high

    tileRow 0 | byte 0 | byte 1
    tileRow 1 | byte 2 | byte 3
    tileRow 3 | byte 4 | byte 5
    tileRow 3 | byte 6 | byte 7
    tileRow 4 | byte 8 | byte 9
    tileRow 5 | byte A | byte B
    tileRow 6 | byte C | byte D
    tileRow 7 | byte E | byte F

    Row
      byte one (hi)  |   byte two (lo)
        1234 5678    |     ABCD EFGH

    Colors:
    p0 p1 p2 p3 p4 p5 p6 p7
    1A 2B 3C 4D 5E 6F 7G 8G


    */
    uint32_t tileCounter = 0;
    uint16_t tileRow = 0;
    uint16_t tileRowOffset = 0;
    uint16_t maxVRAM = 0x2000;
    uint16_t vramStart = 0x8000;
    // pokemon sprite test
    // FF 00 7E FF      85 81 89 83     93 85 A5 8B    C9 97 7E FF
    // mmu->Write(vramStart, (uint8_t)0xFF);
    // mmu->Write(vramStart+1, (uint8_t)0x00);
    // mmu->Write(vramStart+2, (uint8_t)0x7E);
    // mmu->Write(vramStart+3, (uint8_t)0xFF);

    // mmu->Write(vramStart+4, (uint8_t)0x85);
    // mmu->Write(vramStart+5, (uint8_t)0x81);
    // mmu->Write(vramStart+6, (uint8_t)0x89);
    // mmu->Write(vramStart+7, (uint8_t)0x83);

    // mmu->Write(vramStart+8, (uint8_t)0x93);
    // mmu->Write(vramStart+9, (uint8_t)0x85);
    // mmu->Write(vramStart+10, (uint8_t)0xA5);
    // mmu->Write(vramStart+11, (uint8_t)0x8B);

    // mmu->Write(vramStart+12, (uint8_t)0xC9);
    // mmu->Write(vramStart+13, (uint8_t)0x97);
    // mmu->Write(vramStart+14, (uint8_t)0x7E);
    // mmu->Write(vramStart+15, (uint8_t)0xFF);

    for (uint16_t ii = 0; ii < maxVRAM; ii += 2) {
        // ii iterates through every byte in vram
        // ii % 16 is which byte of the tile we're looking at
        // each time ii % 16 == 0, increment our tile counter
        // we want to read two bytes at a time
        if (0 == ii % 16 && 0 != ii) {
            tileCounter++;
            // we reset tileRow when tileCounter goes up
            tileRow = 0;
        }

        if (16 < tileCounter) {
            tileCounter = 0;
            tileRowOffset++;
        }

        if (tileRowOffset == 3) {
            break;
        }


        // the bytes are in order lo to high
        uint8_t lo = mmu->Read((vramStart + ii));
        uint8_t hi = mmu->Read((vramStart + ii + 1));

        // 1000 0000 >> 6 & 2 == 0000 001x & 2 == 0000 0010
        uint8_t p0 = ((hi >> 6) & 2) | ((lo >> 7) & 1);
        uint8_t p1 = ((hi >> 5) & 2) | ((lo >> 6) & 1);
        uint8_t p2 = ((hi >> 4) & 2) | ((lo >> 5) & 1);
        uint8_t p3 = ((hi >> 3) & 2) | ((lo >> 4) & 1);
        uint8_t p4 = ((hi >> 2) & 2) | ((lo >> 3) & 1);
        uint8_t p5 = ((hi >> 1) & 2) | ((lo >> 2) & 1);
        uint8_t p6 =  (hi &  2)      | ((lo >> 1) & 1);
        uint8_t p7 = ((hi << 1) & 2) |  (lo &  1);

        // mvprintw(tileRow, 50, "%d", p0);
        // mvprintw(tileRow, 51, "%d", p1);
        // mvprintw(tileRow, 52, "%d", p2);
        // mvprintw(tileRow, 53, "%d", p3);
        // mvprintw(tileRow, 54, "%d", p4);
        // mvprintw(tileRow, 55, "%d", p5);
        // mvprintw(tileRow, 56, "%d", p6);
        // mvprintw(tileRow, 57, "%d", p7);

        Draw(mmu->bgp[p0], (tileRowOffset*9)+tileRow, (tileCounter*10)+0);
        Draw(mmu->bgp[p1], (tileRowOffset*9)+tileRow, (tileCounter*10)+1);
        Draw(mmu->bgp[p2], (tileRowOffset*9)+tileRow, (tileCounter*10)+2);
        Draw(mmu->bgp[p3], (tileRowOffset*9)+tileRow, (tileCounter*10)+3);
        Draw(mmu->bgp[p4], (tileRowOffset*9)+tileRow, (tileCounter*10)+4);
        Draw(mmu->bgp[p5], (tileRowOffset*9)+tileRow, (tileCounter*10)+5);
        Draw(mmu->bgp[p6], (tileRowOffset*9)+tileRow, (tileCounter*10)+6);
        Draw(mmu->bgp[p7], (tileRowOffset*9)+tileRow, (tileCounter*10)+7);

        // we've read two bytes for a row, increment
        tileRow++;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movl $0x0, -0xc(%rbp)
movw $0x0, -0xe(%rbp)
movw $0x0, -0x10(%rbp)
movw $0x2000, -0x12(%rbp)    # imm = 0x2000
movw $0x8000, -0x14(%rbp)    # imm = 0x8000
movw $0x0, -0x16(%rbp)
movzwl -0x16(%rbp), %eax
movzwl -0x12(%rbp), %ecx
cmpl %ecx, %eax
jge 0x36027
movzwl -0x16(%rbp), %eax
movl $0x10, %ecx
cltd
idivl %ecx
xorl %eax, %eax
cmpl %edx, %eax
jne 0x35ce4
movzwl -0x16(%rbp), %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x35ce4
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
movw $0x0, -0xe(%rbp)
movl $0x10, %eax
cmpl -0xc(%rbp), %eax
jae 0x35d01
movl $0x0, -0xc(%rbp)
movw -0x10(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x10(%rbp)
movzwl -0x10(%rbp), %eax
cmpl $0x3, %eax
jne 0x35d0f
jmp 0x36027
movq -0x28(%rbp), %rax
movq 0x5a98(%rax), %rdi
movzwl -0x14(%rbp), %eax
movzwl -0x16(%rbp), %ecx
addl %ecx, %eax
movzwl %ax, %esi
callq 0x334c0
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, -0x17(%rbp)
movq 0x5a98(%rax), %rdi
movzwl -0x14(%rbp), %eax
movzwl -0x16(%rbp), %ecx
addl %ecx, %eax
addl $0x1, %eax
movzwl %ax, %esi
callq 0x334c0
movq -0x28(%rbp), %rdi
movb %al, -0x18(%rbp)
movzbl -0x18(%rbp), %eax
sarl $0x6, %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x7, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x19(%rbp)
movzbl -0x18(%rbp), %eax
sarl $0x5, %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x6, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1a(%rbp)
movzbl -0x18(%rbp), %eax
sarl $0x4, %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x5, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1b(%rbp)
movzbl -0x18(%rbp), %eax
sarl $0x3, %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x4, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1c(%rbp)
movzbl -0x18(%rbp), %eax
sarl $0x2, %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x3, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1d(%rbp)
movzbl -0x18(%rbp), %eax
sarl %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl $0x2, %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1e(%rbp)
movzbl -0x18(%rbp), %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
sarl %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x1f(%rbp)
movzbl -0x18(%rbp), %eax
shll %eax
andl $0x2, %eax
movzbl -0x17(%rbp), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movb %al, -0x20(%rbp)
movq 0x5a98(%rdi), %rax
movzbl -0x19(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x0, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1a(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x1, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1b(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x2, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1c(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x3, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1d(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x4, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1e(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x5, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x1f(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x6, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movq -0x28(%rbp), %rdi
movq 0x5a98(%rdi), %rax
movzbl -0x20(%rbp), %ecx
movb 0xe39e(%rax,%rcx), %sil
movzwl -0x10(%rbp), %eax
imull $0x9, %eax, %eax
movzwl -0xe(%rbp), %ecx
addl %ecx, %eax
movb %al, %dl
imull $0xa, -0xc(%rbp), %eax
addl $0x7, %eax
movb %al, %cl
movq (%rdi), %rax
movzbl %sil, %esi
movzbl %dl, %edx
movzbl %cl, %ecx
callq *0x78(%rax)
movw -0xe(%rbp), %ax
addw $0x1, %ax
movw %ax, -0xe(%rbp)
movzwl -0x16(%rbp), %eax
addl $0x2, %eax
movw %ax, -0x16(%rbp)
jmp 0x35ca9
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)