Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


intvnut last won the day on December 27 2016

intvnut had the most liked content!

Community Reputation

2,412 Excellent

About intvnut

  • Rank
    River Patroller

Profile Information

  • Gender
  • Location
    @R6 (top of stack)

Recent Profile Visitors

18,767 profile views
  1. What you really want, if you're going to do that, is a daughtercard that replaces the RA-3-9600 and has a socket for the STIC. With that, you could easily add a 20x24 character mode, double vertical-res text, multi-color background tiles, 256 GRAM tiles, full access to all 512 tiles in FG/BG mode (at least for the background; MOBs would still be limited), etc. With a little more elbow grease, you could also probably manage to do higher-vertical-res MOBs as well, just by curating the STIC's experience. Imagine a max-height MOB (128 scanlines?) that actually had different bitmap data on each scanline? That could be used to add a lot of detail to a scene when combined with higher-res BACKTAB. At some point, though, you have to ask yourself: Is it still Intellivision? I mean... look at this "TI-99/4A" demo, which is really just showing off the 100MHZ TMS9900 clone + DMA engine inside the F18A FPGA. At what point does it stop being an Intellivision and start being an Intellivision controller interface for something completely different? (Skip to 2:30 for where it gets really ridiculous.)
  2. That's correct. The priority bit is a little odd: It determines if a given sprite is in front of or behind the background pixels. But, it does not change its ordering with respect to the other sprites. You might be wondering how that works. First, the sprites are stacked on top of each other with 0 in front, 7 in back. Then, for each given pixel of the result, that pixel either goes in front of or behind the background based on whichever sprite was "front-most" in the stackup of sprites. This can lead to weird paradoxes. For example, suppose MOB #0 is a horizontal bar, and MOB #1 is a vertical bar, and they overlap like this: 111 111 111 00000000 00000000 111 111 All fine and dandy. Now suppose I set both #0 and #1 to be "behind" the background, and I overlap the bottom right corner with background pixels 'b': 111 111 111 00000000 0000bbbb 1bbbb 1bbbb bbbb So far, so good. Now let's say I change #1 to be "in front of" the background. The image becomes: 111 111 111 00000000 0000bbbb 111bb 111bb bbbb Weird, huh?
  3. I've never been great at reading linearly. I do more of a page level non-linear grep. Maybe that's why I'm better with data sheets and could never really grok fiction narrative.
  4. Finally found the mask number table, by the way. Page 197 of the same PDF. This confirms 32040 is the mask number for the RAM. I wish I could find a CPS for the "40-1/4K Exec. ROM", as it might tell us what pin selects Sears vs. Mattel.
  5. Aha... I figured out what's up with RA-3-9600-1. Basically, it looks like they speed-binned these turds, and the -1 parts aren't fast enough for PAL systems. See the clock period spec at the top of the page, and Note 2 at the bottom, on page 68 of this PDF: http://papaintellivision.com/pdfs/CCF10232011_00012.pdf And if that wasn't clear enough, on page 74: I'm sure I've read this text before. I must've forgotten about it.
  6. BTW, this is the doc that has all the thermal testing stuff: http://papaintellivision.com/pdfs/CCF10222011_00011.pdf
  7. Iiinteresting. I'm trying to remember whether I've seen Inty IIs with just the mask-number on top. I think I have. (That's that 32040 number you mentioned previously.) Sounds positively chilly compared to this:
  8. That's actually by design. As the RAM test goes on, it increases the number of iterations of each test. The net effect is that it appears the test sequence slows down. Really, it's iterating each test in the sequence more times. I'm not sure that's necessary. And I'm almost 100% certain they won't fit in an Intellivision II with heat sinks, as the trays for the controllers nearly rest on top of the chips. The chips that were intended for use only with heat-sinks tend to have their pertinent information printed on the underside, and came with heat sinks epoxied on the top.
  9. If the IAB bus phase doesn't produce the right vector at reset, then the machine won't boot. That's a nice single-point-of-failure right there. IAB is supposed to return $1000 right after reset, and $1004 subsequently. It only knows about reset thanks to ~MSYNC. So, if its ~MSYNC pin is damaged... Basically, if ~MSYNC is damaged and IAB causes the ROM to output the interrupt vector ($1004) rather than the reset vector ($1000), things are unlikely to go well from there, as the stack pointer isn't initialized, the RAM interrupt vector at $100/$101 isn't initialized... it'll send the CPU on a jump into some random location, most likely $FFFF. Since ~MSYNC is a pin that's also exposed on the cartridge port, I suppose that's a likely candidate for ESD strikes and damage.
  10. I'm pretty sure the IntyBASIC random number generator isn't meant to be repeatable. It has a _next_random function that gets called in the interrupt service routine to advance the random generator. If you want a repeatable, replayable random number generator that runs from solely a seed and produces the exact same random numbers every time from that seed, you'll have to code one directly, I think. LFSRs are cheap both in execution time and storage. If you have some RAM to spare, a lagged-Fibonacci generator is also cheap, but requires RAM for the state. And, of course, you need to expand the seed to initialize the lagged-Fibonacci history buffer. I'm guessing you don't want the xkcd approach: And then there's the Doom approach.
  11. Found it right away, I see. Awesome! It's fun to watch, isn't it?
  12. Actually... I have seen Rick Koenig's original docs for his debugger (Version 3.0). He specifically mentions using "two of your business cards" as overlays (presumably drawing the debugger inputs on the back). I kid you not.
  13. I keep staring at that and it hurts my eyes. I know you're losing 6 cycles to "ADDI" being split into "MVII + ADDR", but it feels like you're losing as much to "SLR + MULT." This sequence: ANDI #248,R2 SLR R2,1 MULT R2,R4,5 ADDR R2,R1 expands to: ANDI #248,R2 SLR R2,1 MOVR R2,R4 SLL R2,2 ADDR R4,R2 ADDR R2,R1 That's 40 cycles and 7 words. If you coded this in assembly yourself you could do: ANDI #$F8, R2 SLR R2, 1 ADDR R2, R1 SLL R2, 2 ADDR R2, R1 That's 34 cycles and 6 words, and leaves R4 untouched. *shrug* If you care about 6 cycles and one word, why not code directly in assembly?
  14. BTW, in case I wasn't clear: I'm documenting what's already shipped and is in all 600-ish LTO Flash units today, and has been in jzIntv for over 3 years now. If I change anything, it will be to add to the ISA in a backward compatible way. Yes, there aren't any programs out there that use the existing ISA. But, the ISA has already shipped, and is actually verified. There's no real indication you're in an interrupt context or not. PV is not banked nor is it preserved. PV is primarily intended to be ephemeral and should be consumed immediately after it's generated. The instructions that set PV are also non-interruptible. Thus, the intended, safe and idiomatic use of PV is: EXT3OP X0, X1, X2 MVI PV, R0 I should make this clearer in the documentation. It's not meant for any other use. From this, you can implement a number of interesting idioms, but you really have to bolt a MVI or ADD, or something next to it to immediately consume the value. In general, using the extended register set (X0 - XF) from an interrupt handler needs to be done with care, as the standard ISR save/restore won't save and restore it. I'd wanted PSHM/PULM to make that more efficient. For now, it's maybe easier to say "don't use these from ISRs," but I need to include context switch concerns in the Programmer's Guide as well. Either that, or partition the Xregs so that some are for interrupt context and the rest are for foreground context. There are 16 of them. If I do an "upgrade" to the ISA, it might be work considering register banks as well, similar to an 8051. I don't want to try to detect "return from interrupt," though. I'd make bank selection manual. But, it'd be one instruction as opposed to many. At the start, I really wanted to avoid having an external status register, in particular because I hadn't worked out how to do branches efficiently. As it stands, I have a limited ability to encode new conditional branches efficiently, and I may have wasted my one opportunity by using the MVI xx, R7 encoding for TSTBNZ. I encoded the CMPxx the way I did, to better reflect how IntyBASIC performs comparisons. The CMPxx& construct allows you to build compound comparisons quickly, or to conditionally zero out a value (think "break statement"). A XSWD becomes part of the interrupt context in a strong way. PV seemed safe to me as long as you stick to the idiomatic use. XSWD is a little more of a problem because the instruction that generates it is not necessarily immediately before the instruction that consumes it. Reading it and PSHR'ing it onto the stack is no fun either. And then there's the simple concern that it's costly for me to compute. Some of the ISA implementations pushed the limit of what I could do on a 40MHz PIC. The I2BCD, BCD2I, ABCD/SBCD, ATAN2, and ISQRTFX were tight, as I recall. If you gave me 20% more cycles, I could compute the flags. I don't have those cycles. The lack of flags forces you into a "branch-free algorithm" mindset. Given that branches are costly anyway, it's not necessarily a bad place to be. What I'm missing is a good conditional-move instruction to round it out. "Based on src1, conditionally move src2 into dst." I like them, but I couldn't figure out how to arrange the operands to make it efficient. It really wants to be a 4 operand instruction, with the extracted-from entity separate from the extracted-to entity. In the end, I settled for a two-instruction sequence of shift (or multiply) followed by a rotate. Perhaps, in a V2 of the extensions. As you note, this starts looking more like an anti-goal. I'd need to consider whether to prioritize GRAM loading efficiency or obviousness. (e.g. use the more obvious encoding of 8 LSBs in each of 8 registers, or the more efficient encoding of packed 8-bit pairs in 4 registers.) And, without PSHM/PULM to quickly block transfer data into and out of the Xregs, the memory bottleneck quickly overwhelms whatever you might save. So, I decided to table those ideas until I had an efficient way to get data into and out of Xregs. I didn't bother trying to solve that one, as JLP stores 10-bit ROM in 12-bit pages rather than 16-bit pages, and already gets most of the benefit for me. (The 16-bit vs. 12-bit decision works on 4K page boundaries. Any game with significant voice can pack it in dedicated 4K pages and get the benefit.) That said, if you set aside an 8 word buffer of RAM, it wouldn't be hard to write an efficient 5-to-8 decoder that took a block of 5 16-bit words and output 8 10-bit words using the existing shifts and bit operations. It just didn't seem like the more pressing concern. A better use of my time would be to work on a tighter encoding for Intellivoice data, as the current data is not at all compressed. Yes, I used both meanings from C here: Address-of for the effective-address addressing modes, and bitwise-AND for the comparison instructions. I figured there's enough variation in heading update logic that having the inverse didn't make sense. You can easily convert ATAN2 into sine/cosine values of the desired precision with something like: ATAN2 R0, X0, X1 MVI @X1(sintbl), R1 ; sine value MVI @X1(sintbl+4), R2 ; cosine value MPY16 R1, X2, X3 ; assume X2 is velocity MPY16 R2, X2, X4 If you instead wanted to do that in fixed point, just replace MPY16 with MPYFXS. Or, if you want to model rotational inertia and use a finer-grain sine table, you could do that. etc. etc. Ah, remember the bad old days of how to detect 8088 vs. 8086 vs. 80286, before they added CPUID? I could even return a short manufacturer string like x86 does ("GenuineIntel" / "AuthenticAMD"). "LegitLTO"? I need to check whether RXSER / TXSER modify the register when branching to the error path. In any case, JLP and Locutus both put their serial port at the same address, so if / when these instructions come to JLP, the address for serial status will be the same. If someone figures out how to backport this to a CC3, you could always add a CP-1600X compatible serial port window at the alternate address. That's an out-of-place accumulation, as it required storing the intermediate result in X8 - XB. An in-place accumulation would have stored the accumulated value directly in X4 - X7 without disturbing other registers (except perhaps one for the carry). If I had instead defined the extended precision instructions as adding the carry/borrow to dst_hi, then I could have gotten away with fewer new instructions (just 2 rather than 4). This is a case where the rapid speed with which I spec'd the ISA caused me to miss an opportunity.
  • Create New...