-
Content Count
7,205 -
Joined
-
Last visited
-
Days Won
8
Posts posted by Tursi
-
-
Looks like good progress! The questions were sort of unanswered - it's always 4 sprites on a line. This is a hardware limitation so it doesn't matter what language you code it in.
Besides the clever tricks Sometimes already mentioned, sometimes you have to flicker. There are two ways to do this.
One is to order your sprites so that the ones that disappear (higher number) won't really impact the game play. They vanish, but they were just extra colors.
The other is an actual flicker routine. The purpose of a flicker routine is to change the sprite numbers every frame so that if a sprite disappears, it will only be gone for one frame. There are a lot of ways to do this, but the approach I prefer is very simple and I haven't seen better results from any other. You can only get good flicker results from assembly or another compiled language, Extended BASIC won't be fast enough and can't detect the frame sync.
The first step is to determine how many sprites you need. The fewer sprites that flicker, the faster the flicker will be and the better it will look. For instance, let's say you want 16 sprites onscreen in your game.
The second step is to arrange your sprites. Assume 0-15 for now. Space out your multi-colored sprites so the different colors are 4 or more sprites apart - this helps to ensure some part of the character is always onscreen.
Finally, define your sprite table in CPU RAM - this is a mirror of the VDP sprite table. Do all your sprite updates there (this gives you a small speed boost, too, which is nice, and even a full 32-sprite table is only 128 bytes). Have an interrupt routine that runs during vertical blank. This interrupt routine will copy the sprite table to VDP RAM, starting at a different offset each frame. This way, your program still sees the sprites as 0-15, but the VDP will see different numbers each time, so different sprites are the 'highest' number and disappear on different frames. Persistence of vision does the rest, and you see the sprite as just 'flickering'.
This routine is also nice because you don't have to care whether any sprites are on the same line and need flickering or not - because you rotate the table every frame, the flickering just happens automagically when it's needed.
For example, let's say there are 8 sprites, and we have them all on one line. I will say they are the first 8 letters of the alphabet. When we first run the program, and we copy them to VDP, the VDP Sprite Table will see them like so:
A B C D E F G H
Because we can only have 4 sprites on a line, though, on screen we will see this:
A B C D
The next frame, we increment our start pointer by 4. We copy from there to the end of the table, then, knowing we aren't done, we copy from the beginning of the table to the start pointer. In essence, the CPU sprite table becomes a ring buffer. We increment by 4, because that's how many sprites are allowed on a line. So this time, the VDP Sprite table looks like this:
E F G H A B C D
but the actual sprite information has not changed, only the order in the table. Because of this, on screen we will see this:
E F G H
When the next frame comes, we again increment by 4. We notice we are off the end of the table (which was 8 entries long), and reset to 0, which will give us the first case again. This makes the sprites flicker 4 at a time (which is the worst case), and since there are only two frames before it repeats, the worst case is 1 in 2 frames.
If you had 16 sprites, then it would take 4 frames to repeat, so the worst case is 1 in 4 frames, which is still tolerable. If you use all 32 sprites, the worst case becomes 1 in 8 frames, which is not very tolerable, but since it's usually not too frequent, it's okay.
The pseudocode would look like this. I'll do it in Extended BASIC, and you can actually run it. You'll see how it works then, but remember to actually "flicker" you have to run it every frame, at that speed it looks good. (Even as is, you will probably want to speed up the emulator - with Classic99 use CPU Overdrive
). With the XB copy, it's slow enough that you can see the updates as they happen - this causes characters that shouldn't flicker to do so slightly as they are moved, and sometimes the wrong character is briefly visible. In assembly you do this during the vertical blank, so it's never visible.This code lets you move the 'A' with joystick 1, so you can see how you have to update the mirrored table and not the VDP one, but that it still works. You can also see how that affects the actual flicker, but it is very slow.
Run it at normal speed first, then kick in CPU Overdrive (or in MESS, whatever the speed up mode there is), and you can get a better visualization of the flicker itself.100 REM SPRITE FLICKER SAMPLE 110 REM SHOWS (SLOWLY!) A FLICKER 120 REM OF 12 SPRITES ON ONE LINE 130 REM MOVE THE 'A' WITH JOYSTICK 1 140 REM 150 REM THIS IS THE SPRITE TABLE 160 REM (ROW, COLUMN, CHAR, COLOR) 170 DIM ROW(12),COL(12),CH(12),HUE(12) 180 INDEX=1 :: REM WHICH SPRITE IS COPIED FIRST 190 REM 200 REM SET UP THE SPRITES 210 FOR I=1 TO 12 220 ROW(I)=100 :: COL(I)=I*12 :: CH(I)=64+I :: HUE(I)=1+I 230 NEXT I 240 CALL CLEAR :: CALL SCREEN(15) 250 REM 260 REM MAIN LOOP 270 GOSUB 350 :: REM COPY SPRITE TABLE TO VDP 280 CALL JOYST(1,X,Y):: REM READ JOYSTICK 290 REM NOTE WE HAVE TO UPDATE THE MIRROR, NOT THE 300 REM REAL TABLE, SO WE CAN'T USE AUTO-MOTION 310 ROW(1)=(ROW(1)-Y)AND 255 :: REM THE AND HELPS IT WRAP AROUND 320 COL(1)=(COL(1)+X)AND 255 :: REM THE AND HELPS IT WRAP AROUND 330 GOTO 270 340 REM 350 REM COPY SPRITE TABLE 360 REM YOU WOULD NORMALLY DO THIS IN ASSEMBLY 370 REM IN A SINGLE COPY OF A MIRRORED SPRITE 380 REM TABLE, BUT HERE WE HAVE TO DO IT 390 REM THE SLOW WAY. AT LEAST YOU CAN SEE 400 REM WHAT IT DOES! 410 REM COPY FROM INDEX 420 VDPINDEX=1 430 FOR I=INDEX TO 12 440 CALL SPRITE(#VDPINDEX,CH(I),HUE(I),ROW(I),COL(I)) 450 VDPINDEX=VDPINDEX+1 460 NEXT I 470 REM COPY FROM START 480 FOR I=1 TO INDEX-1 490 CALL SPRITE(#VDPINDEX,CH(I),HUE(I),ROW(I),COL(I)) 500 VDPINDEX=VDPINDEX+1 510 NEXT I 520 INDEX=INDEX+4 :: IF INDEX>12 THEN INDEX=1 530 RETURN
-
My converter (http://www.harmlesslion.com/cgi-bin/onesoft.cgi?102) has got a lot of time invested to making the images look good, also have a look at my document about it, available here: http://www.harmlesslion.com/text/Modern%20Graphics%20on%20the%209918.pdf
My tool uses perceptual color matching as well as Floyd-Steinberg dithering, though you can change the dither pattern yourself, as well as tweaking the resize filter and turning various optional settings on and off, even 'nudge' the image to work around the horizontal blocking if you like. It's about as plug-and-play as it gets - to convert an image, just drag it to the window. It resizes automatically (and has several options for dealing with images with a non-4:3 aspect ratio). It even has a secret 'random slideshow' mode... double-click on the empty window frame, and the 'Open' button becomes 'Next'. Click it, and select any file in the folder you want to slideshow. Each time you click 'next', it will randomly choose a file from that folder and convery it.

As for the output format, the standard most widely used is "TI Artist format", which is two separate files, one containing a raw 6k dump of the color table, one containing a raw 6k dump of the pattern table. It's assumed in this format that the SIT contains the usual arrangement of three sets of characters 0-255. If you name them with the extensions TIAP and TIAC, I actually have a Windows-based Photoshop filter that can read (not write) the files (I use it with ThumbsPlus for organizing the hundreds of images I have converted and kept with my tool) here: http://www.harmlesslion.com/cgi-bin/onesoft.cgi?112
Since there's no requirement for which comes first in VDP (color or pattern), and because there is 2k of unused space between them, and because the normal TI image file loaders manage 8k blocks at a time, two files was probably a reasonable compromise. Personally I prefer to keep existing formats unless they actually don't work, than to introduce new formats at such a late stage, but I seem to be in the minority there.
My converter can also RLC compress the tables, though I've more used this in my own software.

As an example, here's what my tool with the "Perc"eptual option and default filter does with the sample pic from the top:
(note that my tool scales the image 2:1 for display on the screen, that's why the pixels are large, but it is 256x192
) -
I'm kind of interested, actually. I don't have one, but I've been holding off getting one to inspire myself to build my PC interface already (it's amazing how much you can do without such a device when you're putting off harder work
). On the other hand, if nobody else claims it, I can probably use it for the faire.
(Which I still need to make sure I can get to...) -
I finally got a chance to check this thread out, and it's looking fan-tastic! I'll definately chip in on publishing costs, this must come out!

