aboutsummaryrefslogtreecommitdiff
path: root/src/interrupts.s
blob: 2c78099e03e64f0d4d6456853734ea0557db79d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
.segment "CODE"

.proc nmi
    ;; Should we skip it?
    bit Globals::zp_flags

    ;; If we are on a dev environment, account for any frame drops.
    .ifdef PARTIAL
        bmi @after_frame_check
        jmp @account_for_frame_drop
    @after_frame_check:
    .else
        bmi @save_registers
        rti
    .endif

@save_registers:
    pha
    txa
    pha
    tya
    pha

    ;; Sprite DMA.
    lda #$00
    sta OAM::m_address
    lda #$02
    sta OAM::m_dma

    ;; Toggle pause message from the HUD.
    bit Driver::zp_flags
    bvc @increase_rand
    jsr Driver::hud_toggle_pause

@increase_rand:
    ;; Increase the random seed.
    inc Prng::zp_rand

    ;; Are we paused? If so skip timers, PAL handler and the likes.
    lda #%00001000
    and Globals::zp_flags
    bne @ppu_registers

    ;; PAL-specific code
    .ifdef PAL
        jsr Driver::pal_handler
    .endif

    ;; Handle player selection blinking.
    bit Driver::zp_blink_status
    bpl @update_lifes

    ;; Sprinkle, sprinkle!
    lda #0
    bvc @set_blinking
    lda #$70
@set_blinking:
    sta Globals::zp_nmi_reserved
    jsr Driver::blink_player_selection

@update_lifes:
    ;; Do we need to update the lifes from players on the HUD?
    lda Player::zp_state
    and #%00001000
    beq @shuttle_update

    ;; Yeah!

    ;; Update for player 1.
    bit PPU::m_status
    lda #$28
    sta PPU::m_address
    lda #$4B
    sta PPU::m_address
    lda Player::zp_lifes
    clc
    adc #$10
    sta PPU::m_data

    ;; Update for player 2 if exists.
    bit Globals::zp_multiplayer
    bpl @unset_life_flag

    bit PPU::m_status
    lda #$28
    sta PPU::m_address
    lda #$56
    sta PPU::m_address
    lda Player::zp_lifes + 1
    clc
    adc #$10
    sta PPU::m_data

@unset_life_flag:
    ;; And unset the 'life' flag from the player.
    lda Player::zp_state
    and #%11110111
    sta Player::zp_state

@shuttle_update:
    ;; Should the shuttle be updated?
    lda Globals::zp_flags
    tax
    and #%00100000
    beq @game_status
    jsr Items::update_shuttle

    ;; And unset the flag.
    lda Globals::zp_flags
    and #%11011111
    sta Globals::zp_flags

@game_status:
    txa
    and #%00000001
    bne @ppu_registers

    ;; Decrease title timer.
    lda Title::zp_title_timer
    beq @ppu_registers
    dec Title::zp_title_timer

@ppu_registers:
    ;; Should we update PPU registers?
    bit Globals::zp_flags
    bvc @scroll

    ;; Zero out the `ppu` flag.
    lda #%10111111
    and Globals::zp_flags
    sta Globals::zp_flags

    bit PPU::m_status

    ;; Update the PPU control/mask registers with shadowed values.
    lda PPU::zp_mask
    sta PPU::m_mask
    lda PPU::zp_control
    sta PPU::m_control

@scroll:
    ;; Always reset the scroll just in case.
    bit PPU::m_status
    lda #$00
    sta PPU::m_scroll
    sta PPU::m_scroll

    ;; Unblock the main code.
    lda #%01111111
    and Globals::zp_flags
    sta Globals::zp_flags

    ;; Restore registers.
    pla
    tay
    pla
    tax
    pla

    rti

    ;; If we are on a dev environment, account for any frame drops.
.ifdef PARTIAL
@account_for_frame_drop:
    inc Debug::zp_frame_drops
    rti
.endif
.endproc

;; Unused.
.proc irq
    rti
.endproc