590 lines
12 KiB
ArmAsm
590 lines
12 KiB
ArmAsm
|
|
#include "nes.inc"
|
||
|
|
|
||
|
|
.globl ppu_next_scanline
|
||
|
|
ppu_next_scanline:
|
||
|
|
push {r4-r8, r10-r11, lr}
|
||
|
|
|
||
|
|
ldr r10, [r9, #s_ppu_flags]
|
||
|
|
|
||
|
|
ldr r0, [r9, #s_ppu_scanline]
|
||
|
|
|
||
|
|
add r0, r0, #1
|
||
|
|
|
||
|
|
cmp r0, #-1 @ Vblank is over
|
||
|
|
biceq r10, r10, #0xC00000
|
||
|
|
|
||
|
|
cmp r0, #241 @ Vblank is starting
|
||
|
|
bne 1f
|
||
|
|
mov r0, #-21
|
||
|
|
orr r10, r10, #0x800000
|
||
|
|
and r2, r10, #0x80 @ NMI enabled?
|
||
|
|
strb r2, [r9, #s_nmi_reset]
|
||
|
|
1:
|
||
|
|
|
||
|
|
str r0, [r9, #s_ppu_scanline]
|
||
|
|
|
||
|
|
cmp r0, #240
|
||
|
|
bcs rendering_off
|
||
|
|
|
||
|
|
tst r10, #0x1800
|
||
|
|
beq 1f
|
||
|
|
cmp r0, #0
|
||
|
|
@ Line 0: Move to (X,Y) position specified in s_ppu_scroll
|
||
|
|
@ Lines 1-239: Move back to X position specified in s_ppu_scroll
|
||
|
|
ldr r1, [r9, #s_ppu_address]
|
||
|
|
ldr r0, [r9, #s_ppu_scroll]
|
||
|
|
moveq r2, #0xFF00
|
||
|
|
addeq r2, r2, #0x00FF
|
||
|
|
movne r2, #0x0400
|
||
|
|
addne r2, r2, #0x001F
|
||
|
|
and r0, r0, r2
|
||
|
|
bic r1, r1, r2
|
||
|
|
orr r1, r1, r0
|
||
|
|
str r1, [r9, #s_ppu_address]
|
||
|
|
1:
|
||
|
|
|
||
|
|
ldr r0, [r9, #s_frameskip_cur]
|
||
|
|
cmp r0, #0
|
||
|
|
bne frameskipped
|
||
|
|
|
||
|
|
@ Allocate scanline pixel buffer
|
||
|
|
sub sp, sp, #272
|
||
|
|
|
||
|
|
@ Step I: Render background
|
||
|
|
tst r10, #0x0800
|
||
|
|
beq background_disabled
|
||
|
|
mov r1, r10, lsl #8
|
||
|
|
and r1, r1, #0x1000
|
||
|
|
|
||
|
|
ldr r2, [r9, #s_ppu_address]
|
||
|
|
and r8, r2, #0x1F
|
||
|
|
add r1, r1, r2, lsr #12
|
||
|
|
bl get_name_table_pointers
|
||
|
|
|
||
|
|
mov r11, #33
|
||
|
|
ldr r6, =0x08040201
|
||
|
|
ldr r7, =0xEEEEEEEE
|
||
|
|
draw_chr:
|
||
|
|
@ Get attribute for this block
|
||
|
|
ldrb r12, [r0, r8, lsr #2]
|
||
|
|
|
||
|
|
@ Get character
|
||
|
|
ldrb r3, [r2, r8]
|
||
|
|
|
||
|
|
tst r2, #0x40 @ Assuming nametable is 128-byte aligned
|
||
|
|
movne r12, r12, lsr #4
|
||
|
|
tst r8, #0x02
|
||
|
|
moveq r12, r12, lsl #2
|
||
|
|
and r12, r12, #0x0C
|
||
|
|
orr r12, r12, #0x03
|
||
|
|
orr r12, r12, lsl #8
|
||
|
|
orr r12, r12, lsl #16
|
||
|
|
|
||
|
|
@ Get pixels for appropriate row of character
|
||
|
|
add r4, r1, r3, lsl #4
|
||
|
|
mov r3, r4, lsr #10
|
||
|
|
add r3, r9, r3, lsl #2
|
||
|
|
ldr r3, [r3, #s_ppu_mem_map]
|
||
|
|
ldrb r3, [r4, r3]! @ Low plane
|
||
|
|
ldrb r4, [r4, #8] @ High plane
|
||
|
|
|
||
|
|
@ Move to next character over
|
||
|
|
add r8, r8, #1
|
||
|
|
cmp r8, #0x20
|
||
|
|
bleq swap_name_table
|
||
|
|
|
||
|
|
@ Unpack each pixel into a nybble
|
||
|
|
mul r3, r6, r3
|
||
|
|
mul r4, r6, r4
|
||
|
|
orr r3, r7, r3, lsr #3
|
||
|
|
orr r4, r7, r4, lsr #3
|
||
|
|
and r4, r3, r4, ror #31
|
||
|
|
|
||
|
|
@ Unpack nybbles into bytes
|
||
|
|
and r3, r12, r4, lsr #4
|
||
|
|
and r4, r12, r4
|
||
|
|
stmia sp!, {r3-r4}
|
||
|
|
|
||
|
|
subs r11, r11, #1
|
||
|
|
bne draw_chr
|
||
|
|
sub sp, sp, #264
|
||
|
|
|
||
|
|
@ Blank out left 8 pixels
|
||
|
|
tst r10, #0x0200
|
||
|
|
bne background_done
|
||
|
|
ldr r0, [r9, #s_ppu_scroll]
|
||
|
|
mov r3, #0
|
||
|
|
add r0, sp, r0, lsr #29
|
||
|
|
strb r3, [r0]
|
||
|
|
strb r3, [r0, #1]
|
||
|
|
strb r3, [r0, #2]
|
||
|
|
strb r3, [r0, #3]
|
||
|
|
strb r3, [r0, #4]
|
||
|
|
strb r3, [r0, #5]
|
||
|
|
strb r3, [r0, #6]
|
||
|
|
strb r3, [r0, #7]
|
||
|
|
background_done:
|
||
|
|
|
||
|
|
ldr r0, [r9, #s_ppu_scroll]
|
||
|
|
add sp, sp, r0, lsr #29
|
||
|
|
|
||
|
|
@ Step II: Sprites
|
||
|
|
tst r10, #0x1000
|
||
|
|
beq no_sprites
|
||
|
|
|
||
|
|
@ Get sprite height (minus 1)
|
||
|
|
tst r10, #0x0020
|
||
|
|
moveq r12, #7
|
||
|
|
movne r12, #15
|
||
|
|
|
||
|
|
ldrb r1, [r9, #s_spr_loc_table_valid]
|
||
|
|
movs r1, r1
|
||
|
|
bleq refresh_spr_loc_table
|
||
|
|
|
||
|
|
ldr r0, [r9, #s_ppu_scanline]
|
||
|
|
|
||
|
|
add r2, r9, #s_spr_loc_table
|
||
|
|
add r2, r2, r0, lsl #3
|
||
|
|
ldrb r1, [r2, r0]!
|
||
|
|
|
||
|
|
cmp r1, #0
|
||
|
|
beq no_sprites
|
||
|
|
|
||
|
|
@ Only up to 8 sprites are actually stored in the table
|
||
|
|
cmp r1, #8
|
||
|
|
movcs r1, #8
|
||
|
|
|
||
|
|
sub r0, r0, #1
|
||
|
|
sprite_loop:
|
||
|
|
ldrb r4, [r2, #1]!
|
||
|
|
add r8, r9, #s_ppu_oam_ram
|
||
|
|
ldr r4, [r8, r4]
|
||
|
|
|
||
|
|
@ Get offset from the top
|
||
|
|
and r6, r4, #0xFF
|
||
|
|
sub r5, r0, r6
|
||
|
|
|
||
|
|
bl fetch_sprite_bits
|
||
|
|
|
||
|
|
@ Get palette
|
||
|
|
mov r8, r4, lsr #14
|
||
|
|
and r8, r8, #0x0C
|
||
|
|
orr r8, r8, #0x30
|
||
|
|
|
||
|
|
tst r4, #0x400000
|
||
|
|
movne r5, r5, lsl #7
|
||
|
|
moveq r3, #31
|
||
|
|
movne r3, #1
|
||
|
|
|
||
|
|
mov r6, #8
|
||
|
|
add r11, sp, r4, lsr #24
|
||
|
|
tst r4, #0x200000
|
||
|
|
bne sprite_draw_low_pri
|
||
|
|
sprite_draw_high_pri:
|
||
|
|
ldrb lr, [r11], #1
|
||
|
|
and r7, r5, #0x80
|
||
|
|
orr r7, r8, r7, lsr #7
|
||
|
|
tst r5, #0x8000
|
||
|
|
addne r7, r7, #2
|
||
|
|
tst r7, #3
|
||
|
|
beq 1f
|
||
|
|
tst lr, #0x20
|
||
|
|
streqb r7, [r11, #-1]
|
||
|
|
1: mov r5, r5, ror r3
|
||
|
|
subs r6, r6, #1
|
||
|
|
bne sprite_draw_high_pri
|
||
|
|
b sprite_next
|
||
|
|
sprite_draw_low_pri:
|
||
|
|
ldrb lr, [r11], #1
|
||
|
|
and r7, r5, #0x80
|
||
|
|
orr r7, r8, r7, lsr #7
|
||
|
|
tst r5, #0x8000
|
||
|
|
addne r7, r7, #2
|
||
|
|
tst r7, #3
|
||
|
|
beq 1f
|
||
|
|
tst lr, #3
|
||
|
|
orrne r7, lr, #0x20
|
||
|
|
strb r7, [r11, #-1]
|
||
|
|
1: mov r5, r5, ror r3
|
||
|
|
subs r6, r6, #1
|
||
|
|
bne sprite_draw_low_pri
|
||
|
|
sprite_next:
|
||
|
|
subs r1, r1, #1
|
||
|
|
bne sprite_loop
|
||
|
|
no_sprites:
|
||
|
|
|
||
|
|
@ Step III: Draw to screen
|
||
|
|
ldrb r0, [r9, #s_message_timer]
|
||
|
|
ldr r8, [r9, #s_ppu_scanline]
|
||
|
|
movs r0, r0
|
||
|
|
movne r0, #16
|
||
|
|
cmp r8, r0
|
||
|
|
addcc sp, #256
|
||
|
|
bcc draw_done
|
||
|
|
|
||
|
|
mov r4, #0xC0000000
|
||
|
|
ldr r4, [r4, #0x10]
|
||
|
|
add r5, r9, #s_palette_cache
|
||
|
|
|
||
|
|
ldr r0, [r9, #s_hw_color]
|
||
|
|
ldrb r1, [r9, #s_palette_cache_valid]
|
||
|
|
movs r0, r0
|
||
|
|
bne draw_color
|
||
|
|
|
||
|
|
movs r1, r1
|
||
|
|
bleq refresh_palette_cache_bw
|
||
|
|
|
||
|
|
@ Draw in black and white
|
||
|
|
add r8, r8, r8, lsl #2
|
||
|
|
add r4, r4, r8, lsl #5
|
||
|
|
add r4, r4, #0x10
|
||
|
|
|
||
|
|
mov r8, #256
|
||
|
|
1: ldrb r0, [sp], #1
|
||
|
|
ldrb r1, [sp], #1
|
||
|
|
ldrb r2, [sp], #1
|
||
|
|
ldrb r3, [sp], #1
|
||
|
|
ldrb r0, [r5, r0]
|
||
|
|
ldrb r1, [r5, r1]
|
||
|
|
ldrb r2, [r5, r2]
|
||
|
|
ldrb r3, [r5, r3]
|
||
|
|
orr r0, r1, r0, lsl #4
|
||
|
|
orr r0, r0, r2, lsl #12
|
||
|
|
orr r0, r0, r3, lsl #8
|
||
|
|
strh r0, [r4], #2
|
||
|
|
subs r8, r8, #4
|
||
|
|
bne 1b
|
||
|
|
|
||
|
|
b draw_done
|
||
|
|
draw_color:
|
||
|
|
movs r1, r1
|
||
|
|
bleq refresh_palette_cache_color
|
||
|
|
|
||
|
|
add r8, r8, r8, lsl #2
|
||
|
|
add r4, r4, r8, lsl #7
|
||
|
|
add r4, r4, #0x40
|
||
|
|
|
||
|
|
mov r8, #256
|
||
|
|
1: ldrb r0, [sp], #1
|
||
|
|
ldrb r1, [sp], #1
|
||
|
|
ldrb r2, [sp], #1
|
||
|
|
ldrb r3, [sp], #1
|
||
|
|
add r0, r0
|
||
|
|
add r1, r1
|
||
|
|
add r2, r2
|
||
|
|
add r3, r3
|
||
|
|
ldrh r0, [r5, r0]
|
||
|
|
ldrh r1, [r5, r1]
|
||
|
|
ldrh r2, [r5, r2]
|
||
|
|
ldrh r3, [r5, r3]
|
||
|
|
orr r0, r1, lsl #16
|
||
|
|
str r0, [r4], #4
|
||
|
|
orr r2, r3, lsl #16
|
||
|
|
str r2, [r4], #4
|
||
|
|
subs r8, r8, #4
|
||
|
|
bne 1b
|
||
|
|
|
||
|
|
|
||
|
|
draw_done:
|
||
|
|
ldr r0, [r9, #s_ppu_scroll]
|
||
|
|
add sp, sp, #16
|
||
|
|
sub sp, sp, r0, lsr #29
|
||
|
|
|
||
|
|
frameskipped:
|
||
|
|
@ Check for sprite 0 hit
|
||
|
|
@ (TODO: should only occur when two opaque pixels collide)
|
||
|
|
tst r10, #0x1000
|
||
|
|
beq sprite_0_done
|
||
|
|
tst r10, #0x0020
|
||
|
|
moveq r12, #7
|
||
|
|
movne r12, #15
|
||
|
|
ldr r0, [r9, #s_ppu_scanline]
|
||
|
|
ldr r4, [r9, #s_ppu_oam_ram]
|
||
|
|
sub r0, r0, #1
|
||
|
|
and r6, r4, #0xFF
|
||
|
|
sub r5, r0, r6
|
||
|
|
cmp r5, r12
|
||
|
|
bls sprite_0_check
|
||
|
|
sprite_0_done:
|
||
|
|
|
||
|
|
tst r10, #0x1800
|
||
|
|
beq rendering_off
|
||
|
|
@ Move down by one pixel
|
||
|
|
ldr r1, [r9, #s_ppu_address]
|
||
|
|
add r1, r1, #0x1000
|
||
|
|
cmp r1, #0x8000
|
||
|
|
bcc 1f
|
||
|
|
bic r1, r1, #0x8000
|
||
|
|
add r1, r1, #0x0020
|
||
|
|
ands r2, r1, #0x03E0
|
||
|
|
subeq r1, r1, #0x0400 @ If Y wraps 31->0, no name table change
|
||
|
|
cmp r2, #0x03C0
|
||
|
|
eoreq r1, r1, #0x0BC0 @ If Y wraps 29->0, name table change
|
||
|
|
1: str r1, [r9, #s_ppu_address]
|
||
|
|
|
||
|
|
rendering_off:
|
||
|
|
str r10, [r9, #s_ppu_flags]
|
||
|
|
ldr r0, [r9, #s_ppu_scanline]
|
||
|
|
cmp r0, #-21
|
||
|
|
bleq newframe
|
||
|
|
pop {r4-r8, r10-r11, pc}
|
||
|
|
|
||
|
|
.pool
|
||
|
|
|
||
|
|
swap_name_table:
|
||
|
|
ldr r2, [r9, #s_ppu_address]
|
||
|
|
mov r8, #0
|
||
|
|
eor r2, r2, #0x0400
|
||
|
|
get_name_table_pointers:
|
||
|
|
and r2, r2, #0x0FE0
|
||
|
|
orr r2, r2, #0x2000
|
||
|
|
mov r5, r2, lsr #10
|
||
|
|
add r5, r9, r5, lsl #2
|
||
|
|
ldr r5, [r5, #s_ppu_mem_map]
|
||
|
|
|
||
|
|
and r0, r2, #0xFC00
|
||
|
|
orr r0, r0, r2, lsr #4
|
||
|
|
orr r0, r0, #0x03C0
|
||
|
|
bic r0, r0, #7
|
||
|
|
|
||
|
|
add r2, r5, r2
|
||
|
|
add r0, r5, r0
|
||
|
|
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
background_disabled:
|
||
|
|
@ Weird NES behavior: if rendering is completely disabled (both BG and sprite),
|
||
|
|
@ and PPUADDR points inside palette, draw that color.
|
||
|
|
@ Otherwise, just draw color 0
|
||
|
|
tst r10, #0x1800
|
||
|
|
bne 1f
|
||
|
|
ldr r0, [r9, #s_ppu_address]
|
||
|
|
ands lr, r0, #0x3F00
|
||
|
|
and r0, r0, #0x1F
|
||
|
|
orr r0, r0, #0x20 @ use alternate palette (doesn't map $04,$08,$0C -> $00)
|
||
|
|
orr r0, r0, r0, lsl #8
|
||
|
|
orr r0, r0, r0, lsl #16
|
||
|
|
cmp lr, #0x3F00
|
||
|
|
1: movne r0, #0
|
||
|
|
|
||
|
|
mov r11, #264
|
||
|
|
1: subs r11, r11, #4
|
||
|
|
str r0, [sp, r11]
|
||
|
|
bne 1b
|
||
|
|
b background_done
|
||
|
|
|
||
|
|
sprite_0_check:
|
||
|
|
bl fetch_sprite_bits
|
||
|
|
movs r5, r5
|
||
|
|
orrne r10, r10, #0x400000
|
||
|
|
b sprite_0_done
|
||
|
|
|
||
|
|
fetch_sprite_bits:
|
||
|
|
@ Vertical flip
|
||
|
|
tst r4, #0x800000
|
||
|
|
rsbne r5, r5, r12
|
||
|
|
|
||
|
|
@ Get CHR address
|
||
|
|
tst r10, #0x0020
|
||
|
|
moveq r8, r10, lsl #9
|
||
|
|
movne r8, r4, lsl #4
|
||
|
|
and r8, r8, #0x1000
|
||
|
|
moveq r6, #0xFF
|
||
|
|
movne r6, #0xFE
|
||
|
|
and r6, r6, r4, lsr #8
|
||
|
|
addne r6, r6, r5, lsr #3
|
||
|
|
and r5, r5, #7
|
||
|
|
|
||
|
|
add r6, r8, r6, lsl #4
|
||
|
|
mov r8, r6, lsr #10
|
||
|
|
add r8, r9, r8, lsl #2
|
||
|
|
ldr r8, [r8, #s_ppu_mem_map]
|
||
|
|
add r6, r8, r6
|
||
|
|
|
||
|
|
ldrb r5, [r6, r5]! @ low plane
|
||
|
|
ldrb r6, [r6, #8] @ high plane
|
||
|
|
|
||
|
|
orr r5, r5, r6, lsl #8
|
||
|
|
|
||
|
|
@ Check if sprite needs to be clipped against left edge of screen
|
||
|
|
cmp r4, #0x08000000
|
||
|
|
bxcs lr
|
||
|
|
clip_sprite:
|
||
|
|
tst r10, #0x0400
|
||
|
|
bxne lr
|
||
|
|
mov r3, r4, lsr #24
|
||
|
|
add r3, pc, r3, lsl #2
|
||
|
|
ldr r3, [r3, #sprite_clip_table - (.+4)]
|
||
|
|
tst r4, #0x400000
|
||
|
|
biceq r5, r5, r3
|
||
|
|
bicne r5, r5, r3, lsr #16
|
||
|
|
bx lr
|
||
|
|
sprite_clip_table:
|
||
|
|
.word 0xFFFFFFFF
|
||
|
|
.word 0x7F7FFEFE
|
||
|
|
.word 0x3F3FFCFC
|
||
|
|
.word 0x1F1FF8F8
|
||
|
|
.word 0x0F0FF0F0
|
||
|
|
.word 0x0707E0E0
|
||
|
|
.word 0x0303C0C0
|
||
|
|
.word 0x01018080
|
||
|
|
|
||
|
|
refresh_spr_loc_table:
|
||
|
|
@ Start by clearing the table (0 sprites for every scanline)
|
||
|
|
add r1, r9, #s_spr_loc_table
|
||
|
|
mov r2, #0
|
||
|
|
mov r3, #240
|
||
|
|
1: strb r2, [r1], #9
|
||
|
|
subs r3, r3, #1
|
||
|
|
bne 1b
|
||
|
|
|
||
|
|
add r2, r9, #s_spr_loc_table
|
||
|
|
add r2, r2, #9
|
||
|
|
|
||
|
|
@ Loop over each sprite
|
||
|
|
add r0, r9, #s_ppu_oam_ram
|
||
|
|
sub r0, r0, #4
|
||
|
|
mov r6, #64
|
||
|
|
spr_loc_loop1:
|
||
|
|
@ Get first scanline (minus one) of sprite
|
||
|
|
ldrb r3, [r0, #4]!
|
||
|
|
|
||
|
|
rsbs r4, r3, #239 @ Number of visible scanlines
|
||
|
|
bls spr_loc_done
|
||
|
|
cmp r4, r12
|
||
|
|
addhi r4, r12, #1
|
||
|
|
|
||
|
|
add r1, r2, r3, lsl #3
|
||
|
|
add r1, r1, r3
|
||
|
|
|
||
|
|
@ Loop over each scanline this sprite is in,
|
||
|
|
@ appending the sprite index to each one's list
|
||
|
|
spr_loc_loop2:
|
||
|
|
ldrb r5, [r1]
|
||
|
|
add r5, r5, #1
|
||
|
|
cmp r5, #8
|
||
|
|
strlsb r0, [r1, r5] @ Assuming OAM is 256-byte aligned
|
||
|
|
strb r5, [r1], #9
|
||
|
|
subs r4, r4, #1
|
||
|
|
bne spr_loc_loop2
|
||
|
|
spr_loc_done:
|
||
|
|
subs r6, r6, #1
|
||
|
|
bne spr_loc_loop1
|
||
|
|
|
||
|
|
mov r0, #1
|
||
|
|
strb r0, [r9, #s_spr_loc_table_valid]
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
refresh_palette_cache_bw:
|
||
|
|
adr r0, nes_color_to_gray_table
|
||
|
|
add r1, r9, #s_ppu_palette
|
||
|
|
add r2, r5, #0x40
|
||
|
|
mov r3, #0x1F
|
||
|
|
1: ldrb r6, [r1, r3]
|
||
|
|
ldrb r6, [r0, r6]
|
||
|
|
strb r6, [r2, #-1]!
|
||
|
|
subs r3, r3, #1
|
||
|
|
bpl 1b
|
||
|
|
mov r3, #0x1F
|
||
|
|
1: tst r3, #0x03
|
||
|
|
ldreqb r6, [r1]
|
||
|
|
ldrneb r6, [r1, r3]
|
||
|
|
ldrb r6, [r0, r6]
|
||
|
|
strb r6, [r2, #-1]!
|
||
|
|
subs r3, r3, #1
|
||
|
|
bpl 1b
|
||
|
|
strb r3, [r9, #s_palette_cache_valid]
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
refresh_palette_cache_color:
|
||
|
|
adr r0, nes_color_to_rgb_table
|
||
|
|
add r1, r9, #s_ppu_palette
|
||
|
|
add r2, r5, #0x80
|
||
|
|
mov r3, #0x1F
|
||
|
|
1: ldrb r6, [r1, r3]
|
||
|
|
add r6, r6
|
||
|
|
ldrh r6, [r0, r6]
|
||
|
|
strh r6, [r2, #-2]!
|
||
|
|
subs r3, r3, #1
|
||
|
|
bpl 1b
|
||
|
|
mov r3, #0x1F
|
||
|
|
1: tst r3, #0x03
|
||
|
|
ldreqb r6, [r1]
|
||
|
|
ldrneb r6, [r1, r3]
|
||
|
|
add r6, r6
|
||
|
|
ldrh r6, [r0, r6]
|
||
|
|
strh r6, [r2, #-2]!
|
||
|
|
subs r3, r3, #1
|
||
|
|
bpl 1b
|
||
|
|
strb r3, [r9, #s_palette_cache_valid]
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
.globl invert_colors
|
||
|
|
invert_colors:
|
||
|
|
adr r0, nes_color_to_gray_table
|
||
|
|
mov r2, #64
|
||
|
|
1: subs r2, r2, #1
|
||
|
|
ldrb r1, [r0, r2]
|
||
|
|
eor r1, r1, #0x0F
|
||
|
|
strb r1, [r0, r2]
|
||
|
|
bne 1b
|
||
|
|
adr r0, nes_color_to_rgb_table
|
||
|
|
mov r2, #128
|
||
|
|
1: subs r2, r2, #4
|
||
|
|
ldr r1, [r0, r2]
|
||
|
|
mvn r1, r1
|
||
|
|
str r1, [r0, r2]
|
||
|
|
bne 1b
|
||
|
|
strb r2, [r9, #s_palette_cache_valid]
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
nes_color_to_gray_table:
|
||
|
|
.byte 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0
|
||
|
|
.byte 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0
|
||
|
|
.byte 15,10,10,10,10,10,10,10,10,10,10,10,10, 5, 0, 0
|
||
|
|
.byte 15,13,13,13,13,13,13,13,13,13,13,13,13,11, 0, 0
|
||
|
|
|
||
|
|
@ .byte 7, 3, 4, 4, 5, 6, 6, 4, 3, 3, 4, 3, 3, 0, 0, 0
|
||
|
|
@ .byte 11, 7, 6, 7, 7, 8, 8, 8, 7, 7, 8, 7, 7, 0, 0, 0
|
||
|
|
@ .byte 15,10, 9, 8,11,11,10,11,12,10,11,12,12, 7, 0, 0
|
||
|
|
@ .byte 15,13,13,13,13,13,12,13,14,14,13,14,14,12, 0, 0
|
||
|
|
|
||
|
|
nes_color_to_rgb_table:
|
||
|
|
.hword 0x73ae,0x20d1,0x0015,0x4013,0x880e,0xa802,0xa000,0x7840
|
||
|
|
.hword 0x4160,0x0220,0x0280,0x01e2,0x19eb,0x0000,0x0000,0x0000
|
||
|
|
.hword 0xbdf7,0x039d,0x21dd,0x801e,0xb817,0xe00b,0xd940,0xca61
|
||
|
|
.hword 0x8b80,0x04a0,0x0540,0x0487,0x0411,0x0000,0x0000,0x0000
|
||
|
|
.hword 0xffff,0x3dff,0x5cbf,0x445f,0xf3df,0xfbb6,0xfbac,0xfcc7
|
||
|
|
.hword 0xf5e7,0x8682,0x4ee9,0x5fd3,0x075b,0x7bcf,0x0000,0x0000
|
||
|
|
.hword 0xffff,0xaf3f,0xc6bf,0xd65f,0xfe3f,0xfe3b,0xfdf6,0xfed5
|
||
|
|
.hword 0xff34,0xe7f4,0xaf97,0xb7f9,0x9ffe,0xc638,0x0000,0x0000
|
||
|
|
|
||
|
|
.globl toggle_border
|
||
|
|
toggle_border:
|
||
|
|
ldr r0, [r9, #s_border_color]
|
||
|
|
mvn r0, r0
|
||
|
|
str r0, [r9, #s_border_color]
|
||
|
|
.globl clear_screen
|
||
|
|
clear_screen:
|
||
|
|
ldr r1, [r9, #s_border_color]
|
||
|
|
mov r0, #0xC0000000
|
||
|
|
ldr r0, [r0, #0x10]
|
||
|
|
ldr r2, [r9, #s_hw_color]
|
||
|
|
movs r2, r2
|
||
|
|
mov r2, #0x9600
|
||
|
|
lslne r2, #2
|
||
|
|
1: str r1, [r0], #4
|
||
|
|
subs r2, #4
|
||
|
|
bne 1b
|
||
|
|
bx lr
|
||
|
|
|
||
|
|
.globl display_ingame_message
|
||
|
|
display_ingame_message:
|
||
|
|
mov r1, #60
|
||
|
|
strb r1, [r9, #s_message_timer]
|
||
|
|
mov r1, #4
|
||
|
|
mov r2, #36
|
||
|
|
ldr r3, [r9, #s_border_color]
|
||
|
|
mvn r3, r3
|
||
|
|
b display_string
|