-
Content Count
7,205 -
Joined
-
Last visited
-
Days Won
8
Content Type
Profiles
Member Map
Forums
Blogs
Gallery
Calendar
Store
Everything posted by Tursi
-
I may have to revisit the directory stuff in a few weeks, Tim, particularly how the hard drive works. I have an upcoming project of my own that I'd like to be as generic as possible.
-
All the nurses got into this new fangled World of WarBeasts or something, bunch of friggin' cows running around with axes, I don't know. In my day we had a yellow block, and that was Indiana Jones, and the green block was a snake, and that was all the gameplay we needed! And Facepage! What the heck? Bunch of tiny one-liners from every moron on the planet squeezed between a bunch of lame pixel games that make our own TI MOTIF look like a $10M blockbuster! Couldn't even get near the computer for the interwebs. I've been pretty busy working for Neato Robotics on the next generation cleaner... hacking low level all day leaves me pretty satisfied so I haven't been doing much at home. That's due to end in another 3 weeks so hopefully I can get back to the hobby stuff!
-
They are long gone already
-
Uhoh.. do I have to modify my birth certificate to avoid being kicked out? I can get pretty grumpy in my old age.
-
I want to go.. perhaps I should take the time to book that now and turn 'want' into 'will do'. I finally came up with a concept I really want to do.. but the faire is coming so fast it's going to be very hard to get a proof of concept built (especially if my contract at work keeps getting renewed!) Regarding the talks at last year's faire - I agree that I wanted to socialize and chat and SEE what people brought, too - the plan was a little over half a day of presentations and the rest for that. Unfortunately the library double-booked our room, and we lost the entire morning while some mother's group did playtime with their kids. By the time we got the room and got setup, we only had about 3-4 hours before we had to vacate again. Very frustrating. I'm sure that will be on Hal's mind this year, to make sure we get our allotted time! And perhaps better control the time spent by talkers. My own presentation came up short as my machine was unstable once I got it there (and worked fine again when I got it home, of course. This is apparently a normal curse of that room). The pub crawl was surprisingly fun - I've never done that before, but the little group we had was fun to hang out with, and we did get to talk about a lot of different things.
-
CV manuals and screen shots for SD Multi-Cart
Tursi replied to 5-11under's topic in ColecoVision / Adam
On the TI-99, they actually considered two columns on each edge of the screen to be potential clip victims, and only used 28 characters for text. I never saw more than 2 columns total clipped, myself, on many TVs over the years. I suspect that it's not going to be terrible, and the horizontal width can often be adjusted. -
My previous post was a bit snippy, and I realize you may have misinterpreted my information. We're actually talking about several different issues here now, in terms of your reply. We're talking about avoiding the problems caused by the NMI interrupting VDP access, we're talking about delaying the VDP interrupt so that access is safe, and we're talking about missing VDP interrupts. So first we should talk about how the interrupt system works in this configuration. The TMS99x8A datasheet gives this description of the interrupt out line: The interrupt enable (IE) bit in VDP Register 1 is the bit I was describing above. It's simply a mask bit for the vertical blank status bit (F). The datasheet tells us this about (F): It further notes, on clearing this bit: Besides a bit of confusion in calling F both the interrupt flag and the Frame Flag (they mean the same thing here), the important points of this at the VDP is fairly straightforward: 1) The VDP F bit is set at the end of each active display (ie: at the beginning of vertical blanking) 2) If the IE bit in VDPReg 1 is set, then F is mapped to the external interrupt line, with '1' making it active 3) The F bit is cleared by reading the status register. Therefore, the VDP asserts the external interrupt only when both IE and F are set. The order in which they are set is irrelevant, so it's okay to set IE after F has been set, it will still assert the interrupt. INT (active low) = IE NAND F Now, the Z80 NMI pin is edge triggered, that is, it only considers an NMI to have occurred when the line changes from inactive (high) to active (low). Therefore, if the VDP keeps the pin low, subsequent NMIs will not be detected. This is what permits the software workaround to function. So now let's cover what happens in the software workaround case. We will assume an interrupted VDP operation. -First, we set our VDP lockout flag. We start working with the VDP. -An end of frame maliciously occurs, and code execution jumps to the NMI. The NMI code sees the lockout flag, and does not touch the VDP this frame. It sets the NMI happened flag, and returns. -We finish working with the VDP. -We check the NMI happened flag, and we see that it was set. We read the VDP status register to clear the interrupt, and the next frame is ready to come in. -And, finished, we clear the VDP lockout flag. This works, but it takes user code and two flags (which in most people's code will be two bytes). The NMI needs to do extra work, and the main code needs to do extra work every time it touches the VDP. The system operates normally, but with this approach you can't put any VDP work into the NMI function unless it's okay for that code not to execute some frames. An approach that I tried instead was to do all VDP access inside the NMI itself. This works as long as you can afford the RAM to double-buffer things (in particular I double-buffered the sprite table, which makes flicker easier, and I also copied graphics data out of ROM each frame in response to pointers to animate sprites). You must be able to guarantee that you can do all your work in a fixed amount of time - preferably less than one frame, since you are probably still doing game code after you return! This can be difficult to arrange, since the game logic MUST NOT touch the VDP, it can only queue up requests. It looks like this: -Main code is humming along, working only with CPU RAM - buffers and pointers for VDP work may be set but the vDP can not be accessed directly. -VDP interrupt fires, and the NMI takes over. -CPU buffers are updated with VDP RAM (usually writing to it). The NMI starts in the vertical blank, so you can use fast writes if you keep it small enough. All pending VDP work is done here or postponed, if it is determined to be too much. (You have to come up with your own way to determine that). -VDP status register is read to clear the interrupt -NMI returns So no flags or extra code, but there are restrictions on the main code not being allowed to touch the VDP, and the NMI has a time restriction which must be honored. So what happens on other systems, who mask the VDP interrupt in the CPU? There are two trains of thought I have run across. The first, is to only disable the VDP interrupt for brief periods of time, and only when working on the VDP. For instance, like so: -Main code is running, but wants to talk to the VDP (except status register) -interrupts are disabled -VDP is accessed - VDP interrupt line asserts during this code, but CPU has masked it so ignores it -interrupts are re-enabled -CPU processes still-active VDP interrupt There's nothing wrong with this, really, except that you have to wrap all VDP access with a couple of extra instructions. But it keeps latency to a minimum without requiring any structure to the code, and on most CPUs the interrupt enable/disable is a single instruction. The other way I've seen is to leave interrupts disabled for all processing, and enable them only briefly during the loop. This is how the TI-99/4A usually writes code. In that case, you get something like this: -Main code is running, is free to talk to VDP at will (except status register) -VDP interrupt line asserts during loop, but CPU has masked it, so ignores it -Interrupts are enabled -CPU processing pending VDP interrupt -Regardless as to whether an interrupt occurred, interrupts are disabled -Loop repeats Literally, the enable/disable is two lines of code side-by-side. On the TI it's: LIMI 2 * enable VDP int LIMI 0 * disable VDP int If an interrupt is pending, it gets its chance to execute only during that window. This is okay, because it's either ready or not, and if it is, it doesn't matter that the slice is small. The downside, again, is that your loop time needs to be fairly consistent so that you get a steady framerate. If you process for 2 frames, then enable the interrupt, you only get one interrupt, so to be steady you must ALWAYS process for 2 frames. For the Coleco, the first option of these two is not possible. We can't mask NMI on the Z80, and it's not safe to temporarily disable interrupts on the 9918, because it takes two writes to do it. You might be interrupted even while you are disabling them. The second option is not too bad, though. It's always safe to turn the interrupts on if they are off already, and if the interrupt fires, then it is going to be safe to turn them back off again. However, there is a tiny race for the case where the interrupt didn't fire.. it might fire as you are turning the interrupts off again. This would only happen if your processing took you close to the edge, and you never synchronize with the vertical blank. All of the above generally ignores synchronization - which is a major reason for using the vertical blank. This helps you get a real-time source for your game. To that end, one of the flags mentioned way above - NMI Happened - is very useful. If you instead change the enable/disable sequence into a "wait for frame", then you can do this very safely (as long as your NMI takes less than a full frame to run). The NMI just needs to set that flag. That sequence looks like this: -Clear NMI Happened -Enable VDP IE bit in Register 1 to allow interrupts -Wait for NMI Happened to be set -Disable VDP IE bit in Register 1 to disable interrupts -Main code loop continues This is pretty decent. It's safe so long as the NMI is guaranteed to take less than a full frame to execute, because then you can predict when the disable write takes place. It gives the main code freedom to talk to the VDP (except the status register, this is needed to trigger the NMI). If your title needs the status register, you have a couple of options. For one, you can disable interrupts altogether - clear the IE bit and run at will. You can manually check for the F bit in the VDP Status register to provide synchronization. The same loop above will work, but instead of an NMI happened flag, you just poll the status register until F is set. The other way, and a common one, is to cache the VDP Status register in RAM somewhere when the NMI reads it to clear the interrupt. One final approach, that I noticed in the Mario and Zelda disassemblies from the NES, I think is rather clever and something I might try myself. They run the entire game logic on the vertical blank itself -- this is pretty much the opposite of disabling interrupts and polling. The main code loop just spins, waiting for an NMI to fire. When the NMI does fire, it runs through the entire game logic for one frame before clearing the status bit and returning. This has the same limitation of timing - you need to run a relatively consistent timing, ideally under one frame, but it works well, and has no limitations on VDP access at all, while giving you hardware timing without any variables. I'm getting tired and probably rambling - hope that's clear to someone.
-
That's also true for disabling it on the CPU, as you noted in your previous post: You don't miss the retrace at all. It will remain pending until you read the status register. It is possible to miss an entire frame, but it is regardless of where in the chain you mask it. Given that this is what most other systems do, and working with it for better than 25 years, as well as using it in my ColecoVision Super Space Acer port, I can assure you that it works just fine for action games.
-
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
I was just thinking that. Amazing sometimes what gets locked instantly while other pointless arguments carry on for 9 pages (and counting). That's cause we aren't in the Jaguar forum Running away now... -
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
Thanks! I hope to get to them next month or so. -
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
And since I came back late, too, and replied a few times, now that I'm caught up on the thread, I think a lot of great ideas were put up. With respect to my two games, he has removed the download links and replaced them with website links, which makes me happy. Hopefully he's no longer selling them to people. I'm satisfied for now. -
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
That's funny because neither Super Space Acer nor Waterville Rescue, my two homebrews, are authorized for distribution in such a manner. But they are both there. (I have sent my take down request). Super Space Acer includes this text in the download archive: Waterville Rescue has the even more explicit: So it's not like they should have been mistaken as ROMs that could be repackaged and sold - I don't even permit distribution. -
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
He had to program it. He is the author of the code. There can be no doubt of that. Using their IP would be the only issue. By making it look, feel, play like their IP does not mean he doesn't own the code he wrote from scratch, only that he is responsible for the reproductions of how it was fashioned to be so similar (getting authorization, or possible action against him for using it without permission). This is why so many Pac-Man clones are "Munch Man" or other clever names. AX then he should of call it something other than 'Mario Bros.' maybe 'Plumber Bros.' It would seem to come closest to falling under "derived work", since it is a new work that is based on an existing copyrighted work. At least under US Copyright law. http://en.wikipedia.org/wiki/Derivative_work (Wikipedia is suprisingly on the ball for this article, and cites the relevant passages of the actual law so I don't need to). Because the work doesn't demonstrate its own originality, it probably has no copyright protection of its own. However, Nintendo could still come after it for copyright infringement of the original, if they chose to. All of it is original and not ported from any other system. -
When I first got into Coleco work, seeing this assertion (written elsewhere by others!) really threw me, because I took it at face value. I came from the TI-99/4A where it's also maskable on the CPU. So I did all the little workarounds for being unable to predict when the interrupt would occur (what worked best was doing all my VDP access immediately after VBLANK, and making sure it could all be done in less than one frame). But it's actually not strictly true. You CAN prevent interrupts from occurring any time you like. You can't mask it on the Z80, but you CAN mask it on the VDP. I think since every other system lets you mask on the CPU, we all forget about that bit? Bit 2 in VDP Register 1 has the VDP enable bit. When cleared, the VDP will not assert the interrupt pin on vertical blank. When you set this bit again, if the interrupt bit in the status register is set, then the interrupt pin is asserted. With this knowledge, you can delay the interrupt as long as you need to. You can also do away with the interrupt, and poll the status register, if you prefer - note that reading the status register will still clear the interrupt bit. So if that's useful, this is the code that I'm using, patterned after the rest of the library that I was using. // enables and disables the vblank interrupt so we can run safely void cv_vdpout(const unsigned char reg, const unsigned char data1); extern uint8_t cv_vdpreg[2]; // in CV lib void cv_set_vint_active(bool active) { cv_vdpout(0x1, cv_vdpreg[1] = (active ? 0x20 : 0x0) | (cv_vdpreg[1] & ~0x20)); } Note this library has a cache of VDP registers 0 and 1 named cv_vdpreg[], and has a function named cv_vdpout() used to set the register, but it should be pretty easy to adapt it to another lib. I've been moving to my own code lately just to make it a little more familiar to my TI background. All my code does is take the cached version of VDP register 1, mask out bit 0x20 (VDP Interrupt enable), and then if you pass in 'active' as true, ORs the value in. It then saves the result back in the VDP register cache, and passes it to cv_vdpout, which writes the resulting value to the register. Note, of course, that if you are using any BIOS or library functions that need to run on the vertical blank, that disabling the interrupt may interfere with those. hth!
-
I don't have any GOOD example code. But for the standard TI devices, yes, the PAB must always be in VDP RAM. Anything that's compatible with them will expect that as well, and also the OS itself expects this when it does the DSR search, which needs the PAB.
-
A minor thing, but I ported one of my TI BASIC games to Batari BASIC with moderate success. It couldn't be a direct port since the 2600's resolution was much lower, but it didn't take more than a couple of hours. http://www.harmlesslion.com/software/spacefight Someday I'd like to ask for help here in getting a kernel that will give me a smooth slope on the side windows. I have the basic idea but I couldn't quite figure out what the Batari kernel was doing there.
-
Unless you know something we don't know, there's no way in software to change the wave output shape of the sound chip?
-
Classic99's sound is pretty close now.. still not perfect. In particular it can only change rates over 60 times a second (that's a temporary limitation), and I haven't verified the output of the white noise generator. In working on it I've already learned a few ways that it differs from popular documentation on similar sound chips (a big example is that if you set the frequency count to 0 on the Sega variations of the chip, you get a flat line high output, but the TI's version of the sound chip treats that as a count of >0400, making it the lowest possible frequency, which >03FF the second lowest). The white noise generator is the biggest deal -- every variation of the chip did it a little differently, and if it doesn't match any of the normal patterns, it might be tricky to get the right values for it. But it sounds close enough for now, and the period should at least be right.
-
I respectfully disagree. I've played those versions, as well the Genesis version had a 3-button mode. It's just not the same - the game is designed for six. I've made do without too much complaint using 4 buttons on Playstation pads, but that's about my minimum. There was a Game Boy version of Street Fighter, too. Just because someone sold it didn't mean it was any good.
-
Unauthorized copies of ColecoVision homebrew games
Tursi replied to opcode's topic in ColecoVision / Adam
I'm glad you guys haven't deleted this thread yet - you have to give everyone a chance to actually see it, y'know. My titles are up there too, and are explicitly licensed as "not for distribution" from my site. So I've also sent a note. In a week or so I will have a friend order the package, and see if my ROMs are on it. -
I've been thinking about how to pull off SF2 on the TI for years. But we need 6 buttons for that. We do have enough ROM now.
-
Yeah, it still uses the very, very old joystick API, that only supported two joysticks and I think 4 buttons. I need to update it to use DirectInput (or whatever the current version of that API is), then there will be a lot more flexibility.
-
I guess the next big step in TI debugging is source-level debugging. The unfortunate side is that the object file formats don't have the information we need - but I've been thinking that if we also use a listing file, we should be able to do it... they contain all the labels as well as source line numbers.
-
No, there isn't, but you've given me a reason to update that.
-
It's an emulator, we can do anything. Want a high-resolution, true color title page? We can add a single opcode to do that. (In fact I do that in my old Super Space Acer DX project, where I was upgrading my original TI game by adpating the emulator instead of the code. I didn't quite finish the 3D perspective, but you can see it here: http://www.harmlesslion.com/cgi-bin/showprog.cgi?search=dx 64k of VRAM is easy, we only change the amount of RAM reserved and the VDP address mask. It's just a question of how far from the original hardware you want to stray. Once you cross a certain, nebulously defined point, you are using Classic99 more as a development platform than an emulator. Personally I have no problem with that.
