Porting PLATOTERM to the QL as a QDOS app.
Porting PLATOTERM to the QL as a QDOS app.
Hello everyone.
I've spent the last two years building a massive on-line platform for retrocomputing users (IRATA.ONLINE), based on PLATO, and to this end have written almost TWO DOZEN ports of the required terminal access software PLATOTERM.
It can be gotten here, for many platforms, including the ZX Spectrum: https://www.irata.online/
Now I am trying to get up to speed as quickly as possible to make a full screen QDOS application (there are various reasons for this, if you really want to know, ask and I'll explain.)
and I have put together a toolchain based on XTC68 and the C68 libs/includes.
Thus far, I have been able to compile, link, and test simple programs in Qemulator, and am now trying to set up the correct drawing context by opening my own channel and not dealing with the default CON that C68 seems to create.
I did try to redirect the consetup function pointer, to a blank function prototype (to test and see if I was correctly casting the pointer), but the default CON_ still appears.
https://github.com/tschak909/platotermq ... main.c#L22
https://github.com/tschak909/platotermq ... reen.c#L28
What's going on here? also, why is my program task name still showing as C_PROG (when I look at it via file), despite me changing it?
Assuming I can get past this, is getting the window I want, simply a matter of calling io_open against the appropriate SCR or CON specification? (I am leaning towards SCR, as I do not want normal keyboard input semantics, and want to handle this on my own.)
also, I have noticed the sd_iscale function, why only the single scale value? Can I only symmetrically scale both X and Y? (I can work around this, just like I do everywhere else by using scaling tables, but I wanted to see if I could leverage the system ROM to give me a 512x512 display scaled down to 512x256 or 256x256 depending on the display mode)
-Thom
I've spent the last two years building a massive on-line platform for retrocomputing users (IRATA.ONLINE), based on PLATO, and to this end have written almost TWO DOZEN ports of the required terminal access software PLATOTERM.
It can be gotten here, for many platforms, including the ZX Spectrum: https://www.irata.online/
Now I am trying to get up to speed as quickly as possible to make a full screen QDOS application (there are various reasons for this, if you really want to know, ask and I'll explain.)
and I have put together a toolchain based on XTC68 and the C68 libs/includes.
Thus far, I have been able to compile, link, and test simple programs in Qemulator, and am now trying to set up the correct drawing context by opening my own channel and not dealing with the default CON that C68 seems to create.
I did try to redirect the consetup function pointer, to a blank function prototype (to test and see if I was correctly casting the pointer), but the default CON_ still appears.
https://github.com/tschak909/platotermq ... main.c#L22
https://github.com/tschak909/platotermq ... reen.c#L28
What's going on here? also, why is my program task name still showing as C_PROG (when I look at it via file), despite me changing it?
Assuming I can get past this, is getting the window I want, simply a matter of calling io_open against the appropriate SCR or CON specification? (I am leaning towards SCR, as I do not want normal keyboard input semantics, and want to handle this on my own.)
also, I have noticed the sd_iscale function, why only the single scale value? Can I only symmetrically scale both X and Y? (I can work around this, just like I do everywhere else by using scaling tables, but I wanted to see if I could leverage the system ROM to give me a 512x512 display scaled down to 512x256 or 256x256 depending on the display mode)
-Thom
- NormanDunbar
- Forum Moderator
- Posts: 2277
- Joined: Tue Dec 14, 2010 9:04 am
- Location: Leeds, West Yorkshire, UK
- Contact:
Re: Porting PLATOTERM to the QL as a QDOS app.
For the job name:
As a global assignment, outside of all functions, including main(). I don't know about there being a channel open but I suspect it's for stdin,stdout,stderr maybe.
I suspect, perhaps that this might remove the default channel:
But I haven't tested it.
EDITED: To add details about _conname.
Cheers,
Norm.
Code: Select all
char _prog_name[] = "program_name";
I suspect, perhaps that this might remove the default channel:
Code: Select all
char _conname[] = NULL;
EDITED: To add details about _conname.
Cheers,
Norm.
Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts
No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
Author of Arduino Software Internals
Author of Arduino Interrupts
No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
Re: Porting PLATOTERM to the QL as a QDOS app.
The software is now almost functional, it is starting to render correctly, and is starting to read from keyboard and i/o to the serial port, I recorded a demonstration of what's happening:
The incoming buffer isn't draining properly, for some reason... What's the correct pattern for dealing with I/O ?
I am doing the following in main.c:
io_main:
keyboard_main()
touch_main is currently empty.
What could be going on?
-Thom
The incoming buffer isn't draining properly, for some reason... What's the correct pattern for dealing with I/O ?
I am doing the following in main.c:
Code: Select all
for (;;)
{
io_main();
keyboard_main();
touch_main();
}
Code: Select all
/**
* io_main() - The IO main loop
*/
void io_main(void)
{
char ch;
padByte pb;
if (io_pend(ser,0)==0)
{
io_fbyte(ser,-1,&ch);
pb=ch;
ShowPLATO(&pb,1);
}
}
Code: Select all
/**
* keyboard_main - Handle the keyboard presses
*/
void keyboard_main(void)
{
char ch;
if (io_pend(win,0)==0)
{
io_fbyte(win,0,&ch);
if (ch==0x0a)
ch=0x0d;
io_send_byte(ch);
}
}
What could be going on?
-Thom
Re: Porting PLATOTERM to the QL as a QDOS app.
What does ShowPLATO() do? How much time does it take? If that's too much (you seem to be drawing fairly complex stuff there), you will easily lose characters. In that case, it would make sense to split off serial receive in its own job and feed a pipe to ShowPLATO() in this job.
Serial comms on the QL is somewhat shaky: There are no hardware buffers, and characters the 8049 cannot deliver to the main CPU immediately are silently discarded.
Do you use any type of handshake? If yes, is your cable wired properly?
What baud rate are you receiving at?
Also take note that
Is potentially dangerous: If there's more than one character arriving between calls, you'll never read everything available and inevitably lose characters. This should be more like
Tobias
Serial comms on the QL is somewhat shaky: There are no hardware buffers, and characters the 8049 cannot deliver to the main CPU immediately are silently discarded.
Do you use any type of handshake? If yes, is your cable wired properly?
What baud rate are you receiving at?
Also take note that
Code: Select all
if (io_pend(...) {
io_fbyte (exactly one character)
}
Code: Select all
while (io_pend(...)
io_fbyte (one character)
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: Porting PLATOTERM to the QL as a QDOS app.
ShowPLATO() is the primary state machine, in protocol.c
https://github.com/tschak909/platotermq ... col.c#L781
Data goes in, and is interpreted, and various callbacks are called to handle screen drawing, etc. It is very complex, yes, but it needs to be.
I did try to do an aggressive buffering technique where I keep grabbing data as long as io_pending was returning 0, but I was still getting the same behavior.
Nominally, I am testing at 1200 baud in qemulator, at "original QL speed"
SER1 is set up to use COM1, which is attached to tcpser on the other side, set up for hardware handshaking.
I am not losing characters, I am having to press keys on the keyboard to get the data to come across, and I am not sure why.
I have written over TWO DOZEN versions of this for other platforms, all from the same core C code, and would really like to get over this hump, so I can get you guys an excellent terminal emulator to access IRATA.ONLINE (and other PLATO systems)
-Thom
https://github.com/tschak909/platotermq ... col.c#L781
Data goes in, and is interpreted, and various callbacks are called to handle screen drawing, etc. It is very complex, yes, but it needs to be.
I did try to do an aggressive buffering technique where I keep grabbing data as long as io_pending was returning 0, but I was still getting the same behavior.
Nominally, I am testing at 1200 baud in qemulator, at "original QL speed"
SER1 is set up to use COM1, which is attached to tcpser on the other side, set up for hardware handshaking.
I am not losing characters, I am having to press keys on the keyboard to get the data to come across, and I am not sure why.
I have written over TWO DOZEN versions of this for other platforms, all from the same core C code, and would really like to get over this hump, so I can get you guys an excellent terminal emulator to access IRATA.ONLINE (and other PLATO systems)
-Thom
Re: Porting PLATOTERM to the QL as a QDOS app.
What you could try for the moment is, change your receiving code (both console and ser) to
This saves the io_pend calls (trying to read with zero timeout returns with ERR_NC if nothing there), so the code is effectively the same, but saving some traps.
Actually, I don't see a good reason why the program should be waiting for keypresses.
Tobias
Code: Select all
if (io_fbyte (ch, 0, &c) == 0) {
// got something
} else
// got nothing
Actually, I don't see a good reason why the program should be waiting for keypresses.
Tobias
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: Porting PLATOTERM to the QL as a QDOS app.
How can I set up a seperate job for the serial i/o? I see mt_cjob()...
-Thom
-Thom
Re: Porting PLATOTERM to the QL as a QDOS app.
And by removing the io_pend() calls for keyboard and serial i/o, and depending on a zero time-out to simply return a NC, I am able to get the buffer to behave as expected, and am now able to successfully connect into IRATA.ONLINE, without any hiccups, at 9600 baud in Norma QL speed (using RTS/CTS), as to how this fares to a real QL, we'll have to see, would love to buy or borrow a unit for dev testing.
The new bits of code:
Now onto getting the text output fixed, making sure it doesn't wrap or break lines, then implementing the rest of the missing draw modes, implementing the new fonts, implementing font downloading, and finally implementing preferences.
The new bits of code:
Code: Select all
/**
* keyboard_main - Handle the keyboard presses
*/
void keyboard_main(void)
{
char ch;
int ret;
ret=io_fbyte(win,0,&ch);
if (ret==0)
{
if (ch==0x0a)
ch=0x0d;
io_send_byte(ch);
}
}
Code: Select all
/**
* io_main() - The IO main loop
*/
void io_main(void)
{
char ch;
while (io_fbyte(ser,0,&ch)==0)
{
buff[len++]=ch;
}
ShowPLATO(buff,len);
len=0;
}
Re: Porting PLATOTERM to the QL as a QDOS app.
That's what I use (It's assembler, but just use it, it was written By TT, the creator of QDOS. Ready to be compiled by C68-as). A data space of 500 bytes works well for me for most functions. Hand the independent job the end of an opened pipe to your main program or some shared buffer area it can place received characters in. You might want to set the job's priority higher than in your main program, and your loop will be able to block in serial input.:tschak909 wrote:How can I set up a seperate job for the serial i/o? I see mt_cjob()...
-Thom
Stolen from Tony Tebby's C PTR example routines:
Code: Select all
;******************************************************************************
;
; The function jcall sets up a C function as a dependant job.
; This Job can share the workspace of its parent.
;
; It returns the JOBID or 0 if the job fails. In this case, _oserr is set.
;
; The call parameters are:
; char * function
; char * job name
; long priority
; long data space
; long number of parameters to pass
; ..... parameters passed to function.
;
;******************************************************************************
.globl _jcall
sms.myjb equ -1
sms.crjb equ $01
sms.frjb equ $05
sms.acjb equ $0a
jcb_a0 equ $40
jcb_a7 equ $5c
jcb_end equ $68
_jcall:
movem.l d2-d4/d7/a2/a3,-(sp)
stk_func equ $1c
stk_jnam equ $20
stk_prio equ $24
stk_data equ $28
stk_npar equ $2c
stk_parm equ $30
move.l stk_jnam(a7),a0 ; first we count that characters
moveq #-1,d4 ; of the jobname 'cos C does not
jc_cntc: ; know about strings
addq.l #1,d4
tst.b (a0)+
bne jc_cntc
move.w sr,d7
move.l a7,a3
trap #0 ; atomic while we patch the jcb
moveq #sms.myjb,d1 ; create for me
moveq #11,d2 ; header and round up
add.l d4,d2
and.w #$fffe,d2 ; asm bug in bclr
move.l stk_data(a3),d3 ; data space
sub.l a1,a1
moveq #sms.crjb,d0
trap #1
move.l d0,__oserr ; error?
blt jc_njobu ; ... yes
move.l stk_func(a3),jcb_a0-jcb_end(a0) ; set Job's A0
move.l stk_npar(a3),d0
lsl.l #2,d0 ; 4 bytes per parameter
lea stk_parm(a3,d0.l),a1 ; the parameters
move.l jcb_a7-jcb_end(a0),a2 ; and push bits onto the stack
bra jc_parme
jc_parml:
move.l -(a1),-(a2) ; push parameter
jc_parme:
subq.l #4,d0
bge jc_parml
move.l a2,jcb_a7-jcb_end(a0) ; set job's stack pointer
lea jc_header,a1
move.l (a1)+,(a0)+ ; header
move.l (a1)+,(a0)+
move.w d4,(a0)+ ; job name
move.l stk_jnam(a3),a1
jc_cname:
move.b (a1)+,(a0)+
bne jc_cname
move.w d7,sr ; back to user mode
moveq #sms.acjb,d0 ; activate
move.l stk_prio(a7),d2
moveq #0,d3 ; and do not wait
trap #1
move.l d0,__oserr
bne jc_njob
move.l d1,d0 ; job id
jc_exit:
movem.l (sp)+,d2-d4/d7/a2/a3
rts
jc_njobu:
move.w d7,sr ; back to user mode
jc_njob:
moveq #0,d0
bra jc_exit
jc_header: jmp jc_wrapper ; jump to wrapper
dc.w $4afb
jc_wrapper:
jsr (a0) ; jsr to function
jc_die:
moveq #sms.frjb,d0
moveq #sms.myjb,d1
moveq #0,d3
trap #1 ; then die
Code: Select all
mjobid=jcall ((char *) function_to_run,"Name of function to run", job_priority, job_dataspace_size, num_params, params, ...));
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: Porting PLATOTERM to the QL as a QDOS app.
call to sd_fount() doesn't seem to make a difference, am defining the font here: https://github.com/tschak909/platotermq ... src/font.h
and calling it here:
https://github.com/tschak909/platotermq ... een.c#L169
Not getting an error code back, but it's also not changing the font. ARRGHH...
-Thom
and calling it here:
https://github.com/tschak909/platotermq ... een.c#L169
Not getting an error code back, but it's also not changing the font. ARRGHH...
-Thom