-
I'm not claiming this one... just merging the other two.

-
My own c99 games are Super Space Acer, Super Sled Acer, and Waterville Rescue:
http://www.harmlesslion.com/cgi-bin/onesoft.cgi?64
http://www.harmlesslion.com/cgi-bin/onesoft.cgi?28
http://www.harmlesslion.com/cgi-bin/onesoft.cgi?67
There's source, but they are very badly written. I've ported Space Acer and Waterville Rescue to the ColecoVision, and will be porting Space Acer back to the TI when I'm done improving it (though I need a new compiler..
) -
hehe.. very cool. If you want to use ZomBXB the text file in the zip is about the limit of my writing skill

-
Heh... so now that the contest is done, Codex, do you mind if I take TI Farmer and mash it up with ZomBXB? I'd like to do an asm version that gets the speed I wanted to see on the Zombie side, and at the same time we'll grant Owen's wish of seeing them together.

-
I can't get super specific with C99 these days since I don't think I have all the disks anymore (though I'm sure they are online). I did several games with it, though. It's a fairly limited dialect of C and the code it produces is not very efficient -- but it does work.
The basic process is first to write your program using the editor of your choice (normally Editor/Assembler, but it doesn't matter). Next, you run C99C in Editor/Assembler, and give it the input and output filenames - this compiles the code into assembly. Finally, run the Assembler to assemble the code into an object file.
To run, load the object file, CSUP (which is the C library), any other libraries you need, and I believe START is the program name.
You can use the Editor/Assembler image creation tool SAVE with C99 programs.. to do that, load C99PFI as the first modules, and C99PFF as the last one. After that, load SAVE and run it. The program must fit in the 24k bank to work this way.
C99 programs used to require the Editor/Assembler cart be loaded, and would hang otherwise. I don't remember if later runtimes fixed that. I tended to use my own startup code which bypassed the copy from GROM and manually loaded the E/A utilities into the load bank by making it one of the program images. That probably isn't going to be a concern when you are starting out.
Also... C99 programs will not run on a cartridge-only system, they require the 32k (because the stack is hard coded into the low memory bank). There are no switches to change that behaviour.
Feel free to ask questions, and if someone more useful doesn't pop up I can try to remember.

-
I'm quite happy with ABC. It's short, yes, but I don't mind games for short. It feels like Afterburner but looks beautiful and the play is even faster, so I like the thrill.

-
I always had that problem, too... never really got it to work with any glasses I tried, including the new ones in the box.
-
I think he's using the terms himself to mean "Game RAM" and "Game ROM", and they are not the TI GROM or related GRAM devices.
-
I couldn't reproduce, and the fix I had in mind is already in the code... that said, if you take focus away (click on some other Window), that should completely reset the keyboard code and stop whatever it's doing.
I'd like to know what's happening so I can fix it someday...
-
Yeah, INTERNAL is the best option for what you're doing. I tried using DISPLAY, but it auto-truncates to 28 characters in BASIC. And it won't permit characters above 127 either, I think.Is this actually true? I've always been under the impression it doesn't actually do anything but set a flag... have you tested that?
Damn it, I have too many things to test...

-
hehe... though it was a mistaken question, brought on by lack of sleep and memories of a much older bug I once ran into.
I've fixed this bug and uploaded a fixed Classic99. The keyboard issue from another thread I'd already fixed the way I expected, and couldn't reproduce, so no change there...
The sprite position bug affects any sprite row 1 (XB) and higher (though I still need to test that sprites fade out on the top on a real console.. I can't right now as my cartridge port is otherwise occupied
) -
Looks like some nice stuff brewing!
One comment on the disk files - there's no difference on the disk between DISPLAY and INTERNAL, it's just a flag in the header.

-
Have found and fixed the bug, will publish a new version later (with the focus keyboard fix too).... it would specifically affect fade-in from the top including the very top row, row 1, and cause the sprite to be drawn one row lower than it should have been. Thanks for the clear example of the problem!
-
Confirmed. (And validated on real hardware).
Well. This is strange. Will look at it a bit more after work, I'm late.

-
Neat sounding device, I will definitely take one if orders are still open.
-
Usually this happens if you use a keyboard shortcut to take focus away, for example, Alt+Tab -- Classic99 sees the alt and the tab down events, but Windows never delivers the up events because it doesn't have focus anymore (now that I think about it, it would be easy to clear the keyboard state when focus is lost, let me take a note on that and I'll code up that fix).
If you are running CPU overdrive, the keyboard repeat delay ends up way too short, and my workaround for that doesn't work in Extended BASIC, so you get massive keyboard repeats, although that at least should respect the keyboard.
There's no explicit reset built-in, but tapping the key that is repeating should stop it. Tapping Enter should clear any stuck meta-keys (control, alt, shift).
-
The real question is, "Where are the other sprites?"
CALL COINC(ALL) means ALL sprites, not just the ones visible on the screen. XB can actually throw a collision for sprites located off the bottom of the screen, where they all sit till they are in use (as Sometimes99er alluded to). (edit: that statement was full of it
)Just to verify, try bringing up the other sprites and placing them at notably non-touching locations, or like he suggests, try 1 and 2.
I believe I tested that real hardware sees collisions off the bottom of the screen... but that was years ago and is worth testing again, since I don't remember coding that in Classic99

-
The CF7 just pops up on EBay semi-regularly, as far as I know that's the only way to get one.
I don't have one, but I don't think you can use the CF7 and the PEB at the same time.
-
Yeah, there are all kinds of TI keyboard mechs (they are all electrically compatible though)... everything from discrete switches to printed plastic contact sheets. The switch ones seem to last forever unless they are in really dirty environments, the contact sheet ones I've had little luck with (and I don't know if they respond to being cleaned). More than likely the issue is oxidation and lack of use, so it might be possible to scrub them up, but it's generally easier to replace. So many spare keyboards flooded the "experimenters" market after TI dumped the console that they still aren't really rare (I have a box of them myself
). -
9228? How very interesting!
Slightly higher resolution, it appears (256x210), and 16 full colors from a 512 color palette, plus 80-column text, high resolution (512x192) and hardware scroll. Plus still more... how very cool.
It does appear very similar to Sega's chip. This would have been a fantastic chip to have, it has all the features I was wishing for.
The datasheet is all over the net... there's a note in an old TI newsletter that the 9938 was derived from the 9928 (but was not compatible), many of the otehr hits are in Japanese.
Interesting.. it would have been nice to have had this chip!

Challenge: Optimize this header...
in TI-99/4A Development
Posted
Finally got a chance to read here.. InsaneMultitaker's option is the best for saving space - by putting a different copy loop in each bank, you only need to select the appropriate bank, and then each bank would have a different set of data.
Also, of course, the character set copy code could be reduced by removing the 99/4 support -- I don't expect anyone is using a 99/4 in actual use given their limitations and value, but it was a challenge in my original code to make it work.
I'm glad it's working though.