English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 17 January 2020, 21:59   #1
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Detect a single keystroke in the Shell window

Hi,


I've got a little problem on how to detect a keystroke in the Shell window in a system friendly way.

I wrote a little Shell-command which informs the user to press the keys "y" to admit or "n" to reject an action. I know from many pure Shell commands that only a key is pressed and the program proceeds. Pressing the return key is not necessary. So they don't use the Input() command of the dos.library.

I want to code such a routine in assembler. But how do I detect such a keystroke in the Shell window? Via the IDCMP flags VANILLAKEY or RAWKEY (which won't be set automatically in the Shell window structure I guess), via the keybord.device or the CON:-device directly?

I know that I have to create a message port (for keyboard/CON device) to get a signal what I could use for the Wait() function. I also know that the signal bit needed for this function is derived from mp_SigBit of the port.

Does someone have a little code section which shows how to wait for the keys "y" and "n" pressed in the Shell window?


Thanks, Dissident
dissident is offline  
Old 17 January 2020, 22:43   #2
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 321
Quote:
Originally Posted by dissident View Post
I wrote a little Shell-command which informs the user to press the keys "y" to admit or "n" to reject an action. I know from many pure Shell commands that only a key is pressed and the program proceeds. Pressing the return key is not necessary. So they don't use the Input() command of the dos.library.
They do. They all need to know where the input is coming from, and it is coming from Process->pr_CIS, or Input().


Quote:
Originally Posted by dissident View Post
I want to code such a routine in assembler. But how do I detect such a keystroke in the Shell window? Via the IDCMP flags VANILLAKEY or RAWKEY (which won't be set automatically in the Shell window structure I guess), via the keybord.device or the CON:-device directly?
You first need to switch the console to "raw" mode, which works with the dos packet ACTION_SCREEN_MODE, see dos/dosextens.h. See



https://wiki.amigaos.net/wiki/AmigaDOS_Packets


for more details. This packet tells the con-handler to deliver keystrokes directly, i.e. unbuffered, without line buffering. Read the key, with Read(), then switch the con-handler back to con-mode.


To send the packet, you need to get the message port from the file handle you received from Input(). For this, convert the BPTR from Input() into a pointer by shifting it left by 2 bits, then read the fh_Type member of the struct FileHandle, see again <dos/dosextens.h> for the structure.


ACTION_SCREEN_MODE takes one parameter that controls line buffering on or off. If I recall correctly, the parameter is 0 for line buffering on, and 1 for line buffering off. (And 2, from 3.2 on, for the medium mode used by the shell).




Quote:
Originally Posted by dissident View Post
I know that I have to create a message port (for keyboard/CON device) to get a signal what I could use for the Wait() function. I also know that the signal bit needed for this function is derived from mp_SigBit of the port.
No, you are on the wrong track. The only message port you need is that of the process your program is running as, and this already exists. No IDCMP, no console.device. The console.device is already in use by the con-handler, and it does not have an IDCMP either.
Thomas Richter is offline  
Old 17 January 2020, 22:57   #3
mark_k
Registered User
 
Join Date: Aug 2004
Location:
Posts: 3,168
If you don't mind only working on Kickstart 2.0 or later, you can use the new DOS function SetMode() instead of messing with packets.
mark_k is offline  
Old 17 January 2020, 23:20   #4
alkis
Registered User

 
Join Date: Dec 2010
Location: Athens/Greece
Age: 49
Posts: 512
Funny, I was searching old usenet yesterday for something like that.

I came across this one https://github.com/alexalkis/sillych...03ff9356ac54dd

It's in C, but should give the general idea. Looks 1.3 compatible. I haven't found the time to test it yet, though.
alkis is offline  
Old 17 January 2020, 23:58   #5
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by Thomas Richter View Post
They do. They all need to know where the input is coming from, and it is coming from Process->pr_CIS, or Input().



You first need to switch the console to "raw" mode, which works with the dos packet ACTION_SCREEN_MODE, see dos/dosextens.h. See



https://wiki.amigaos.net/wiki/AmigaDOS_Packets


for more details. This packet tells the con-handler to deliver keystrokes directly, i.e. unbuffered, without line buffering. Read the key, with Read(), then switch the con-handler back to con-mode.


To send the packet, you need to get the message port from the file handle you received from Input(). For this, convert the BPTR from Input() into a pointer by shifting it left by 2 bits, then read the fh_Type member of the struct FileHandle, see again <dos/dosextens.h> for the structure.


ACTION_SCREEN_MODE takes one parameter that controls line buffering on or off. If I recall correctly, the parameter is 0 for line buffering on, and 1 for line buffering off. (And 2, from 3.2 on, for the medium mode used by the shell).





No, you are on the wrong track. The only message port you need is that of the process your program is running as, and this already exists. No IDCMP, no console.device. The console.device is already in use by the con-handler, and it does not have an IDCMP either.

Many thanks for your detailed answer, Thomas. I know the "RAW-mode" from using RAW-windows. Switching the console to the "RAW-mode" is a very smart trick.


I guess this method also works on pre- OS2.x systems. This solution explains the whole behaviour of the CON-window which acts like a RAW-window.


I will try to write a routine based on your great explanation.
dissident is offline  
Old 18 January 2020, 00:01   #6
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by mark_k View Post
If you don't mind only working on Kickstart 2.0 or later, you can use the new DOS function SetMode() instead of messing with packets.

Fine, a good hint, mark_k. I will use this DOS function in my alternative 68020/OS2.x version of my little tool.
dissident is offline  
Old 18 January 2020, 00:03   #7
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by alkis View Post
Funny, I was searching old usenet yesterday for something like that.

I came across this one https://github.com/alexalkis/sillych...03ff9356ac54dd

It's in C, but should give the general idea. Looks 1.3 compatible. I haven't found the time to test it yet, though.

Thanks for sharing the link, alkis. I will check it.
dissident is offline  
Old 19 January 2020, 18:14   #8
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by alkis View Post
Funny, I was searching old usenet yesterday for something like that.

I came across this one https://github.com/alexalkis/sillych...03ff9356ac54dd

It's in C, but should give the general idea. Looks 1.3 compatible. I haven't found the time to test it yet, though.

Sorry, my knowledge about C is very miserable. I don't understand these lines:

Code:
register struct Process           * proc;
    register struct StandardPacket * packet;
    register LONG                     res1;

    proc = (struct Process *)FindTask(NULL);

    if (packet = (struct StandardPacket *)AllocMem( sizeof(struct StandardPacket),
                                MEMF_CLEAR | MEMF_PUBLIC) ) {

        packet->sp_Msg.mn_Node.ln_Name        = (char *)&(packet->sp_Pkt);
        packet->sp_Pkt.dp_Link                = & packet->sp_Msg;
        packet->sp_Pkt.dp_Port                = & proc->pr_MsgPort;
          packet->sp_Pkt.dp_Type                = action;
To my mind, the entries of the message structure aren't initialized:

Code:
struct Message {
    struct  Node mn_Node;
    struct  MsgPort *mn_ReplyPort;  /* message reply port */
    UWORD   mn_Length;            /* total message length, in bytes */
                    /* (include the size of the Message */
                    /* structure in the length) */
What about the entries "pointer to the message reply port" and "length of the message structure"?

Only the entries "sp_link"," dp_port" and "dp_type" of the packet structure are initialized.


And what does this line below mean?

Code:
packet->sp_Msg.mn_Node.ln_Name        = (char *)&(packet->sp_Pkt);
The pointer to the node name points to the message structure in the standard packet structure and this is a string


The only thing I've understood is how to get the pointer to the message port of the CON device. There are two ways:


One way is via the input-handle like Thomas told me:

Code:
  CALLDOS Input
  move.l  d0,input_handle(a3) ;Save handle
  beq     input_handle_error ;If NULL -> skip
  move.l  d0,a0              ;BPTR
  add.l   a0,a0              ;*4 = CPTR
  add.l   a0,a0
  move.l  fh_type(a0),d0     ;Get Message-Port for PutMsg()
  beq     port_error         ;If NULL -> skip
  move.l  d0,a4              ;Get pointer to Message-Port structure
Or the second way via the Process structure directly:

Code:
  sub.l   a1,a1               ;NULL = Search for own Task
  CALLEXEC FindTask           ;Get pointer to own Task-structure/Process structure
  tst.l   d0                  
  beq     no_task_found       ;If NULL -> skip
  move.l  d0,a0               ;Get pointer to Task/Process
  move.b  LN_TYPE(a0),d0      ;Get type
  cmp.b   #NT_PROCESS,d0      ;DOS process ?
  bne     no_dos_process      ;No -> skip
  move.l  pr_ConsoleTask(a0),a4 ;Get pointer to message port structure
I understand that a packet structure is combined with a message structure and via PutMsg() sent to the CON device, but how this is done in detail is still a mystery to me. Maybe someone can enlighten me.
dissident is offline  
Old 19 January 2020, 21:56   #9
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 321
Quote:
Originally Posted by dissident View Post
What about the entries "pointer to the message reply port" and "length of the message structure"?
Not needed. Tripos aka dos.library does not use the reply port, but replies to Pkt->dp_Port. It neither uses the lengh, but expects always a standard packet pointed to by mn_Node.ln_Name.


Quote:
Originally Posted by dissident View Post
Only the entries "sp_link"," dp_port" and "dp_type" of the packet structure are initialized.
That is correct. sp_link points to the message, dp_Port to the port it should be replied to, and dp_Type is the type of the packet. Also, dp_Args needs to be initialized by additional arguments, i.e. the direction into which to switch.




Quote:
Originally Posted by dissident View Post

And what does this line below mean?


Code:
packet->sp_Msg.mn_Node.ln_Name        = (char *)&(packet->sp_Pkt);
The pointer to the node name points to the message structure in the standard packet structure and this is a string
It means, "put the address of the standard packet into mn_Node.ln_Name, do not worry about it being not a string.


Well, this is the beauty of Tripos: It was an operating system of its own, and all what happend when "Caos" did not become ready was that our friendly developers used an enourmous amount of hot-glue, duct-tape and chewing gum to fit the Tripos core - which we nowadays call the dos.library - on top of the already existing multitasking core, which we call the exec.library. What you see here is exactly this type of "hot glue":


Message passing requires messages, but Tripos does not use messages. It uses packets. So the message is used to transport the packet as exec uses the latter, but tripos depends on the former. There is no pointer to in an exec message to point to the message, so Tripos hijacks the name pointer, which is then not a name at all.


Also, the handler you send the packet to - here the console - was part of tripos, and it did not use the exec message at all. Instead, Tripos has its own way of replying messages, namely to use pkt->dp_Port as reply port, and "PutMsg" the packet back there. mn_ReplyPort is not used at all. Junk, I know, but this is another layer of hotglue, ducktape... you name it.


Quote:
Originally Posted by dissident View Post
The only thing I've understood is how to get the pointer to the message port of the CON device. There are two ways:


One way is via the input-handle like Thomas told me:

Code:
  CALLDOS Input
  move.l  d0,input_handle(a3) ;Save handle
  beq     input_handle_error ;If NULL -> skip
  move.l  d0,a0              ;BPTR
  add.l   a0,a0              ;*4 = CPTR
  add.l   a0,a0
  move.l  fh_type(a0),d0     ;Get Message-Port for PutMsg()
  beq     port_error         ;If NULL -> skip
  move.l  d0,a4              ;Get pointer to Message-Port structure
Or the second way via the Process structure directly:

Code:
  sub.l   a1,a1               ;NULL = Search for own Task
  CALLEXEC FindTask           ;Get pointer to own Task-structure/Process structure
  tst.l   d0                  
  beq     no_task_found       ;If NULL -> skip
  move.l  d0,a0               ;Get pointer to Task/Process
  move.b  LN_TYPE(a0),d0      ;Get type
  cmp.b   #NT_PROCESS,d0      ;DOS process ?
  bne     no_dos_process      ;No -> skip
  move.l  pr_ConsoleTask(a0),a4 ;Get pointer to message port structure
Be warned, these two are not identical! The Input() file handle is where the input of the program is coming from. That is, it can be changed by the shell via input redirection. "<ram:foo" makes it come from "ram:foo". pr_ConsoleTask is always the handler that is responsible for "*", that is, the current console. It is not changed by input redirection. The 3.9 and 3.1.4 shells allow its change by means of the "*>ram:foo" redirection, read as "the console (*) goes to ram:foo". Its closest equivalent is "stderr" in the *ix world (though, confusingly, we also have pr_CES = error output in 3.1, which is - however - not be used before Os 3.2).




Quote:
Originally Posted by dissident View Post
I understand that a packet structure is combined with a message structure and via PutMsg() sent to the CON device, but how this is done in detail is still a mystery to me. Maybe someone can enlighten me.
This "StandardPacket" is just a convenience structure. They don't have to sit near each other as it is here. The only important thing is that pkt->dp_Link points to the message, pkt->dp_Port back to the reply port where the handler puts the message back to indicate that it is done, and msg->mn_Node.ln_Name points to the packet.


Thus, there are actually two structures, the packet and the message, that are crosswise linked to each other, one over the "dp_Link" pointer, the other by hijacking mn_Node.ln_Name.


As said... layers of hot glue, duct tape and chewing gum.
Thomas Richter is offline  
Old 19 January 2020, 22:18   #10
alkis
Registered User

 
Join Date: Dec 2010
Location: Athens/Greece
Age: 49
Posts: 512
Code:
	incdir  "/opt/amiga/gcc6/m68k-amigaos/ndk-include"
	include dos/dosextens.i
	include lvo/exec_lib.i
	include lvo/dos_lib.i


CALL	MACRO
		jsr     _LVO\1(a6)
		ENDM


	move.l	$4.w,a6
	move.l  a6,_SysBase
	lea.l	DOSNAME,a1
	moveq.l	#0,d0
	CALL	OpenLibrary
	move.l 	d0,_DOSBase
	beq		errorNoDOS

	moveq.l #-1,d0
	bsr		@set_screen_mode


	move.l _DOSBase,a6
	CALL	Input
	move.l  d0,stdInput
	move.l  d0,d1		;should guard for 0 here...too lazy now
	move.l 	#15*1000000,d2
	CALL	WaitForChar	
	tst.l 	d0
	beq		nochar


	move.l stdInput,d1
	move.l #thechar,d2
	moveq.l #1,D3
	CALL	Read

	
	CALL	Output
	move.l d0,d1
	move.l #msg,d2
	move.l #msgend-msg,d3 
	CALL	Write


nochar:
	moveq.l #0,d0
	bsr		@set_screen_mode	
	move.l	_SysBase,a6
	move.l 	_DOSBase,a1
	CALL	CloseLibrary
	moveq.l	#42,d0
	rts
errorNoDOS:
	moveq.l #20,d0
	rts	


@set_screen_mode:
	move.l d0,-(sp)
	bsr		_set_screen_mode
	addq.l #4,sp
	rts

_set_screen_mode:
        link.w a5,#-28
        move.l a6,-(sp)
        move.l d2,-(sp)
        move.l (8,a5),d2
        sub.l a1,a1
        move.l _SysBase,a6
        CALL 	FindTask
        move.l d0,a0
        move.l (164,a0),d0
       	beq .L1
        ext.l d2
        move.l d2,(-28,a5)
        move.l d0,-(sp)
        pea (-28,a5)
        pea 994.w
        bsr _send_packet
        moveq #1,d0
.L1:
        move.l (-36,a5),d2
        move.l (-32,a5),a6
        unlk a5
        rts

_send_packet:
        link.w a5,#-20
        movem.l a6/a4/a3/a2/d2,-(sp)
        move.l (12,a5),d2
        sub.l a1,a1
        move.l _SysBase,a6
        CALL 	FindTask
        move.l d0,a3
        moveq #68,d0
        move.l #65537,d1
        CALL	AllocMem
        move.l d0,a2
        tst.l d0
        beq .L5
        lea (20,a2),a0
        move.l a0,(10,a2)
        move.l d0,(20,a2)
        lea (92,a3),a4
        move.l a4,(24,a2)
        move.l (8,a5),(28,a2)
        tst.l d2
        beq .L6
        move.l d2,a0
        moveq #28,d0
        lea (40,a2),a1
        CALL	CopyMem
.L6:
        move.l a2,a1
        move.l (16,a5),a0
        CALL 	PutMsg
        move.l (180,a3),a1
        move.l a1,d0
        beq .L7
        lea (-20,a5),a0
        jsr (a1)
.L8:
        move.l (172,a3),d0
        lsl.l #2,d0
        move.l d0,a0
        move.l (36,a2),(a0)
        move.l (32,a2),a3
        move.l _SysBase,a6
        moveq #68,d0
        move.l a2,a1
        CALL 	FreeMem
.L4:
        move.l a3,d0
        movem.l (-40,a5),d2/a2/a3/a4/a6
        unlk a5
        rts
.L7:
        move.l a4,a0
        move.l _SysBase,a6
        CALL 	WaitPort
        move.l a4,a0
        CALL	GetMsg
        bra .L8
.L5:
        move.l (172,a3),d0
        lsl.l #2,d0
        move.l d0,a0
        moveq #103,d1
        move.l d1,(a0)
        move.l a2,a3
        bra .L4

	section data
_SysBase: dc.l 0
_DOSBase: dc.l 0
stdInput: dc.l 0
DOSNAME: dc.b "dos.library",0
msg:	dc.b "You pressed "
thechar: dc.b " "
		dc.b "\n"
msgend:
Save that as consoleraw.s
Assemble with: (you need to change incdir path)
vasmm68k_mot -esc -Fhunkexe -kick1hunks consoleraw.s -o craw

Lightly tested on A500. Looks like it works.
alkis is offline  
Old 19 January 2020, 23:54   #11
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 321
Quote:
Originally Posted by alkis View Post
Assemble with: (you need to change incdir path)
vasmm68k_mot -esc -Fhunkexe -kick1hunks consoleraw.s -o craw

Lightly tested on A500. Looks like it works.

There is no need to WaitForChar() if your task attempts to block anyhow. Also, please use the Os includes instead of using absolute offsets.


As a side remark, it is not necessary to allocate a standard packet. It can easily sit on the stack.
Thomas Richter is offline  
Old 20 January 2020, 03:25   #12
alkis
Registered User

 
Join Date: Dec 2010
Location: Athens/Greece
Age: 49
Posts: 512
Quote:
Originally Posted by Thomas Richter View Post
There is no need to WaitForChar() if your task attempts to block anyhow. Also, please use the Os includes instead of using absolute offsets.


As a side remark, it is not necessary to allocate a standard packet. It can easily sit on the stack.
I thought it was obvious that this "source code" comes from gcc compiling the C source I linked. (Except for the first init part)

PS: https://franke.ms/cex/z/I0smeH

Last edited by alkis; 20 January 2020 at 04:01. Reason: added the link to compiler explorer
alkis is offline  
Old 21 January 2020, 20:21   #13
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by Thomas Richter View Post
ACTION_SCREEN_MODE takes one parameter that controls line buffering on or off. If I recall correctly, the parameter is 0 for line buffering on, and 1 for line buffering off. (And 2, from 3.2 on, for the medium mode used by the shell).
Yes, I can confirm this:


con-mode = 0
raw-mode = 1 or -1


Quote:
Originally Posted by Thomas Richter View Post
No, you are on the wrong track. The only message port you need is that of the process your program is running as, and this already exists.
Yes, & proc->pr_MsgPort works for both options:


1) Packet sending via the file input handler
2) Packet sending via the console handler


Quote:
Originally Posted by alkis View Post
Code:
    incdir  "/opt/amiga/gcc6/m68k-amigaos/ndk-include"
    include dos/dosextens.i
    include lvo/exec_lib.i
    include lvo/dos_lib.i

CALL    MACRO
        jsr     _LVO\1(a6)
        ENDM


    move.l    $4.w,a6
    move.l  a6,_SysBase
    lea.l    DOSNAME,a1
    moveq.l    #0,d0
    CALL    OpenLibrary
    move.l     d0,_DOSBase
    beq        errorNoDOS

    moveq.l #-1,d0
    bsr        @set_screen_mode


    move.l _DOSBase,a6
    CALL    Input
    move.l  d0,stdInput
    move.l  d0,d1        ;should guard for 0 here...too lazy now
    move.l     #15*1000000,d2
    CALL    WaitForChar    
    tst.l     d0
    beq        nochar


    move.l stdInput,d1
    move.l #thechar,d2
    moveq.l #1,D3
    CALL    Read

    
    CALL    Output
    move.l d0,d1
    move.l #msg,d2
    move.l #msgend-msg,d3
    CALL    Write


nochar:
    moveq.l #0,d0
    bsr        @set_screen_mode    
    move.l    _SysBase,a6
    move.l     _DOSBase,a1
    CALL    CloseLibrary
    moveq.l    #42,d0
    rts
errorNoDOS:
    moveq.l #20,d0
    rts    


@set_screen_mode:
    move.l d0,-(sp)
    bsr        _set_screen_mode
    addq.l #4,sp
    rts

_set_screen_mode:
        link.w a5,#-28
        move.l a6,-(sp)
        move.l d2,-(sp)
        move.l (8,a5),d2
        sub.l a1,a1
        move.l _SysBase,a6
        CALL     FindTask
        move.l d0,a0
        move.l (164,a0),d0
           beq .L1
        ext.l d2
        move.l d2,(-28,a5)
        move.l d0,-(sp)
        pea (-28,a5)
        pea 994.w
        bsr _send_packet
        moveq #1,d0
.L1:
        move.l (-36,a5),d2
        move.l (-32,a5),a6
        unlk a5
        rts

_send_packet:
        link.w a5,#-20
        movem.l a6/a4/a3/a2/d2,-(sp)
        move.l (12,a5),d2
        sub.l a1,a1
        move.l _SysBase,a6
        CALL     FindTask
        move.l d0,a3
        moveq #68,d0
        move.l #65537,d1
        CALL    AllocMem
        move.l d0,a2
        tst.l d0
        beq .L5
        lea (20,a2),a0
        move.l a0,(10,a2)
        move.l d0,(20,a2)
        lea (92,a3),a4
        move.l a4,(24,a2)
        move.l (8,a5),(28,a2)
        tst.l d2
        beq .L6
        move.l d2,a0
        moveq #28,d0
        lea (40,a2),a1
        CALL    CopyMem
.L6:
        move.l a2,a1
        move.l (16,a5),a0
        CALL     PutMsg
        move.l (180,a3),a1
        move.l a1,d0
        beq .L7
        lea (-20,a5),a0
        jsr (a1)
.L8:
        move.l (172,a3),d0
        lsl.l #2,d0
        move.l d0,a0
        move.l (36,a2),(a0)
        move.l (32,a2),a3
        move.l _SysBase,a6
        moveq #68,d0
        move.l a2,a1
        CALL     FreeMem
.L4:
        move.l a3,d0
        movem.l (-40,a5),d2/a2/a3/a4/a6
        unlk a5
        rts
.L7:
        move.l a4,a0
        move.l _SysBase,a6
        CALL     WaitPort
        move.l a4,a0
        CALL    GetMsg
        bra .L8
.L5:
        move.l (172,a3),d0
        lsl.l #2,d0
        move.l d0,a0
        moveq #103,d1
        move.l d1,(a0)
        move.l a2,a3
        bra .L4

    section data
_SysBase: dc.l 0
_DOSBase: dc.l 0
stdInput: dc.l 0
DOSNAME: dc.b "dos.library",0
msg:    dc.b "You pressed "
thechar: dc.b " "
        dc.b "\n"
msgend:
Save that as consoleraw.s
Assemble with: (you need to change incdir path)
vasmm68k_mot -esc -Fhunkexe -kick1hunks consoleraw.s -o craw

Lightly tested on A500. Looks like it works.
Many thanks for this sourcecode, alkis. Well it confirms my opinion about C and why I still code in assembler and not in C. The generated assembler code has too many memory accsesses for variables, is too long and very slow.


The package sending could be done this way:
Code:
; Routine Set-Screen-Mode
; d0 ... Argument for Packet "ACTION_SCREEN_MODE": 0="con-mode" -1="raw-mode"
; d4 ... Pointer to handler Message-Port
; a2 ... Pointer to process Reply-Port
  CNOP 0,4
set_screen_mode
 ; ** Message structure init **
  lea     packet_struc(pc),a1 ;Pointer to Message structure
  lea     sp_Pkt(a1),a0      
  move.l  a0,LN_NAME(a1)     ;Save pointer to Packet structure
; ** Packet strcture init **
  move.l  a1,mn_size+dp_link(a1) ;Save pointer to Message structure
  move.l  a2,mn_size+dp_port(a1) ;Save pointer to Reply Port
  move.l  #ACTION_SCREEN_MODE,mn_size+dp_type(a1) ;Save Packet type
  move.l  d0,mn_size+dp_arg1(a1) ;Save Packet argument
; ** Send packet to console handler or input file handler **
send_packet
  move.l  d4,a0              ;Pointer to handler Message Port
  CALLEXEC PutMsg
  move.l  a2,a0              ;Pointer to process Reply Port
  CALLLIBS WaitPort
  move.l  a2,a0              ;Pointer to process Reply Port
  CALLLIBQ GetMsg
During my testings I found out something remarkable. Before every call of PutMsg(), the Packet structure must be initialized even if this was already done before by a previous PutMsg() call. Otherwise a guru meditation comes around.


For all of you who want to get information from the horse's mouth about DOS internals and in this case about dos packets starting with page 395): https://archive.org/details/1991-bak...-manual-3rd-ed
The funny thing is that I knew this book before, but without hints I wouldn't discovered to use dos packets to solve my problem and that everything is explained in this book.

And last but not least a big thank you to you all, Thomas Richter, alkis & mark_k
As always it was a pleasure to get some great support and learn new things about the programming of the OS.

Last edited by dissident; 21 January 2020 at 21:34.
dissident is offline  
Old 21 January 2020, 22:17   #14
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 321
Quote:
Originally Posted by dissident View Post
1) Packet sending via the file input handler
2) Packet sending via the console handler
Note, again, that this is different as soon as redirections from the shell are in force. Depending on what you want, either option may be correct. Or even the output file handle may be correct (yes, you can read from it).


