tschak909 Posted July 25, 2018 Share Posted July 25, 2018 Now that I have working implementations of PLATOTerm for Commodore 64, Apple II, and the Atari, I am doing my planning for other platforms, and TI 99/4A is on that list. I've found tursi's ti99 lib for gcc, which would be very suitable as a low level library, and there are lots of helpers for talking to the VDP, etc... but I am wondering if there are e.g. any line drawing and dot drawing primitives that anyone might have? or am I going to need to roll a pixel plot and bresenham line routine? -Thom 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 25, 2018 Share Posted July 25, 2018 In c or assembly? Quote Link to comment Share on other sites More sharing options...
tschak909 Posted July 25, 2018 Author Share Posted July 25, 2018 preferably C, or in assembly wrapped in a C call.. doesn't really matter. -Thom 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 25, 2018 Share Posted July 25, 2018 (edited) Here's an assembly version I wrote a few years ago. It is using R10 as a stack pointer but that can easily be changed. I can't help with the c wrapping. ********************************************************************* * * Draw a line from (x1,y1) to (x2,y2) * * Adapted from C version at: * http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C * * void line(int x1, int y1, int x2, int y2) { * int dx = abs(x2-x1), sx = x1<x2 ? 1 : -1; * int dy = abs(y2-y1), sy = y1<y2 ? 1 : -1; * int err = (dx>dy ? dx : -dy)/2, e2; * for(; { * setPixel(x1,y1); * if (x1==x2 && y1==y2) break; * e2 = err; * if (e2 >-dx) { err -= dy; x1 += sx; } * if (e2 < dy) { err += dx; y1 += sy; } * } * } * * This version maintains a screen buffer address * and bit mask instead of coordinates. * * R0 x1 value * R1 y1 value * R2 x2 value * R3 y2 value * * Modifies all registeres except R10 and R11 * LFTBIT EQU >8000 * Leftmost bit of MSB RGTBIT EQU >0100 * Rightmost bit of MSB SEVEN EQU >0007 * Three rightmost bits of LSB * LINE MOV R11,*R10+ * Push return address onto the stack * Setup variables CLR R6 * R6 is sx = 0 MOV R2,R4 * R4 is dx = x2 S R0,R4 * dx = x2 - x1 JGT DXPOS3 DEC R6 * sx = -1 JMP LINE1 DXPOS3 INC R6 * sx = 1 LINE1 ABS R4 * dx = abs(dx)b CLR R7 * R7 is sy = 0 MOV R3,R5 * R5 is dy = y2 S R1,R5 * dy = y2 - y1 JGT DYPOS3 DEC R7 * sy = -1 JMP LINE2 DYPOS3 INC R7 * sy = 1 LINE2 ABS R5 * dy = abs(dy) C R4,R5 * Compare dx to dy JGT DXGTR3 MOV R5,R8 * R8 is err = dy NEG R8 * err = -dy JMP LINE3 DXGTR3 MOV R4,R8 * R8 is err = dx LINE3 SRA R8,1 * err = err / 2 MOV R4,R12 NEG R12 * R12 = -dx * Calculate screen address of first pixel (x1,y1) BL @SCADDR * R14 is byte offset 1, R15 is bit mask 1 MOV R2,R0 * Copy x2 to R0 MOV R3,R1 * Copy y2 to R1 MOV R14,R2 * Copy byte offset 1 to R2 MOV R15,R3 * Copy bit mask 1 to R3 * Calculate screen address of last pixel (x2,y2) BL @SCADDR * R14 is byte offset 2, R15 is bit mask 2 MOV R2,R0 * Copy byte offset 1 to R0 MOV R3,R1 * Copy bit mask 1 to R1 MOV R14,R2 * Copy byte offset 2 to R2 MOV R15,R3 * Copy bit mask 2 to R3 * Add buffer offset to start and end addresses AI R2,SCRBUF AI R0,SCRBUF * Reset working bit field in R13 MSB ANDI R13,>00FF * Clear MSB * Main loop LINEL SOCB R1,R13 * OR bit mask onto working bit field C R0,R2 * Compare byte offset 1 to 2 JNE COMPDX * Continue if different C R1,R3 * Compare bit mask 1 to 2 JNE COMPDX * Continue if different JMP LINEE * Break COMPDX MOV R8,R9 * R9 is e2 = err C R9,R12 * Compare e2 to -dx JLT COMPDY * Jump if e2 < -dx S R5,R8 * err -= dy MOV R6,R6 * Compare sx to zero JLT PRVCOL * Next or previous column? NXTCOL COC @RGTBIT,R1 * Check if byte should change JEQ NXTBYT SRL R1,1 * Next screen bit JMP COMPDY * Don't write to VDP RAM yet NXTBYT SOCB R13,*R0 * Write byte CLR R13 * Clear bit field AI R0,8 * Next screen byte MOV @LFTBIT,R1 * Set bit mask to leftmost bit JMP COMPDY PRVCOL COC @LFTBIT,R1 * Check if byte should change JEQ PRVBYT SLA R1,1 * Previous screen bit JMP COMPDY * Don't write to VDP RAM yet PRVBYT SOCB R13,*R0 * Write byte CLR R13 * Clear bit field AI R0,-8 * Previous screen byte MOV @RGTBIT,R1 * Set bit mask to rightmost bit COMPDY C R9,R5 * Compare e2 to dy JGT LINEL * Loop if e2 > dy A R4,R8 * err += dx SOCB R13,*R0 * Write byte CLR R13 * Clear bit field MOV R7,R7 * Compare sy to zero JLT PRVROW * Next or previous pixel row? NXTROW COC @SEVEN,R0 * Check if character row should change JEQ NXTCHR INC R0 * Next pixel row within same character row JMP LINEL * Loop NXTCHR AI R0,256-7 * First pixel row in next character row JMP LINEL * Loop PRVROW CZC @SEVEN,R0 * Check if character row should change JEQ PRVCHR DEC R0 * Previous pixel row within same character row JMP LINEL * Loop PRVCHR AI R0,7-256 * Last pixel row in previous character row JMP LINEL * Loop LINEE SOCB R13,*R0 * Write byte CLR R13 * Clear bit field * The end DECT R10 * Pop return address off the stack MOV *R10,R11 B *R11 * Return *// LINE ********************************************************************* * * Calculate screen address and bit mask from coordinates * * R0 x value * R1 y value * * R14 Set to byte offset * R15 Set to bit mask * SCADDR MOV R0,*R10+ * Push R0 * Calculate screen address from coordinates * Based on E/A manual page 336 MOV R1,R14 * R14 is the byte offset = y SLA R14,5 * R14 *= 32 SOC R1,R14 * R14 = R14 OR y ANDI R14,>FF07 * R14 = ? MOV R0,R15 * R15 is bit offset = x ANDI R15,7 * R15 = x mod 8 A R0,R14 * R14 += x S R15,R14 * R14 -= bit offset * Calculate bit mask MOV R15,R0 * Copy bit offset to R0 LI R15,>8000 * Set leftmost pixel MOV R0,R0 * Compare R0 to zero JEQ SKIPSR * Skip shifting if 0 - this would shift 16 bits! SRL R15,0 * Shift R15 R0 pixels right * * R15 is now the bit mask SKIPSR DECT R10 * Pop R0 MOV *R10,R0 B *R11 *// SCADDR Edited July 25, 2018 by Asmusr 1 Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted July 25, 2018 Share Posted July 25, 2018 Look at the source for snek Sent from my LG-H872 using Tapatalk Quote Link to comment Share on other sites More sharing options...
tschak909 Posted July 25, 2018 Author Share Posted July 25, 2018 got a link? -Thom Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted July 26, 2018 Share Posted July 26, 2018 well snek's source isn't released.. soo how about the ti library for gcc-9900 https://github.com/tursilion/libti99 which sets bitmap mode, you'll have to read the VDP datasheet to do the rest probably also here's the code to the mouse test which uses bitmap mode and uses libti99 https://github.com/jedimatt42/tipi/tree/master/examples/mouse Quote Link to comment Share on other sites More sharing options...
Zerock Posted August 2, 2018 Share Posted August 2, 2018 Drawing lines seems like an application-specific need. A text program might want to reclaim the space that would be taken up by a line-drawing routine. There's not line drawing in hardware, is there? If so, then I suppose it should be accessible from the standard library, but otherwise it's something the application developer should implement. There are lots of documented line-drawing algorithms. Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 3, 2018 Share Posted August 3, 2018 If written correctly, (just follow Tursi's patterns) then additional functions in libti99.a are omitted when linked if not actually referenced. -M@ Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 3, 2018 Share Posted August 3, 2018 Actually, I've got some experience here, I'll work up a pull request for libti99 -M@ Quote Link to comment Share on other sites More sharing options...
Asmusr Posted August 3, 2018 Share Posted August 3, 2018 Just noticed, in my listing these should have been DATA instead of EQU. LFTBIT EQU >8000 * Leftmost bit of MSBRGTBIT EQU >0100 * Rightmost bit of MSBSEVEN EQU >0007 * Three rightmost bits of LSB Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 4, 2018 Share Posted August 4, 2018 Ok, this was a fun diversion... pull request has been sent for libti99... in the meantime, my branch is available. I'm not good enough at assembly to tell gcc to inline that and only use all but 2 of the registers. I probably could grab a workspace from the stack, and call into an assembly routine... but for now, I just went to wikipedia and implemented the psuedo code as C. https://github.com/tursilion/libti99/pull/5/files There is tile-boundary based puts (put string) so you can still 'draw' text in bitmap mode. Set and clear pixels, and drawline... with some support functions. ( clearing screen, setting 'pen' color' ) -- aiming at high level and generic. Last color attribute for the 1x8 pixel block wins. -M@ 5 Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 4, 2018 Share Posted August 4, 2018 (edited) Actually, I've got some experience here, I'll work up a pull request for libti99 -M@ Make sure you ping me - I don't check Github often enough right now (Ah, you did ) Edited August 4, 2018 by Tursi 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 9, 2018 Share Posted August 9, 2018 Now that I have working implementations of PLATOTerm for Commodore 64, Apple II, and the Atari, I am doing my planning for other platforms, and TI 99/4A is on that list. I've found tursi's ti99 lib for gcc, which would be very suitable as a low level library, and there are lots of helpers for talking to the VDP, etc... but I am wondering if there are e.g. any line drawing and dot drawing primitives that anyone might have? or am I going to need to roll a pixel plot and bresenham line routine? -Thom Maybe you already have this... ? from "Rosetta Code. But it needs the setPixel() function and bitmap config for the VDP. void line(int x0, int y0, int x1, int y1) { int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; int err = (dx>dy ? dx : -dy)/2, e2; for(;{ setPixel(x0,y0); if (x0==x1 && y0==y1) break; e2 = err; if (e2 >-dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } } Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 9, 2018 Share Posted August 9, 2018 Maybe you already have this... ? from "Rosetta Code. But it needs the setPixel() function and bitmap config for the VDP. void line(int x0, int y0, int x1, int y1) { int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; int err = (dx>dy ? dx : -dy)/2, e2; for(;{ setPixel(x0,y0); if (x0==x1 && y0==y1) break; e2 = err; if (e2 >-dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } } I couldn't get that code to work under gcc, so I went with something else on wikipedia. I think the gcc optimizer was playing games with me... But now we have a set of routines in libti99: // bm_setforeground - specify foreground color to use when drawing void bm_setforeground(int c); // bm_setbackground - specify background color to use when drawing void bm_setbackground(int c); // bm_clearscreen - clear the screen and sets all regions to the // current colors void bm_clearscreen(); // bm_setpixel - turn a pixel on // Inputs: x - 0-255 - horizontal location // y - 0-192 - vertial location void bm_setpixel(unsigned int x, unsigned int y); // bm_clearpixel - turn a pixel off // Inputs: x - 0-255 - horizontal location // y - 0-192 - vertial location void bm_clearpixel(unsigned int x, unsigned int y); // bm_drawline - plot a line between two points void bm_drawline(int x0, int y0, int x1, int y1); // bm_consolefont - loads console font to vdp, then copies it up into ram for // later use in bitmap mode. Use this before switching to bitmap mode if // you want a TI font. void bm_consolefont(); // bm_putc - draw a character at a tile location. // Inputs : c - character column 0:31 // r - character row 0:23 void bm_putc(int c, int r, unsigned char alphanum); // bm_puts - draw a 0 terminated string at a tile location. // this provides no scrolling, or bounds limiting. // Inputs : c - character column 0:31 // r - character row 0:23 void bm_puts(int c, int r, unsigned char* str); // bm_placetile - draw a 8x8 pattern at the given tile. // Inputs : c - character column 0:31 // r - character row 0:23 void bm_placetile(int c, int r, const unsigned char* pattern); -M@ 2 Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 9, 2018 Share Posted August 9, 2018 Now that I have working implementations of PLATOTerm for Commodore 64, Apple II, and the Atari, I am doing my planning for other platforms, and TI 99/4A is on that list. I've found tursi's ti99 lib for gcc, which would be very suitable as a low level library, and there are lots of helpers for talking to the VDP, etc... but I am wondering if there are e.g. any line drawing and dot drawing primitives that anyone might have? or am I going to need to roll a pixel plot and bresenham line routine? -Thom You will find this has recently been done for you and merged into libti99 Enjoy. -M@ 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 9, 2018 Author Share Posted August 9, 2018 Much appreciated! This means I can immediately start a port of PLATOTerm. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 9, 2018 Author Share Posted August 9, 2018 Sorry, am a little topsy-turvy trying to dig through years of thread, but, where can I get the latest patches for ti99 GCC? -Thom Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 9, 2018 Share Posted August 9, 2018 Sorry, am a little topsy-turvy trying to dig through years of thread, but, where can I get the latest patches for ti99 GCC? -Thom I see you've found the gcc thread under the developement forum... so you are rolling... -M@ Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 9, 2018 Author Share Posted August 9, 2018 Yup, I've wound up using the installer script. Am working through the deps and it seems to be compiling. I needed to do a full upgrade of cygwin to get GCC 7.3.0... I've built ea5split and elf2ea5...am seeing what else I need.... -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 9, 2018 Author Share Posted August 9, 2018 (edited) Yup, have managed to build libti99 and the test program. And it runs in Classic99 in the E/A.. This is good. Yay. It looks like there are DSR routines. Are these sufficient to be able to do RS232 I/O? Apologies, this will literally be the first piece of software I've done for the TI-99/4A. -Thom Edited August 9, 2018 by tschak909 1 Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted August 10, 2018 Share Posted August 10, 2018 You should probaby fish with another topic (to get the RS232 interested people reading), cause I don't believe in practice anyone ever uses RS232 through the DSR, except maybe to open/configure it... The DSR will read and write records. This will be very inefficient for small protocols... Then your next hurdle, is that everyone who as accessed RS232 for terminal programs has done it in assembly... You'll invariably have to get dirty with inline assembly or some assembly modules in your program anyway... I believe the RS232 byte level access is going to involve a bunch of CRU bit manipulation.. but I've never done it... and I don't know where the reference material for that particular bit is. InsaneMultitasker is an RS232 wizard, as is Stuart Stuart has example assembly of talking to a serial mouse: http://www.stuartconner.me.uk/ti/ti.htm#connecting_serial_mouse -M@ Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 10, 2018 Share Posted August 10, 2018 ... Then your next hurdle, is that everyone who as accessed RS232 for terminal programs has done it in assembly... You'll invariably have to get dirty with inline assembly or some assembly modules in your program anyway... I believe the RS232 byte level access is going to involve a bunch of CRU bit manipulation.. but I've never done it... and I don't know where the reference material for that particular bit is. ... -M@ FYI, here, on Thierry’s site, is the CRU map of the TMS9902 chips on the RS232 card. [Edit: Per Matt’s suggestion, this post is repeated in post #2 of Accessing-RS232-via-C-in-gcclibti99] ...lee 1 Quote Link to comment Share on other sites More sharing options...
+9640News Posted August 10, 2018 Share Posted August 10, 2018 If you telnet into 9640news.ddns.net port 9640, look for the MyTerm source code. I think I also uploaded a version on Heatwave last month. In the archive, look for the SUB1 file that has assembly code for accessing the RS232. The snippits of code in that file should work whether you are using a 4A or Geneve. Now, I am not sure, but I do not believe some of the flow control is 100% so that you only pull bytes from the RS232 when you need them. Still a work in progress. On the Geneve though, I can run at 38400. Not sure what the fastest rate you can achieve is on a 4A before dropping characters. If you have flow control correct and with the correct cabling, I think you should be able to have only one routine instead of embedded checks for characters waiting inside other routines like your VDP reads/writes, etc. I can tell you a couple of things I have learned to keep in mind. I poll the RS232 quite frequently and store characters in a buffer. I have only seen this on non TI BBS's under a specific occasion, but with a Telnet connection at 38400 baud, I can get hit with an 8K+ chunk of inbound data pretty quick that is buffered. As it is a circular buffer pulling characters off it as fast as I can, it can still get overrun so things get dropped and never get displayed on the screen. Keep in mind you should anticipate needing a buffer that could be as large as the largest chunk of data you could receive between keypresses if you do not get flow control or handshaking right. Where this happens on my BBS, is if you do a scan for new messages or new files. If there is nothing "new", there can be upwards of 200 areas scanned with each area requiring a screen clear. So, there is a whole lot of VDP writing with it that just takes time. As far as your PlatoTerm software, are you anticipating using it with just RS232 software, or with TIPI? If you are Telnetting into the website, a TIPI interface should be relatively easy as I think Matt has that code available already for the 4A on github. Now, if you are writing for RS232 control and a WIFI modem, that will take some more effort. From what I have learned from Matt, if you have TIPI, your buffer can be relatively small as the TIPI is buffering everything on the PI and you just pull the characters off the port as you need them. Beery Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 10, 2018 Author Share Posted August 10, 2018 I will try to support both, especially as there is no TIPI emulation _ANYWHERE_. I do not have TI hardware, and do not have access to any close by, so I am having to do ALL of my work in emulation. ANY help that anyone can give to push this thing along, would be most appreciated. (please?) -Thom Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.