From 1e6d7673bc6b93747db7b64be003ca9adfeb0b65 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 14 May 2023 23:11:24 +0200 Subject: [PATCH 1/4] update cx16 keyhandler example to r43 keyboard changes --- examples/cx16/keyboardhandler.p8 | 94 +++++++++----------------------- 1 file changed, 26 insertions(+), 68 deletions(-) diff --git a/examples/cx16/keyboardhandler.p8 b/examples/cx16/keyboardhandler.p8 index 8c9b18798..6f12d1768 100644 --- a/examples/cx16/keyboardhandler.p8 +++ b/examples/cx16/keyboardhandler.p8 @@ -2,99 +2,57 @@ %zeropage basicsafe %option no_sysinit -; The documentation for custom PS2 key handlers can be found here: +; The documentation for a custom key handler can be found here: ; https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler main { sub start() { - txt.print("ps2 custom key handler test - press keys! esc to quit!\n") + txt.print("custom key handler test - press keys! esc to quit!\n") sys.set_irqd() uword old_keyhdl = cx16.KEYHDL - cx16.KEYHDL = &keyboard_scancode_handler + cx16.KEYHDL = &main.key_handler.asm_hook sys.clear_irqd() bool escape_pressed while not escape_pressed { - handle_keyboard_event() + ; do nothing here, just wait until ESC is pressed } + sys.set_irqd() cx16.KEYHDL = old_keyhdl sys.clear_irqd() } - ; Keyboard handler communication variables. - ; these need to be in block scope instead of in a subroutine, - ; so that they won't get overwritten with initialization values every time. - ; The assembly keyboard handler will set these, prog8 will read them. - bool @shared keyhdl_event ; is there a keyboard event to handle? - ubyte @shared keyhdl_prefix - ubyte @shared keyhdl_scancode - ubyte @shared keyhdl_updown - - sub handle_keyboard_event() { - ; Potentially handle keyboard event. - ; Note that we do this from the program's main loop instead of - ; the actual keyboard handler routine itself. - ; The reason for this is documented below in the handler assembly routine. - if not keyhdl_event - return - keyhdl_event = false - txt.print_ubhex(keyhdl_prefix, true) - txt.chrout(':') - txt.print_ubhex(keyhdl_scancode, true) + sub key_handler(ubyte keycode) -> bool { + txt.print_ubhex(keycode, true) txt.spc() - if keyhdl_updown + if keycode & $80 txt.chrout('u') else txt.chrout('d') txt.nl() - if keyhdl_prefix==0 and keyhdl_scancode==119 and keyhdl_updown { - ; escape was pressed! exit back to basic - main.start.escape_pressed = true + if keycode==$6e { + main.start.escape_pressed=true + } + return false ; this eats the keypress - return true if you want to pass it through + + asmsub asm_hook(ubyte keycode @A) -> ubyte @A { + %asm {{ + sta key_handler.keycode + pha + jsr key_handler + tay + pla + cpy #0 + beq + + rts ++ tya + rts + }} } } - asmsub keyboard_scancode_handler() { - - ; NOTE that the keyboard handler is an asm subroutine. - ; Unfortunately is it not possible to use prog8 code or calls here, - ; because the X register gets overwritten here (to store the prefix byte) - ; and prog8 uses the X register internally (for the evaluation stack). - ; So it is unsafe to call prog8 code from here because the evaluation stack pointer - ; will be invalid which produces undefined results. - ; So, instead, we store the various keyboard event bytes and signal - ; the main prog8 program that a keyboard event has occurred. - ; It then processes it independently from the assembly code here. - ; - ; Unfortunately this also means you cannot decide from that prog8 code - ; if the keyboard press should be consumed/ignored or put into the keyboard queue - ; (this is controlled by returning 0 or 1 in register A here) - ; - ; see: - ; https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler - - %asm {{ - php - pha - phx - stz keyhdl_updown - bcc + - inc keyhdl_updown -+ stx keyhdl_prefix - sta keyhdl_scancode - lda #1 - sta keyhdl_event - ; we can do additional stuff here and decide if we want to - ; consume the key event or not (A=0 or A!=0) - plx - pla - lda #0 ;By setting A=0 we will remove this key event for now - tax - plp - rts - }} - } } From 70cd4fedbe260efa355be16c11726aec09d2f9ba Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 14 May 2023 23:29:04 +0200 Subject: [PATCH 2/4] Revert "update cx16 keyhandler example to r43 keyboard changes" This reverts commit 1e6d7673bc6b93747db7b64be003ca9adfeb0b65. --- examples/cx16/keyboardhandler.p8 | 94 +++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/examples/cx16/keyboardhandler.p8 b/examples/cx16/keyboardhandler.p8 index 6f12d1768..8c9b18798 100644 --- a/examples/cx16/keyboardhandler.p8 +++ b/examples/cx16/keyboardhandler.p8 @@ -2,57 +2,99 @@ %zeropage basicsafe %option no_sysinit -; The documentation for a custom key handler can be found here: +; The documentation for custom PS2 key handlers can be found here: ; https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler main { sub start() { - txt.print("custom key handler test - press keys! esc to quit!\n") + txt.print("ps2 custom key handler test - press keys! esc to quit!\n") sys.set_irqd() uword old_keyhdl = cx16.KEYHDL - cx16.KEYHDL = &main.key_handler.asm_hook + cx16.KEYHDL = &keyboard_scancode_handler sys.clear_irqd() bool escape_pressed while not escape_pressed { - ; do nothing here, just wait until ESC is pressed + handle_keyboard_event() } - sys.set_irqd() cx16.KEYHDL = old_keyhdl sys.clear_irqd() } - sub key_handler(ubyte keycode) -> bool { - txt.print_ubhex(keycode, true) + ; Keyboard handler communication variables. + ; these need to be in block scope instead of in a subroutine, + ; so that they won't get overwritten with initialization values every time. + ; The assembly keyboard handler will set these, prog8 will read them. + bool @shared keyhdl_event ; is there a keyboard event to handle? + ubyte @shared keyhdl_prefix + ubyte @shared keyhdl_scancode + ubyte @shared keyhdl_updown + + sub handle_keyboard_event() { + ; Potentially handle keyboard event. + ; Note that we do this from the program's main loop instead of + ; the actual keyboard handler routine itself. + ; The reason for this is documented below in the handler assembly routine. + if not keyhdl_event + return + keyhdl_event = false + txt.print_ubhex(keyhdl_prefix, true) + txt.chrout(':') + txt.print_ubhex(keyhdl_scancode, true) txt.spc() - if keycode & $80 + if keyhdl_updown txt.chrout('u') else txt.chrout('d') txt.nl() - if keycode==$6e { - main.start.escape_pressed=true - } - return false ; this eats the keypress - return true if you want to pass it through - - asmsub asm_hook(ubyte keycode @A) -> ubyte @A { - %asm {{ - sta key_handler.keycode - pha - jsr key_handler - tay - pla - cpy #0 - beq + - rts -+ tya - rts - }} + if keyhdl_prefix==0 and keyhdl_scancode==119 and keyhdl_updown { + ; escape was pressed! exit back to basic + main.start.escape_pressed = true } } + asmsub keyboard_scancode_handler() { + + ; NOTE that the keyboard handler is an asm subroutine. + ; Unfortunately is it not possible to use prog8 code or calls here, + ; because the X register gets overwritten here (to store the prefix byte) + ; and prog8 uses the X register internally (for the evaluation stack). + ; So it is unsafe to call prog8 code from here because the evaluation stack pointer + ; will be invalid which produces undefined results. + ; So, instead, we store the various keyboard event bytes and signal + ; the main prog8 program that a keyboard event has occurred. + ; It then processes it independently from the assembly code here. + ; + ; Unfortunately this also means you cannot decide from that prog8 code + ; if the keyboard press should be consumed/ignored or put into the keyboard queue + ; (this is controlled by returning 0 or 1 in register A here) + ; + ; see: + ; https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler + + %asm {{ + php + pha + phx + stz keyhdl_updown + bcc + + inc keyhdl_updown ++ stx keyhdl_prefix + sta keyhdl_scancode + lda #1 + sta keyhdl_event + ; we can do additional stuff here and decide if we want to + ; consume the key event or not (A=0 or A!=0) + plx + pla + lda #0 ;By setting A=0 we will remove this key event for now + tax + plp + rts + }} + } } From 415c599310d8e1bb9c0a8bd2b6b48c92bb68be40 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 14 May 2023 23:33:57 +0200 Subject: [PATCH 3/4] update cx16 keyhandler example to r43 keyboard changes --- examples/cx16/keyboardhandler.p8 | 46 +++++++++----------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/examples/cx16/keyboardhandler.p8 b/examples/cx16/keyboardhandler.p8 index 8c9b18798..ede7f157c 100644 --- a/examples/cx16/keyboardhandler.p8 +++ b/examples/cx16/keyboardhandler.p8 @@ -9,17 +9,16 @@ main { sub start() { - txt.print("ps2 custom key handler test - press keys! esc to quit!\n") + txt.print("custom key handler test - press keys! esc to quit!\n") sys.set_irqd() uword old_keyhdl = cx16.KEYHDL cx16.KEYHDL = &keyboard_scancode_handler sys.clear_irqd() - bool escape_pressed - while not escape_pressed { - handle_keyboard_event() + while handle_keyboard_event() { } + sys.set_irqd() cx16.KEYHDL = old_keyhdl sys.clear_irqd() @@ -30,70 +29,49 @@ main { ; so that they won't get overwritten with initialization values every time. ; The assembly keyboard handler will set these, prog8 will read them. bool @shared keyhdl_event ; is there a keyboard event to handle? - ubyte @shared keyhdl_prefix ubyte @shared keyhdl_scancode - ubyte @shared keyhdl_updown - sub handle_keyboard_event() { + sub handle_keyboard_event() -> bool { ; Potentially handle keyboard event. ; Note that we do this from the program's main loop instead of ; the actual keyboard handler routine itself. ; The reason for this is documented below in the handler assembly routine. if not keyhdl_event - return + return true keyhdl_event = false - txt.print_ubhex(keyhdl_prefix, true) - txt.chrout(':') txt.print_ubhex(keyhdl_scancode, true) txt.spc() - if keyhdl_updown + if keyhdl_scancode & $80 txt.chrout('u') else txt.chrout('d') txt.nl() - if keyhdl_prefix==0 and keyhdl_scancode==119 and keyhdl_updown { - ; escape was pressed! exit back to basic - main.start.escape_pressed = true - } + return keyhdl_scancode!=$6e ; escape breaks the loop } asmsub keyboard_scancode_handler() { - ; NOTE that the keyboard handler is an asm subroutine. ; Unfortunately is it not possible to use prog8 code or calls here, - ; because the X register gets overwritten here (to store the prefix byte) - ; and prog8 uses the X register internally (for the evaluation stack). + ; because the X register gets overwritten here by the kernal. + ; Pog8 uses the X register internally (for the software eval stack). ; So it is unsafe to call prog8 code from here because the evaluation stack pointer ; will be invalid which produces undefined results. ; So, instead, we store the various keyboard event bytes and signal ; the main prog8 program that a keyboard event has occurred. ; It then processes it independently from the assembly code here. ; - ; Unfortunately this also means you cannot decide from that prog8 code + ; Unfortunately this also means you cannot decide easily from that prog8 code ; if the keyboard press should be consumed/ignored or put into the keyboard queue ; (this is controlled by returning 0 or 1 in register A here) - ; - ; see: - ; https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler %asm {{ - php pha - phx - stz keyhdl_updown - bcc + - inc keyhdl_updown -+ stx keyhdl_prefix sta keyhdl_scancode lda #1 sta keyhdl_event - ; we can do additional stuff here and decide if we want to - ; consume the key event or not (A=0 or A!=0) - plx pla - lda #0 ;By setting A=0 we will remove this key event for now - tax - plp + + lda #0 ; By setting A=0 we will eat this key event. leave A unchanged to pass it through. rts }} } From dea7f3755347c2f0d8edb5eef6f7634b776b94e6 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 15 May 2023 20:33:20 +0200 Subject: [PATCH 4/4] vm: fix % result when dividing by 0 --- virtualmachine/src/prog8/vm/VirtualMachine.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 13c0c8a5b..9918fa3d5 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -1270,7 +1270,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / right } "%" -> { - if(right==0.toUByte()) 0xffu + if(right==0.toUByte()) 0u else left % right } else -> throw IllegalArgumentException("operator byte $operator") @@ -1286,7 +1286,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / value } "%" -> { - if(value==0.toUByte()) 0xffu + if(value==0.toUByte()) 0u else left % value } else -> throw IllegalArgumentException("operator byte $operator") @@ -1298,7 +1298,7 @@ class VirtualMachine(irProgram: IRProgram) { val left = registers.getUB(reg1) val right = registers.getUB(reg2) val division = if(right==0.toUByte()) 0xffu else left / right - val remainder = if(right==0.toUByte()) 0xffu else left % right + val remainder = if(right==0.toUByte()) 0u else left % right valueStack.push(division.toUByte()) valueStack.push(remainder.toUByte()) } @@ -1306,7 +1306,7 @@ class VirtualMachine(irProgram: IRProgram) { private fun divAndModConstUByte(reg1: Int, value: UByte) { val left = registers.getUB(reg1) val division = if(value==0.toUByte()) 0xffu else left / value - val remainder = if(value==0.toUByte()) 0xffu else left % value + val remainder = if(value==0.toUByte()) 0u else left % value valueStack.push(division.toUByte()) valueStack.push(remainder.toUByte()) } @@ -1315,7 +1315,7 @@ class VirtualMachine(irProgram: IRProgram) { val left = registers.getUW(reg1) val right = registers.getUW(reg2) val division = if(right==0.toUShort()) 0xffffu else left / right - val remainder = if(right==0.toUShort()) 0xffffu else left % right + val remainder = if(right==0.toUShort()) 0u else left % right valueStack.pushw(division.toUShort()) valueStack.pushw(remainder.toUShort()) } @@ -1323,7 +1323,7 @@ class VirtualMachine(irProgram: IRProgram) { private fun divAndModConstUWord(reg1: Int, value: UShort) { val left = registers.getUW(reg1) val division = if(value==0.toUShort()) 0xffffu else left / value - val remainder = if(value==0.toUShort()) 0xffffu else left % value + val remainder = if(value==0.toUShort()) 0u else left % value valueStack.pushw(division.toUShort()) valueStack.pushw(remainder.toUShort()) } @@ -1337,7 +1337,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / right } "%" -> { - if(right==0.toUByte()) 0xffu + if(right==0.toUByte()) 0u else left % right } else -> throw IllegalArgumentException("operator byte $operator") @@ -1389,7 +1389,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / right } "%" -> { - if(right==0.toUShort()) 0xffffu + if(right==0.toUShort()) 0u else left % right } else -> throw IllegalArgumentException("operator word $operator") @@ -1405,7 +1405,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / value } "%" -> { - if(value==0.toUShort()) 0xffffu + if(value==0.toUShort()) 0u else left % value } else -> throw IllegalArgumentException("operator word $operator") @@ -1422,7 +1422,7 @@ class VirtualMachine(irProgram: IRProgram) { else left / right } "%" -> { - if(right==0.toUShort()) 0xffffu + if(right==0.toUShort()) 0u else left % right } else -> throw IllegalArgumentException("operator word $operator")