![]() |
![]() |
#21 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 732
|
could you try
__aligned struct StandardPacket con_standard_packet; a lot of DOS things need to be aligned on 4 byte boundaries cause of BCPL pointers. |
![]() |
![]() |
#22 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
Quote:
No. The dos.library functions do nothing else than that: Put the packet on the stack. Of course, you need to make sure that you don't leave your function before you received the packet back from the handler. |
|
![]() |
![]() |
#23 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi Alkis and Thomas!
I don't know how to "align" the struct with VBCC, it doesn't recognise __aligned, would you know how? Best! |
![]() |
![]() |
#24 | |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 694
|
Quote:
guess you'd have to use a static variable Code:
#pragma pack(push,4) static struct StandardPacket con_standard_packet; #pragma pack(pop) which is ok if the function is not invoked parallel PS: and maybe you can omit the memset then, since it's initial zeroed. |
|
![]() |
![]() |
#25 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
In this particular case, alignment is not necessary. The CON-Handler is in C, and all pointers between the packet and the message are C-style pointers.
|
![]() |
![]() |
#26 | |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 732
|
Quote:
Code:
char foo[sizeof(struct StandardPacket)+4]; // 68 + 4 = 72 bytes struct StandardPacket *_con_standard_packet = (struct StandardPacket *)((ULONG) &foo[4] & ~3); memset(_con_standard_packet, 0, sizeof(struct StandardPacket)); Well, after Thomas' feedback this is not necessary. I'll leave it here as a technique to align something with a compiler that doesn't support align. |
|
![]() |
![]() |
#27 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi all!
I'm still "stuck": my code works but from your comments, I'm not sure that it's doing what it should... Any memset or free of the struct StandardPacket * still causes a crash ![]() You can see my current code here, am I missing something "obvious"? Cheers! |
![]() |
![]() |
#28 | |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 694
|
Quote:
this looks wrong: Code:
do { if(GetMsg(_con_reply_port)) { // Nothing to do } else { console_signal = 1L << _con_reply_port->mp_SigBit; received_signals = Wait(console_signal | SIGBREAKF_CTRL_C | controls_signal_playing_stopped()); break; } } while(TRUE); consider the first GetMsg() returns NULL, then it waits for a signal and exits the loop without getting the message (if any). So freeing/clearing the message will overwrite the node values of the still linked message. Thus if a CTRL_C comes first you face the problem of having an unanswered message. Maybe you can work around by using ACTION_WAIT_CHAR with a reasonable timeout. |
|
![]() |
![]() |
#29 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hey!
Thank you all for your advice! ![]() Finally, I got my code to work as expected, with a stack-allocated (and reused) StandardPacket and a reply port that can be safely deleted! Also, it fixes the problem found by Bebbo ![]() Grabbing the Console Code:
static int _grab_console(void) { if((_con_file = Open("*", MODE_OLDFILE)) == 0) { log_print_error("_grab_console(), could not open Consolet\n"); goto _RETURN_ERROR; } if((_con_file_handle = BADDR(_con_file))->fh_Type == NULL) { log_print_error("_grab_console(), could not get Console file handle\n"); goto _RETURN_ERROR; } _enable_RAW_mode(TRUE); _con_message_port = (struct MsgPort *)_con_file_handle->fh_Type; if((_con_reply_port = CreatePort(NULL, 0)) == NULL) { log_print_error( GetString( MSG_CONTROLSCLI_CONTROLSCLICOULDNOTCREATEMESSAGEPORT ) ); goto _RETURN_ERROR; } _open_result = 1; goto _RETURN_OK; _RETURN_OK: return RETURN_OK; goto _RETURN_ERROR; _RETURN_ERROR: return RETURN_ERROR; } Code:
static char _get_char(void) { struct StandardPacket con_standard_packet = { 0 }; char received_char = '\0'; ULONG console_signal = 0L; ULONG received_signals = 0L; struct Message *message = NULL; struct InputEvent *input_event = NULL; while(TRUE) { received_char = '\0'; memset(&con_standard_packet, 0, sizeof(struct StandardPacket)); con_standard_packet.sp_Msg.mn_Node.ln_Name = (char *)&con_standard_packet.sp_Pkt; con_standard_packet.sp_Pkt.dp_Link = &con_standard_packet.sp_Msg; con_standard_packet.sp_Pkt.dp_Port = _con_reply_port; con_standard_packet.sp_Pkt.dp_Type = ACTION_READ; con_standard_packet.sp_Pkt.dp_Arg1 = _con_file_handle->fh_Arg1; con_standard_packet.sp_Pkt.dp_Arg2 = (LONG)&_con_answer; con_standard_packet.sp_Pkt.dp_Arg3 = (LONG)ANSWER_LENGTH; PutMsg(_con_message_port, &con_standard_packet.sp_Msg); console_signal = 1L << _con_reply_port->mp_SigBit; received_signals = Wait(console_signal | SIGBREAKF_CTRL_C | controls_signal_playing_stopped()); if(received_signals & console_signal) { while(message = GetMsg(_con_reply_port)) { ReplyMsg(message); } if(_convert_CSI_to_InputEvent((char *)&_con_answer[1], &input_event) == RETURN_OK) { if(input_event->ie_Class == IECLASS_RAWKEY) { received_char = _convert_InputEvent_to_ANSI(input_event); } else if(input_event->ie_Class = IECLASS_CLOSEWINDOW) { received_char = '0'; } free(input_event); } } else if(received_signals & SIGBREAKF_CTRL_C) { received_char = '0'; } else if(received_signals & controls_signal_playing_stopped()) { controls_acknowledge_playing_stopped(); received_char = '6'; } // We stop listening only when we received an interesting char if(isprint(received_char) || received_char == '\n' || received_char == '\r') { break; } } printf("%c", received_char); fflush(stdout); return received_char; } Code:
static void _release_console(void) { _enable_RAW_mode(FALSE); // Any of these will cause Enforcer hits, memory corruption, Gurus... if(_con_reply_port) DeletePort(_con_reply_port); // if(_con_message_port) ; // Nothing to do, depends on _con_file // if(_con_file_handle) ; // Nothing to do, depends on _con_file if(_con_file) Close(_con_file); _open_result = -1; } Cheers! |
![]() |
![]() |
#30 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi all!
I'm bringing this thread back from the dead because my code doesn't work anymore with AmigaOS v3.1.4.1 and, presumably, v3.2... I never noticed because I'm using v3.1 ![]() What happens is that Open() now fails: Code:
if((_con_file = Open("*", MODE_OLDFILE)) == 0) { log_print_error("_grab_console(), could not open Consolet\n"); goto _RETURN_ERROR; } Thanks in advance! ![]() |
![]() |
![]() |
#31 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
Sorry, the CON:-Handler did not change in 3.1.4, and up to a minor bug fix, the console.device did not change either. "*" still opens the console, and the shell does not work differently.
So, I am not quite clear about the question. You can verify from the shell that "*" still works as expected: Code:
echo "hi" >* |
![]() |
![]() |
#32 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
It's what I thought too
![]() But I don't know what else could be wrong: Open("*", MODE_OLDFILE) returns 0 instead of some handle and SnoopDOS reports a "Fail" ![]() Code:
... 31 [13] AmiModRadio OpenLib locale.library Ver 38 OK 32 [13] AmiModRadio OpenLib intuition.library Ver 36 OK 33 [13] AmiModRadio OpenLib utility.library Ver 37 OK 34 [13] AmiModRadio Lock HD2:Programmation/C/VBCC/AmiModRadio/bin/vbcc-classic/debug/data/Players Read OK 35 [13] AmiModRadio OpenLib rexxsyslib.library Ver 0 OK 36 [13] AmiModRadio Lock ENVARC:AmiModRadio Read OK 37 [13] AmiModRadio Lock HD2:Programmation/C/VBCC/AmiModRadio/bin/vbcc-classic/debug/images/ Read Fail 38 [13] AmiModRadio OpenLib xadmaster.library Ver 11 OK 39 [13] AmiModRadio OpenLib keymap.library Ver 36 OK 40 [13] AmiModRadio Open * Read Fail 41 [13] AmiModRadio Lock ENVARC:AmiModRadio Read OK Thanks! ![]() |
![]() |
![]() |
#33 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
The only reason could be that the process does not have a console task. For example, if it is run from workbench, it would not.
|
![]() |
![]() |
#34 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi Thomas!
But I'm sure that AmiModRadio is run from the CLI... If it helps, this problem happens with v3.1.4.1 and also seem to happen with AmigaOS v4.1 (not tested myself) ![]() PS. I attached a screenshot of the Shell (v3.1.4.1), showing the problem... Thanks in advance! |
![]() |
![]() |
#35 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi!
I did some digging and already found one difference between what's happening in my code running in 3.1 and 3.2. I get the "answer" from the console in response to an event, with: Code:
con_standard_packet.sp_Pkt.dp_Arg2 = (LONG)&_con_answer; Code:
_convert_CSI_to_InputEvent((char *)&_con_answer[1], &input_event) I must do something wrong to "miss" this 0x9B but what is it? ![]() (I'm using printf("\33[1;11{"); to listen to raw keys and the close gadget.) Thanks in advance! Last edited by tygre; 07 January 2023 at 06:30. Reason: More details |
![]() |
![]() |
#36 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
Without complete source, it is hard to reproduce this. Just note that CSI is equivalent to ESC [, so you may want to check for both sequences.
|
![]() |
![]() |
#37 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Thanks Thomas!
![]() Actually, I was wrong: on AmigaOS 3.1 the CSI sequence seems to always start with a char with decimal value -101 (corresponding to 0x9b?) while on 3.2 some sequence do and others don't. Would that make sense? If you wouldn't mind, the code is available on BitBucket: here I get the CSI sequence and there I process it. Thank you in advance! ![]() PS. And I also have this problem that, when I quit and release the console, on 3.1 everything gets back to normal while on 3.2 the console is "frozen": I cannot type anything and I must click the close gadget to close the window. Maybe something with the way I release the console? (I already changed my code by moving _enable_RAW_mode(FALSE); inside the if(_con_file). I also fixed the if(input_event->ie_Class = IECLASS_CLOSEWINDOW), should have been == of course...) Last edited by tygre; 07 January 2023 at 21:10. Reason: More details |
![]() |
![]() |
#38 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
You have a couple of construction problems here, let me go through them:
*) You seem to assume that you always get an entire CSI message, starting with the CSI. However, the console does not guarantee that. Thus, it could very well be that you received only parts of the message, and the rest of the message is delivered with the next ACTION_READ, or it could be that there is more data in the output buffer of the console, and you receive that other part of the message first. Thus, you really need to parse the message character by character, and isolate the CSI control sequence from it, and re-fill your buffer once you run out of bytes. *) You also re-use the same buffer with each ACTION_READ, but do you completely empty the previous buffer? *) You do not seem to look at the size of the returned buffer. Thus, you do not know how many characters are in there. Thus, you need to restructure your code here. There are two possibilities here. Either, you write your main loop around the CSI parser, such that the CSI parser reads characters from the console byte per byte (potentially from a buffer, refilling the buffer when it runs dry), and then performing actions as you get data. Or you write your code around the buffer-receiver, and write the CSI parser as a state machine that updates its state from each byte that it fed into it from the outside, as soon as a new buffer of data arrives. As said earlier, your main assumption here seems to be that the CSI sequences are somehow aligned to the ACTION_READs, but that's not given. |
![]() |
![]() |
#39 | |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,456
|
Hi Thomas and thank you so much!
![]() Quote:
![]() Would you also see why my code release the console well on v3.1 but "freezes" the Shell on v3.2? ![]() Best! |
|
![]() |
![]() |
#40 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,492
|
You should also disable the raw-key events again when leaving the program, or you cut off the con-handler from its input. It listens to the same console device that serves your program, and if raw events are enabled, cooked keyboard events are disabled.
|
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
NewsTek Episode 9 is now available for your listening pleasure. | Pyromania | Amiga scene | 4 | 26 June 2010 16:42 |
Listening to Amiga music does this | moriez | Nostalgia & memories | 4 | 02 April 2010 22:00 |
listening suggestions | Marcuz | request.Modules | 48 | 06 August 2008 11:02 |
NewsTek Episode 2 is now availabe for your listening pleasure. | Pyromania | Amiga scene | 0 | 21 April 2008 05:44 |
Amiga Round Table Podcast #17 is available for your listening pleasure! | Pyromania | Amiga scene | 1 | 18 December 2007 21:22 |
|
|