neilsf / xc-basic3

A BASIC cross compiler for MOS 6502-based machines
MIT License
45 stars 5 forks source link

[X16 Beta] Function Key() causes Fatal error #227

Closed atariVCS closed 1 year ago

atariVCS commented 1 year ago

When I put Key() anywhere in my X16-targeted program, I get an assembler error:

... xcbasic3 .\LORDS\tests.bas TESTS.PRG --target=x16 ERROR There has been an error while trying to execute DASM, please see the bellow message. Tried to execute: "dasm.exe" "...AppData\Local\Temp\xcbtmp_1B564149.asm" -o"TESTS.PRG" -s...\AppData\Local\Temp\xcbtmp_1B564149.sym --- Unresolved Symbol List I_VERA_MOV_STRING_IMPORTED 0000 ???? (R ) I_STR_WTOS_IMPORTED 0000 ???? (R ) I_STRREAD_IMPORTED 0000 ???? (R ) I_BINREAD_IMPORTED 0000 ???? (R ) I_LTOF_IMPORTED 0000 ???? (R ) I_NUCLEUS_DIVBYTE_IMPORTED 0000 ???? (R ) I_F_clock_month_IMPORTED 0000 ???? (R ) I_F_mousex_IMPORTED 0000 ???? (R ) I_F_entropy_IMPORTED 0000 ???? (R ) I_FMOD_IMPORTED 0000 ???? (R ) I_STR_RIGHT_IMPORTED 0000 ???? (R ) I_NUCLEUS_DIV24_IMPORTED 0000 ???? (R ) I_F_src4.mouse_get_IMPORTED 0000 ???? (R ) I_IO_INPUT_IMPORTED 0000 ???? (R ) I_STRREMOV_SC_IMPORTED 0000 ???? (R ) I_STDLIB_BYTE_TO_PETSCII_IMPORTED 0000 ???? (R ) IO_KEYR 0000 ???? (R ) I_F_mousey_IMPORTED 0000 ???? (R ) I_NUCLEUS_DIV16_IMPORTED 0000 ???? (R ) I_F_memcpyvm_long_word_word_IMPORTED 0000 ???? (R ) I_NUCLEUS_MULU16_IMPORTED 0000 ???? (R ) I_CALC_SCRROWPTR_IMPORTED 0000 ???? (R ) I_F_memcpymv_word_long_word_IMPORTED 0000 ???? (R ) I_STDLIB_TAB_IMPORTED 0000 ???? (R ) I_RANDOMIZE_IMPORTED 0000 ???? (R ) I_STRCMP_IMPORTED 0000 ???? (R ) I_STR_UCASE_IMPORTED 0000 ???? (R ) I_F_mouseoff_IMPORTED 0000 ???? (R ) I_IO_READST_IMPORTED 0000 ???? (R ) I_STR_LTOS_IMPORTED 0000 ???? (R ) I_MEMCPY_IMPORTED 0000 ???? (R ) I_MEMSET_IMPORTED 0000 ???? (R ) I_F_mouseon_IMPORTED 0000 ???? (R ) I_F_clock_sec_IMPORTED 0000 ???? (R ) I_F_vpoke_long_byte_IMPORTED 0000 ???? (R ) IO_KEYW 0000 ???? (R ) I_STDLIB_PRINT_DECIMAL_IMPORTED 0000 ???? (R ) I_NUCLEUS_DIVU16_IMPORTED 0000 ???? (R ) I_MEMSHIFT_IMPORTED 0000 ???? (R ) I_EXP_IMPORTED 0000 ???? (R ) I_RUNTIME_ERROR_IMPORTED 0000 ???? (R ) I_FIN_IMPORTED 0000 ???? (R ) I_FPLIB_IMPORTED 0000 ???? (R ) I_SQRW_IMPORTED 0000 ???? (R ) I_F_clock_hour_IMPORTED 0000 ???? (R ) I_FOUT_IMPORTED 0000 ???? (R ) I_F_clock_day_IMPORTED 0000 ???? (R ) I_STR_TONULLTERM_IMPORTED 0000 ???? (R ) I_F_setclock_byte_byte_byte_byte_byte_byte_IMPORTED 0000 ???? (R ) I_F_vpeek_long_IMPORTED 0000 ???? (R ) I_STR_BTOS_IMPORTED 0000 ???? (R ) I_RNDL_IMPORTED 0000 ???? (R ) I_NUCLEUS_MULBYTE_IMPORTED 0000 ???? (R ) I_STR_CONCAT_IMPORTED 0000 ???? (R ) I_RESET_SCRVECTORS_IMPORTED 0000 ???? (R ) I_STR_LCASE_IMPORTED 0000 ???? (R ) I_PET2SC_IMPORTED 0000 ???? (R ) I_STDLIB_PRINT_BYTE_IMPORTED 0000 ???? (R ) I_F_clock_year_IMPORTED 0000 ???? (R ) I_STRSCRATCH_IMPORTED 0000 ???? (R ) I_STR_DTOS_IMPORTED 0000 ???? (R ) I_SQRL_IMPORTED 0000 ???? (R ) I_STR_MID_IMPORTED 0000 ???? (R ) I_NUCLEUS_MUL24_IMPORTED 0000 ???? (R ) I_F_mousebtn_IMPORTED 0000 ???? (R ) I_STR_LEFT_IMPORTED 0000 ???? (R ) I_F_vmemset_long_word_byte_IMPORTED 0000 ???? (R ) I_NUCLEUS_MUL16_IMPORTED 0000 ???? (R ) I_VERA_STRREMOV_SC_IMPORTED 0000 ???? (R ) I_F_clock_min_IMPORTED 0000 ???? (R ) I_BINWRITE_IMPORTED 0000 ???? (R ) I_STRWRITE_IMPORTED 0000 ???? (R ) I_VERA_SETADDR_IMPORTED 0000 ???? (R ) I_RND_IMPORTED 0000 ???? (R ) --- 74 Unresolved Symbols