Quote:
Originally Posted by dissident View Post
Many thanks for this sourcecode, alkis. Well it confirms my opinion about C and why I still code in assembler and not in C. The generated assembler code has too many memory accsesses for variables, is too long and very slow.
You are looking at the toe of the elephant. First, the running time of this little program is dominated by the user being able to hitting a key fast enough, and even disregarding this, just counting cycles, placing the packet on the stack saves more than just a couple of removed "move" instructions.




Quote:
Originally Posted by dissident View Post

During my testings I found out something remarkable. Before every call of PutMsg(), the Packet structure must be initialized even if this was already done before by a previous PutMsg() call. Otherwise a guru meditation comes around.
You mean a software failure. Anyhow, what you need to re-initialize is dp_Port since that is reset by ReplyPkt(). dp_Link stays intact, and so does msg->mn_Node.ln_Name.




Quote:
Originally Posted by dissident View Post


For all of you who want to get information from the horse's mouth about DOS internals and in this case about dos packets starting with page 395): https://archive.org/details/1991-bak...-manual-3rd-ed
The funny thing is that I knew this book before, but without hints I wouldn't discovered to use dos packets to solve my problem and that everything is explained in this book.
While this is the official AmigaDos documentation, I would in general not recommed it as it only scratches the surface and does not go very deeply into the matter. The recommended source is Ralph Babel's "Guru Book", though it may be hard to find a copy these days.
Thomas Richter is offline  
Old 21 January 2020, 23:05   #15
dissident
Registered User

 
Join Date: Sep 2015
Location: Germany
Posts: 231
Quote:
Originally Posted by Thomas Richter View Post
Note, again, that this is different as soon as redirections from the shell are in force. Depending on what you want, either option may be correct. Or even the output file handle may be correct (yes, you can read from it).

