mirror of
https://github.com/irmen/prog8.git
synced 2024-09-30 15:57:06 +00:00
c64 irq handling routines
This commit is contained in:
parent
aea1292f92
commit
2f9eabeac7
@ -6,6 +6,7 @@
|
|||||||
ubyte time_changed
|
ubyte time_changed
|
||||||
|
|
||||||
sub irq() {
|
sub irq() {
|
||||||
|
; activated automatically if run in StackVm
|
||||||
global_time++
|
global_time++
|
||||||
time_changed = 1
|
time_changed = 1
|
||||||
}
|
}
|
||||||
@ -31,7 +32,6 @@
|
|||||||
float[len(zcoor)] rotatedz
|
float[len(zcoor)] rotatedz
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
set_irqvec()
|
|
||||||
while true {
|
while true {
|
||||||
if irq.time_changed {
|
if irq.time_changed {
|
||||||
irq.time_changed = 0
|
irq.time_changed = 0
|
||||||
|
@ -53,24 +53,28 @@
|
|||||||
@(SP0Y+i*2) = rnd()
|
@(SP0Y+i*2) = rnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
c64.SPENA = 255 ; enable all sprites
|
c64.SPENA = 255 ; enable all sprites
|
||||||
|
c64utils.set_rasterirq(51) ; enable animation
|
||||||
set_irqvec() ; enable animation
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
~ irq {
|
~ irq {
|
||||||
sub irq() {
|
sub irq() {
|
||||||
|
c64.EXTCOL--
|
||||||
; float up & wobble horizontally
|
; float up & wobble horizontally
|
||||||
|
|
||||||
|
; @todo for loop with step 2 doesn't work
|
||||||
|
|
||||||
for ubyte i in 0 to 7 {
|
for ubyte i in 0 to 7 {
|
||||||
@(main.SP0Y+i*2)--
|
@(main.SP0Y+i+i)--
|
||||||
ubyte r = rnd()
|
ubyte r = rnd()
|
||||||
if r>208
|
if r>208
|
||||||
@(main.SP0X+i*2)++
|
@(main.SP0X+i+i)++
|
||||||
else if r<48
|
else if r<48
|
||||||
@(main.SP0X+i*2)--
|
@(main.SP0X+i+i)--
|
||||||
}
|
}
|
||||||
|
c64.EXTCOL++
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1658,6 +1658,12 @@ class Subroutine(override val name: String,
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)"
|
return "Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun amountOfRtsInAsm(): Int = statements
|
||||||
|
.asSequence()
|
||||||
|
.filter { it is InlineAssembly }
|
||||||
|
.map { (it as InlineAssembly).assembly }
|
||||||
|
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,12 +100,21 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// there can be an optional 'irq' block with a 'irq' subroutine in it,
|
// there can be an optional 'irq' block with a 'irq' subroutine in it,
|
||||||
// which will be used as the 60hz irq routine in the vm if it's present (and enabled via set_irqvec()/set_irqvec_excl())
|
// which will be used as the 60hz irq routine in the vm if it's present
|
||||||
val irqBlock = module.statements.singleOrNull { it is Block && it.name=="irq" } as? Block?
|
val irqBlock = module.statements.singleOrNull { it is Block && it.name=="irq" } as? Block?
|
||||||
val irqSub = irqBlock?.subScopes()?.get("irq") as? Subroutine
|
val irqSub = irqBlock?.subScopes()?.get("irq") as? Subroutine
|
||||||
if(irqSub!=null) {
|
if(irqSub!=null) {
|
||||||
if(irqSub.parameters.isNotEmpty() || irqSub.returntypes.isNotEmpty())
|
if(irqSub.parameters.isNotEmpty() || irqSub.returntypes.isNotEmpty())
|
||||||
checkResult.add(SyntaxError("irq entrypoint subroutine can't have parameters and/or return values", irqSub.position))
|
checkResult.add(SyntaxError("irq entrypoint subroutine can't have parameters and/or return values", irqSub.position))
|
||||||
|
} else {
|
||||||
|
// @todo this is a little hack to make the assembler happy;
|
||||||
|
// certain assembler routines are -for now- always included and *require* an irq.irq routine to be present
|
||||||
|
val pos = module.statements.last().position
|
||||||
|
val dummyIrqBlock = Block("irq", address = null, statements = mutableListOf(
|
||||||
|
Subroutine("irq", listOf(), listOf(), listOf(), listOf(), setOf(), null, true,mutableListOf(), pos)
|
||||||
|
), position = pos)
|
||||||
|
dummyIrqBlock.linkParents(module)
|
||||||
|
module.statements.add(dummyIrqBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,12 +247,7 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
// subroutine must contain at least one 'return' or 'goto'
|
// subroutine must contain at least one 'return' or 'goto'
|
||||||
// (or if it has an asm block, that must contain a 'rts' or 'jmp')
|
// (or if it has an asm block, that must contain a 'rts' or 'jmp')
|
||||||
if(subroutine.statements.count { it is Return || it is Jump } == 0) {
|
if(subroutine.statements.count { it is Return || it is Jump } == 0) {
|
||||||
val amountOfRtsInAsm = subroutine.statements
|
if (subroutine.amountOfRtsInAsm() == 0) {
|
||||||
.asSequence()
|
|
||||||
.filter { it is InlineAssembly }
|
|
||||||
.map { (it as InlineAssembly).assembly }
|
|
||||||
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
|
||||||
if (amountOfRtsInAsm == 0) {
|
|
||||||
if (subroutine.returntypes.isNotEmpty()) {
|
if (subroutine.returntypes.isNotEmpty()) {
|
||||||
// for asm subroutines with an address, no statement check is possible.
|
// for asm subroutines with an address, no statement check is possible.
|
||||||
if (subroutine.asmAddress == null)
|
if (subroutine.asmAddress == null)
|
||||||
|
@ -101,7 +101,8 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
|
|||||||
|
|
||||||
if(subroutine.returntypes.isEmpty()) {
|
if(subroutine.returntypes.isEmpty()) {
|
||||||
// add the implicit return statement at the end (if it's not there yet), but only if it's not a kernel routine.
|
// add the implicit return statement at the end (if it's not there yet), but only if it's not a kernel routine.
|
||||||
if(subroutine.asmAddress==null) {
|
// and if an assembly block doesn't contain a rts/rti
|
||||||
|
if(subroutine.asmAddress==null && subroutine.amountOfRtsInAsm()==0) {
|
||||||
if (subroutine.statements.lastOrNull {it !is VarDecl} !is Return) {
|
if (subroutine.statements.lastOrNull {it !is VarDecl} !is Return) {
|
||||||
val returnStmt = Return(emptyList(), subroutine.position)
|
val returnStmt = Return(emptyList(), subroutine.position)
|
||||||
returnStmt.linkParents(subroutine)
|
returnStmt.linkParents(subroutine)
|
||||||
|
@ -433,49 +433,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
|
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
|
||||||
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
|
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
|
||||||
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
|
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
|
||||||
when (call) {
|
" jsr prog8_lib.${call.toString().toLowerCase()}"
|
||||||
Syscall.FUNC_SET_IRQVEC ->
|
|
||||||
"""
|
|
||||||
sei
|
|
||||||
lda #<_prog8_irq_handler
|
|
||||||
sta c64.CINV
|
|
||||||
lda #>_prog8_irq_handler
|
|
||||||
sta c64.CINV+1
|
|
||||||
cli
|
|
||||||
jmp +
|
|
||||||
|
|
||||||
_prog8_irq_handler jsr irq.irq
|
|
||||||
jmp c64.IRQDFRT ; continue with normal kernel irq routine
|
|
||||||
+
|
|
||||||
"""
|
|
||||||
Syscall.FUNC_SET_IRQVEC_EXCL ->
|
|
||||||
"""
|
|
||||||
sei
|
|
||||||
lda #<_prog8_irq_handler_excl
|
|
||||||
sta c64.CINV
|
|
||||||
lda #>_prog8_irq_handler_excl
|
|
||||||
sta c64.CINV+1
|
|
||||||
cli
|
|
||||||
jmp +
|
|
||||||
|
|
||||||
_prog8_irq_handler_excl
|
|
||||||
jsr irq.irq
|
|
||||||
lda ${'$'}dc0d ; acknowledge CIA interrupt
|
|
||||||
jmp c64.IRQDFEND ; end irq processing - don't call kernel
|
|
||||||
+
|
|
||||||
"""
|
|
||||||
Syscall.FUNC_RESTORE_IRQVEC ->
|
|
||||||
"""
|
|
||||||
sei
|
|
||||||
lda #<c64.IRQDFRT
|
|
||||||
sta c64.CINV
|
|
||||||
lda #>c64.IRQDFRT
|
|
||||||
sta c64.CINV+1
|
|
||||||
cli
|
|
||||||
"""
|
|
||||||
else -> " jsr prog8_lib.${call.toString().toLowerCase()}"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Opcode.BREAKPOINT -> {
|
Opcode.BREAKPOINT -> {
|
||||||
breakpointCounter++
|
breakpointCounter++
|
||||||
|
@ -54,10 +54,7 @@ val BuiltinFunctions = mapOf(
|
|||||||
"clear_carry" to FunctionSignature(false, emptyList(), null),
|
"clear_carry" to FunctionSignature(false, emptyList(), null),
|
||||||
"set_irqd" to FunctionSignature(false, emptyList(), null),
|
"set_irqd" to FunctionSignature(false, emptyList(), null),
|
||||||
"clear_irqd" to FunctionSignature(false, emptyList(), null),
|
"clear_irqd" to FunctionSignature(false, emptyList(), null),
|
||||||
"set_irqvec" to FunctionSignature(false, emptyList(), null),
|
"memcopy" to FunctionSignature(false, listOf(
|
||||||
"set_irqvec_excl" to FunctionSignature(false, emptyList(), null),
|
|
||||||
"restore_irqvec" to FunctionSignature(false, emptyList(), null),
|
|
||||||
"memcopy" to FunctionSignature(false, listOf(
|
|
||||||
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
|
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
|
||||||
BuiltinFunctionParam("to", IntegerDatatypes + IterableDatatypes),
|
BuiltinFunctionParam("to", IntegerDatatypes + IterableDatatypes),
|
||||||
BuiltinFunctionParam("numbytes", IntegerDatatypes)), null),
|
BuiltinFunctionParam("numbytes", IntegerDatatypes)), null),
|
||||||
|
@ -70,9 +70,6 @@ enum class Syscall(val callNr: Short) {
|
|||||||
FUNC_SUM_UW(132),
|
FUNC_SUM_UW(132),
|
||||||
FUNC_SUM_W(133),
|
FUNC_SUM_W(133),
|
||||||
FUNC_SUM_F(134),
|
FUNC_SUM_F(134),
|
||||||
FUNC_SET_IRQVEC(135),
|
|
||||||
FUNC_SET_IRQVEC_EXCL(136),
|
|
||||||
FUNC_RESTORE_IRQVEC(137),
|
|
||||||
FUNC_MEMCOPY(138)
|
FUNC_MEMCOPY(138)
|
||||||
|
|
||||||
// note: not all builtin functions of the Prog8 language are present as functions:
|
// note: not all builtin functions of the Prog8 language are present as functions:
|
||||||
@ -133,7 +130,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
private val rnd = Random()
|
private val rnd = Random()
|
||||||
private val bootTime = System.currentTimeMillis()
|
private val bootTime = System.currentTimeMillis()
|
||||||
private lateinit var currentIns: Instruction
|
private lateinit var currentIns: Instruction
|
||||||
private var irqStartInstruction: Instruction? = null // set to first instr of irq routine, if any
|
private var irqStartInstruction: Instruction? = null
|
||||||
var sourceLine: String = ""
|
var sourceLine: String = ""
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@ -161,7 +158,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
P_irqd = false
|
P_irqd = false
|
||||||
sourceLine = ""
|
sourceLine = ""
|
||||||
currentIns = this.program[0]
|
currentIns = this.program[0]
|
||||||
irqStartInstruction = null
|
irqStartInstruction = labels["irq.irq"] // set to first instr of irq routine, if any
|
||||||
}
|
}
|
||||||
|
|
||||||
fun step(instructionCount: Int = 5000) {
|
fun step(instructionCount: Int = 5000) {
|
||||||
@ -1647,12 +1644,6 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val value = heap.get(iterable.heapId)
|
val value = heap.get(iterable.heapId)
|
||||||
evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0))
|
evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0))
|
||||||
}
|
}
|
||||||
Syscall.FUNC_SET_IRQVEC, Syscall.FUNC_SET_IRQVEC_EXCL -> {
|
|
||||||
irqStartInstruction = labels["irq.irq"]
|
|
||||||
}
|
|
||||||
Syscall.FUNC_RESTORE_IRQVEC -> {
|
|
||||||
irqStartInstruction = null
|
|
||||||
}
|
|
||||||
Syscall.FUNC_MEMCOPY -> {
|
Syscall.FUNC_MEMCOPY -> {
|
||||||
val numbytes = evalstack.pop().integerValue()
|
val numbytes = evalstack.pop().integerValue()
|
||||||
val to = evalstack.pop().integerValue()
|
val to = evalstack.pop().integerValue()
|
||||||
|
@ -633,20 +633,6 @@ set_irqd() / clear_irqd()
|
|||||||
Set (or clear) the CPU status register Interrupt Disable flag. No result value.
|
Set (or clear) the CPU status register Interrupt Disable flag. No result value.
|
||||||
(translated into ``SEI`` or ``CLI`` cpu instruction)
|
(translated into ``SEI`` or ``CLI`` cpu instruction)
|
||||||
|
|
||||||
set_irqvec_excl()
|
|
||||||
Sets the system's IRQ vector to the special ``irq.irq`` subroutine exclusively -- the system's
|
|
||||||
default IRQ handler is no longer called. The routine should be defined as a parameterless subroutine
|
|
||||||
``irq`` in a block ``irq``.
|
|
||||||
|
|
||||||
set_irqvec()
|
|
||||||
Add the special ``irq.irq`` subroutine to the system's IRQ vector -- the system's
|
|
||||||
default IRQ handler will still be called after your custom subroutine finishes.
|
|
||||||
The routine should be defined as a parameterless subroutine
|
|
||||||
``irq`` in a block ``irq``.
|
|
||||||
|
|
||||||
restore_irqvec()
|
|
||||||
Restore the IRQ vector to the default system IRQ handling subroutine.
|
|
||||||
|
|
||||||
rsave()
|
rsave()
|
||||||
Saves the CPU registers and the status flags.
|
Saves the CPU registers and the status flags.
|
||||||
You can now more or less 'safely' use the registers directly, until you
|
You can now more or less 'safely' use the registers directly, until you
|
||||||
|
@ -94,6 +94,44 @@
|
|||||||
|
|
||||||
; ---- end of VIC-II registers ----
|
; ---- end of VIC-II registers ----
|
||||||
|
|
||||||
|
; ---- CIA 1 & 2 registers ----
|
||||||
|
|
||||||
|
memory ubyte CIA1PRA = $DC00 ; CIA 1 DRA, keyboard column drive
|
||||||
|
memory ubyte CIA1PRB = $DC01 ; CIA 1 DRB, keyboard row port
|
||||||
|
memory ubyte CIA1DDRA = $DC02 ; CIA 1 DDRA, keyboard column
|
||||||
|
memory ubyte CIA1DDRB = $DC03 ; CIA 1 DDRB, keyboard row
|
||||||
|
memory ubyte CIA1TALO = $DC04 ; CIA 1 timer A low byte
|
||||||
|
memory ubyte CIA1TAHI = $DC05 ; CIA 1 timer A high byte
|
||||||
|
memory ubyte CIA1TBLO = $DC06 ; CIA 1 timer B low byte
|
||||||
|
memory ubyte CIA1TBHI = $DC07 ; CIA 1 timer B high byte
|
||||||
|
memory ubyte CIA1TOD10 = $DC08 ; time of day, 1/10 sec.
|
||||||
|
memory ubyte CIA1TODS = $DC09 ; time of day, seconds
|
||||||
|
memory ubyte CIA1TODM = $DC0A ; time of day, minutes
|
||||||
|
memory ubyte CIA1TODH = $DC0B ; time of day, hours
|
||||||
|
memory ubyte CIA1SDR = $DC0C ; Serial Data Register
|
||||||
|
memory ubyte CIA1ICR = $DC0D
|
||||||
|
memory ubyte CIA1CRA = $DC0E
|
||||||
|
memory ubyte CIA1CRB = $DC0F
|
||||||
|
|
||||||
|
memory ubyte CIA2PRA = $DD00 ; CIA 2 DRA, serial port and video address
|
||||||
|
memory ubyte CIA2PRB = $DD01 ; CIA 2 DRB, RS232 port / USERPORT
|
||||||
|
memory ubyte CIA2DDRA = $DD02 ; CIA 2 DDRA, serial port and video address
|
||||||
|
memory ubyte CIA2DDRB = $DD03 ; CIA 2 DDRB, RS232 port / USERPORT
|
||||||
|
memory ubyte CIA2TALO = $DD04 ; CIA 2 timer A low byte
|
||||||
|
memory ubyte CIA2TAHI = $DD05 ; CIA 2 timer A high byte
|
||||||
|
memory ubyte CIA2TBLO = $DD06 ; CIA 2 timer B low byte
|
||||||
|
memory ubyte CIA2TBHI = $DD07 ; CIA 2 timer B high byte
|
||||||
|
memory ubyte CIA2TOD10 = $DD08 ; time of day, 1/10 sec.
|
||||||
|
memory ubyte CIA2TODS = $DD09 ; time of day, seconds
|
||||||
|
memory ubyte CIA2TODM = $DD0A ; time of day, minutes
|
||||||
|
memory ubyte CIA2TODH = $DD0B ; time of day, hours
|
||||||
|
memory ubyte CIA2SDR = $DD0C ; Serial Data Register
|
||||||
|
memory ubyte CIA2ICR = $DD0D
|
||||||
|
memory ubyte CIA2CRA = $DD0E
|
||||||
|
memory ubyte CIA2CRB = $DD0F
|
||||||
|
|
||||||
|
; ---- end of CIA registers ----
|
||||||
|
|
||||||
; ---- C64 basic and kernal ROM float constants and functions ----
|
; ---- C64 basic and kernal ROM float constants and functions ----
|
||||||
|
|
||||||
; note: the fac1 and fac2 are working registers and take 6 bytes each,
|
; note: the fac1 and fac2 are working registers and take 6 bytes each,
|
||||||
|
@ -408,7 +408,120 @@ _mod2b lda #0 ; self-modified
|
|||||||
bne -
|
bne -
|
||||||
_done rts
|
_done rts
|
||||||
.pend
|
.pend
|
||||||
}}
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
asmsub set_irqvec_excl() -> clobbers(A) -> () {
|
||||||
|
%asm {{
|
||||||
|
sei
|
||||||
|
lda #<_irq_handler
|
||||||
|
sta c64.CINV
|
||||||
|
lda #>_irq_handler
|
||||||
|
sta c64.CINV+1
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
_irq_handler jsr irq.irq
|
||||||
|
lda #$ff
|
||||||
|
sta c64.VICIRQ ; acknowledge raster irq
|
||||||
|
lda c64.CIA1ICR ; acknowledge CIA1 interrupt
|
||||||
|
jmp c64.IRQDFEND ; end irq processing - don't call kernel
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub set_irqvec() -> clobbers(A) -> () {
|
||||||
|
%asm {{
|
||||||
|
sei
|
||||||
|
lda #<_irq_handler
|
||||||
|
sta c64.CINV
|
||||||
|
lda #>_irq_handler
|
||||||
|
sta c64.CINV+1
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
_irq_handler jsr irq.irq
|
||||||
|
jmp c64.IRQDFRT ; continue with normal kernel irq routine
|
||||||
|
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asmsub restore_irqvec() -> clobbers() -> () {
|
||||||
|
%asm {{
|
||||||
|
sei
|
||||||
|
lda #<c64.IRQDFRT
|
||||||
|
sta c64.CINV
|
||||||
|
lda #>c64.IRQDFRT
|
||||||
|
sta c64.CINV+1
|
||||||
|
lda #0
|
||||||
|
sta c64.IREQMASK ; disable raster irq
|
||||||
|
lda #%10000001
|
||||||
|
sta c64.CIA1ICR ; restore CIA1 irq
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asmsub set_rasterirq(uword rasterpos @ AY) -> clobbers(A) -> () {
|
||||||
|
%asm {{
|
||||||
|
sei
|
||||||
|
jsr _setup_raster_irq
|
||||||
|
lda #<_raster_irq_handler
|
||||||
|
sta c64.CINV
|
||||||
|
lda #>_raster_irq_handler
|
||||||
|
sta c64.CINV+1
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
|
||||||
|
_raster_irq_handler
|
||||||
|
jsr irq.irq
|
||||||
|
lda #$ff
|
||||||
|
sta c64.VICIRQ ; acknowledge raster irq
|
||||||
|
jmp c64.IRQDFRT
|
||||||
|
|
||||||
|
_setup_raster_irq
|
||||||
|
pha
|
||||||
|
lda #%01111111
|
||||||
|
sta c64.CIA1ICR ; "switch off" interrupts signals from cia-1
|
||||||
|
sta c64.CIA2ICR ; "switch off" interrupts signals from cia-2
|
||||||
|
and c64.SCROLY
|
||||||
|
sta c64.SCROLY ; clear most significant bit of raster position
|
||||||
|
lda c64.CIA1ICR ; ack previous irq
|
||||||
|
lda c64.CIA2ICR ; ack previous irq
|
||||||
|
pla
|
||||||
|
sta c64.RASTER ; set the raster line number where interrupt should occur
|
||||||
|
cpy #0
|
||||||
|
beq +
|
||||||
|
lda c64.SCROLY
|
||||||
|
ora #%10000000
|
||||||
|
sta c64.SCROLY ; set most significant bit of raster position
|
||||||
|
+ lda #%00000001
|
||||||
|
sta c64.IREQMASK ;enable raster interrupt signals from vic
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub set_rasterirq_excl(uword rasterpos @ AY) -> clobbers(A) -> () {
|
||||||
|
%asm {{
|
||||||
|
sei
|
||||||
|
jsr set_rasterirq._setup_raster_irq
|
||||||
|
lda #<_raster_irq_handler
|
||||||
|
sta c64.CINV
|
||||||
|
lda #>_raster_irq_handler
|
||||||
|
sta c64.CINV+1
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
|
||||||
|
_raster_irq_handler
|
||||||
|
jsr irq.irq
|
||||||
|
lda #$ff
|
||||||
|
sta c64.VICIRQ ; acknowledge raster irq
|
||||||
|
jmp c64.IRQDFEND ; end irq processing - don't call kernel
|
||||||
|
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} ; ------ end of block c64utils
|
} ; ------ end of block c64utils
|
||||||
|
|
||||||
|
@ -476,7 +476,6 @@ abs_f .proc
|
|||||||
|
|
||||||
add_w .proc
|
add_w .proc
|
||||||
; -- push word+word / uword+uword
|
; -- push word+word / uword+uword
|
||||||
; @todo INLINE THIS
|
|
||||||
inx
|
inx
|
||||||
clc
|
clc
|
||||||
lda ESTACK_LO,x
|
lda ESTACK_LO,x
|
||||||
@ -490,7 +489,6 @@ add_w .proc
|
|||||||
|
|
||||||
sub_w .proc
|
sub_w .proc
|
||||||
; -- push word-word
|
; -- push word-word
|
||||||
; @todo INLINE THIS
|
|
||||||
inx
|
inx
|
||||||
sec
|
sec
|
||||||
lda ESTACK_LO+1,x
|
lda ESTACK_LO+1,x
|
||||||
|
Loading…
Reference in New Issue
Block a user