Fatal assembly error: Source is not resolvable.

neilsf commented 1 year ago

Hi @atariVCS The KEY() function is not yet implemented for the X16. I've been trying to figure out how to read the currently pressed key on the X16, but couldn't find anything useful yet. Let me know if you have any tips. Thanks

atariVCS commented 1 year ago

Hi @neilsf

ah, that explains why it doesn't work. The KERNAL Routine for reading the oldest pressed Key on the "stdin" buffer (which is the keyboard unless someone reconfigures it) on the X16 is GETIN, $FFe4 GETIN writes the oldest petscii code in stdin-buffer into the accumulator - OR a 0 if the buffer is empty (no key pressed) GETIN also uses the X and Y register.

I've attached a small sample which I was able to build and run on the X16 read_character.zip

Kudos to Matt from "Retro Desk" for his great Assembler tutorial on youtube (lesson 8) - otherwise I wouldn't have known either :)

neilsf commented 1 year ago

The KERNAL Routine for reading the oldest pressed Key on the "stdin" buffer (which is the keyboard unless someone reconfigures it) on the X16 is GETIN, $FFe4

GETIN is a standard Commodore KERNAL function that you can access through the XC=BASIC command GET. It should work on the X16, too!

The KEY() function in XC=BASIC is different. It tests whether a specific key is actually depressed. (Note: not the buffered, but the actual state of a key) In C64, this is done by sending/reading bytes to/from CIA registers.

Not sure which one you need, GET or KEY()?

atariVCS commented 1 year ago

You are correct. GET should be good for now. KEY() works differently - I didn't realize that. For me, my issue is closed. For the nonetheless interesting question if/how it is possible to read the currently pressed key on keyboard I have asked the X16 developers and I hope to get a reply.

atariVCS commented 1 year ago

I already got the answer. Unlike on a C64, it is not possible on the X16 at hardware-level to check if a specific key is currently pressed. This is due to the PS/2 stuff we guess. In addition, the developer MooingLemur was so nice to explain the following:

There can also be several currently pressed keys. A machine language program can hook into the kernal key handler and track key on/key off events if it wants to track what keys are held. Example: https://github.com/X16Community/x16-docs/blob/master/X16%20Reference%20-%2002%20-%20Editor.md#custom-keyboard-scancode-handler. Without hooking into that, they only information a program gets is the petscii key code when a key down event happens. The main kernal interrupt service routine (called 60 times per second by default) will query the system microcontroller (which is connected to the PS/2 keyboard) and ask whether there's a key event in the microcontroller's buffer. If there is, the kernal fetches and processes it. It works the same way in the emulator, but of course the microcontroller itself is emulated.

Keep in mind holding down a key causes the keyboard itself to issue repeated key down events, so the computer doesn't "know" what keys are held down unless it chooses to track it, keeping state until a key up event is received.

So I guess implementing KEY() would be much more complicated than on a C64? Maybe it is sufficent to mark the KEY() function as unavailable on X16 for now.

neilsf commented 1 year ago

Thanks for the detailed info, @atariVCS For now, the KEY() function remains unimplemented for the X16. I will add a compile-time warning later (instead of failing compilation) but since this is only a beta branch yet, I'll leave it as it is for now.