I can tell you that I will use the first option, sending the Packet via the file input() handler in my shell tool.


Quote:
Originally Posted by Thomas Richter View Post
You are looking at the toe of the elephant. First, the running time of this little program is dominated by the user being able to hitting a key fast enough, and even disregarding this, just counting cycles, placing the packet on the stack saves more than just a couple of removed "move" instructions.

Yes you are right, but in all other cases without any wait loop, assembler is shorter and faster. Maybe it has something to do with the fact that I normally write fx-routines for demos where every cycle counts.


Quote:
Originally Posted by Thomas Richter View Post
You mean a software failure. Anyhow, what you need to re-initialize is dp_Port since that is reset by ReplyPkt(). dp_Link stays intact, and so does msg->mn_Node.ln_Name.

Yes, it was a software failure to be precise. Thanks for the explanation.


Quote:
Originally Posted by Thomas Richter View Post
While this is the official AmigaDos documentation, I would in general not recommed it as it only scratches the surface and does not go very deeply into the matter. The recommended source is Ralph Babel's "Guru Book", though it may be hard to find a copy these days.

Yes, the "Guru Book" is hard to get, but there shall be spread text files of it.
dissident is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Start script without opening a Shell window Joel_w support.Apps 6 01 February 2019 17:56
Trying the get bold, italic and coloured text out to the shell window. chocsplease Coders. C/C++ 16 22 June 2017 15:58
Closing current Shell window programmatically? tygre Coders. General 5 06 September 2015 07:24
Snapshot Amiga Shell window? TenLeftFingers support.Apps 3 15 June 2015 17:38
Clear background color for Shell window- Shell-StartUp fc.studio support.Apps 12 29 December 2009 15:21

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 05:20.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.
Page generated in 0.08512 seconds with 14 queries