.syntax unified
.cpu arm7tdmi
.arm
.equ VRAM, 0x06000000
.equ VCOUNT, 0x04000006
.equ KEYINPUT, 0x04000130
.section .header, "ax"
.global _start
_start:
    b boot
    .space 188
.section .text
boot:
    msr cpsr_c, #0xdf
    ldr sp, =0x03007f00
    ldr r0, =0x04000000
    ldr r1, =0x0483
    strh r1, [r0]
    ldr r0, =__bss_start
    ldr r1, =__bss_end
    mov r2, #0
clear_bss:
    cmp r0, r1
    strlo r2, [r0], #4
    blo clear_bss
    mov r0, #0
    mov r1, #0
    mov r2, #240
    mov r3, #160
    mov r4, #0
    bl fill_rect
    ldr r0, =hero_x
    mov r1, #16
    str r1, [r0]
    ldr r0, =hero_y
    str r1, [r0]
    ldr r0, =0x04000000
    ldr r1, =0x0403
    strh r1, [r0]
@ snippet: moving-loop
main_loop:
    bl wait_vblank
    bl tick
    bl read_keys
    mov r4, #0
    bl paint_hero
    bl update_position
    ldr r4, =0x7fff
    bl paint_hero
    b main_loop
@ end: moving-loop

@ snippet: clock
wait_vblank:
    ldr r0, =VCOUNT
leave_vblank:
    ldrh r1, [r0]
    cmp r1, #160
    bhs leave_vblank
enter_vblank:
    ldrh r1, [r0]
    cmp r1, #160
    blo enter_vblank
    bx lr

tick:
    ldr r0, =frame_tick
    ldr r1, [r0]
    add r1, r1, #1
    str r1, [r0]
    bx lr
@ end: clock
@ snippet: input
read_keys:
    ldr r0, =KEYINPUT
    ldrh r1, [r0]
    mvn r1, r1
    ldr r0, =0x03ff
    and r1, r1, r0
    ldr r0, =keys
    ldr r2, [r0]
    str r1, [r0]
    bic r1, r1, r2
    ldr r0, =pressed
    str r1, [r0]
    tst r1, #1
    ldr r0, =press_count
    ldr r2, [r0]
    addne r2, r2, #1
    str r2, [r0]
    bx lr
@ end: input
@ snippet: movement
update_position:
    ldr r3, =hero_x
    ldr r0, [r3]
    ldr r3, =hero_y
    ldr r1, [r3]
    ldr r3, =keys
    ldr r2, [r3]
    tst r2, #16
    addne r0, r0, #1
    tst r2, #32
    subne r0, r0, #1
    tst r2, #64
    subne r1, r1, #1
    tst r2, #128
    addne r1, r1, #1
    cmp r0, #0
    movlt r0, #0
    cmp r0, #232
    movgt r0, #232
    cmp r1, #0
    movlt r1, #0
    cmp r1, #152
    movgt r1, #152
    ldr r3, =hero_x
    str r0, [r3]
    ldr r3, =hero_y
    str r1, [r3]
    bx lr
@ end: movement

paint_hero:
    ldr r0, =hero_x
    ldr r0, [r0]
    ldr r1, =hero_y
    ldr r1, [r1]
    mov r2, #8
    mov r3, #8
    b fill_rect
@ snippet: pixels
@ r0=x, r1=y, r2=largura, r3=altura, r4=cor.
@ Exige largura/altura positivas e retangulo inteiramente dentro da tela.
fill_rect:
    push {r5-r8, lr}
    mov r5, #240
    mul r6, r1, r5
    add r6, r6, r0
    ldr r5, =VRAM
    add r5, r5, r6, lsl #1
    rsb r7, r2, #240
    mov r7, r7, lsl #1
    mov r6, r3
row:
    mov r8, r2
pixel:
    strh r4, [r5], #2
    subs r8, r8, #1
    bne pixel
    add r5, r5, r7
    subs r6, r6, #1
    bne row
    pop {r5-r8, lr}
    bx lr
@ end: pixels

.ltorg
.section .bss
.balign 4
.global frame_tick
frame_tick: .space 4
.global keys
keys: .space 4
.global pressed
pressed: .space 4
.global press_count
press_count: .space 4
.global hero_x
hero_x: .space 4
.global hero_y
hero_y: .space 4
