1.1 --- a/switcher.oph Sat Jun 27 18:28:12 2015 +0200
1.2 +++ b/switcher.oph Sat Jun 27 19:21:03 2015 +0200
1.3 @@ -17,12 +17,19 @@
1.4
1.5 .include "macros.oph"
1.6
1.7 +.alias SP $70
1.8 +.alias SPH $71
1.9 +.alias NEXT $72
1.10 +.alias NEXTH $73
1.11 +.alias CURRENT $74
1.12 +.alias CURRENTH $75
1.13 +
1.14 .org $2000
1.15 .text
1.16 -
1.17 main:
1.18 jsr install_handler
1.19 - rts
1.20 +test:
1.21 + jmp test
1.22
1.23 ; install the interrupt handler address in IRQ1V
1.24 ;
1.25 @@ -43,22 +50,35 @@
1.26 pha ; A -> stack
1.27 txa
1.28 pha ; X -> stack
1.29 + tsx ; capture the stack pointer now for later use
1.30 + ; (stack is <empty>, X, A, F, LSB, MSB)
1.31 tya
1.32 pha ; Y -> stack
1.33 - .invoke push16 $70
1.34 +
1.35 + ; save zero-page locations used in the handler
1.36 +
1.37 + .invoke push16 SP
1.38 + .invoke push16 NEXT
1.39 + .invoke push16 CURRENT
1.40 +
1.41 +init_sp:
1.42 +
1.43 + ; initialise the stack frame pointer
1.44 +
1.45 + txa
1.46 + sta SP
1.47 + lda #$01 ; $01xx
1.48 + sta SPH
1.49 +
1.50 +test_pc:
1.51
1.52 ; test PC for execution of ROM routines
1.53 ; these are probably not re-entrant
1.54
1.55 ; obtain the stack location of the stored PC MSB
1.56 - tsx
1.57 - txa
1.58 - sta $70
1.59 - lda #$01 ; $01xx
1.60 - sta $71
1.61
1.62 - ldy #6 ; offset of MSB (<empty>, Y, X, A, F, LSB, MSB)
1.63 - lda ($70), y
1.64 + ldy #5 ; offset of MSB (Y, X, A, F, LSB, MSB)
1.65 + lda (SP), y
1.66
1.67 ; reference the stack location and compute PC MSB & $80
1.68 and #$80
1.69 @@ -67,11 +87,73 @@
1.70 ; exit if PC MSB & $80 != 0
1.71 beq exit_handler
1.72
1.73 - ; increment a counter
1.74 - .invoke add16 1, $7000
1.75 +load_task:
1.76 +
1.77 + ; load next task
1.78 +
1.79 + ldx task_index
1.80 + lda tasks, x
1.81 + sta NEXT
1.82 + inx
1.83 + lda tasks, x
1.84 + sta NEXTH
1.85 + inx
1.86 +
1.87 + ; reset the task index if necessary
1.88 +
1.89 + cpx #10 ; length of tasks array
1.90 + bne test_task
1.91 + ldx #0
1.92 +
1.93 +test_task:
1.94 + stx task_index
1.95 +
1.96 + ; exit if null task
1.97 +
1.98 + lda NEXTH
1.99 + cmp #0
1.100 + beq exit_handler
1.101 +
1.102 +switch_task:
1.103 +
1.104 + ; store flags, PC in current task structure
1.105 +
1.106 + .invoke mov16 current_task, CURRENT
1.107 +
1.108 + ldy #5 ; offset of MSB (Y, X, A, F, LSB, MSB)
1.109 + lda (SP), y
1.110 + sta (CURRENT), y
1.111 + dey
1.112 + lda (SP), y
1.113 + sta (CURRENT), y
1.114 + dey
1.115 + lda (SP), y
1.116 + sta (CURRENT), y
1.117 +
1.118 + ; load flags, PC from next task structure
1.119 +
1.120 + lda (NEXT), y
1.121 + sta (SP), y
1.122 + iny
1.123 + lda (NEXT), y
1.124 + sta (SP), y
1.125 + iny
1.126 + lda (NEXT), y
1.127 + sta (SP), y
1.128 + iny
1.129 +
1.130 + ; make the next task the current one
1.131 +
1.132 + .invoke mov16 NEXT, current_task
1.133
1.134 exit_handler:
1.135 - .invoke pull16 $70
1.136 +
1.137 + ; restore zero-page locations used in the handler
1.138 +
1.139 + .invoke pull16 CURRENT
1.140 + .invoke pull16 NEXT
1.141 + .invoke pull16 SP
1.142 +
1.143 pla
1.144 tay ; stack -> Y
1.145 pla
1.146 @@ -79,6 +161,47 @@
1.147 pla ; stack -> A
1.148 jmp (old_handler)
1.149
1.150 +; location of previous interrupt handler
1.151 +
1.152 old_handler: .word 0
1.153
1.154 +; location of current task (duplicated from the table)
1.155 +
1.156 +current_task: .word 0
1.157 +
1.158 +; index of current task
1.159 +
1.160 +task_index: .byte 0
1.161 +
1.162 +; task table containing locations of each task
1.163 +
1.164 +tasks:
1.165 + .word first_task
1.166 + .word second_task
1.167 + .word 0
1.168 + .word 0
1.169 + .word 0
1.170 +
1.171 +; example tasks
1.172 +
1.173 +first_task:
1.174 + .byte 0 ; currently unused
1.175 + .byte 0 ; currently unused
1.176 + .byte 0 ; currently unused
1.177 + .byte 0 ; saved flags
1.178 + .word first_task_start ; saved PC
1.179 +first_task_start:
1.180 + .invoke add16 1, $7000
1.181 + jmp first_task_start
1.182 +
1.183 +second_task:
1.184 + .byte 0 ; currently unused
1.185 + .byte 0 ; currently unused
1.186 + .byte 0 ; currently unused
1.187 + .byte 0 ; saved flags
1.188 + .word second_task_start ; saved PC
1.189 +second_task_start:
1.190 + .invoke add16 1, $7008
1.191 + jmp second_task_start
1.192 +
1.193 ; vim: tabstop=4 expandtab shiftwidth=4