Jump to content

EricBall

Members
  • Content Count

    2,362
  • Joined

  • Last visited

Everything posted by EricBall

  1. My Propeller video driver is almost done, but I've run into a snag. The following is a snippet from the pixel byte to long lookup routine. SHR sprgfx1, #8 ' shift byte into position MOV sprbyte, sprgfx1 AND sprbyte, #$0FF wz MOVS :byte6, sprbyte ' update source pointer MOVD :byte6, sprdata ' update destination pointer ADD sprdata, #1 :byte6 IF_NZ MOV sprdata, sprbyte ' copy color lookup table entry to lineRAM SHR sprgfx1, #8 wz MOVS :byte7, sprgfx1 MOVD :byte7, sprdata :byte7 IF_NZ MOV sprdata, sprbyte ' won't work due to pipeline DJNZ count2, #:nxtspr ' decrement active sprite counter JMP #doblank ' max number of active sprites reached :nxtspr ADD sprptr, #4 DJNZ count1, #:loop ' 48+16+223 = 287 (288) max cycles / sprite doblank What's going on here is some self-modifying code 'cause the Propeller doesn't have any indirect addressing. My problem is the propeller is moderately pipelined, so the next instruction is fetched before the current instruction has been executed. So :byte7 MOV won't reflect the MOVD as it currently stands. For all of the other cases I've been able to slip the ADD instruction back before the MOV, but I don't have that option for :byte7. I could just put a NOP in there, but that adds 4 cycles to the loop, which effectively adds 16 cycles due to external memory timing. (ick!) Other options: 1. Slide back the DJNZ. But then I need to copy :byte7 so it gets executed before the JMP. That's 3 opcodes (again due to the pipeline) and I'd like to only add max 2 for other reasons. 2. Roll up the byte to long translation. Code space efficient, but more cycles. Any other suggestions? (The wz / IF_NZ are to make color 0 transparent. The condition codes are under application control and every instruction may be optionally executed. So wz sets/clears the Zero condition code and IF_NZ executes the MOV only if the Zero condition code is cleared, i.e. the value of sprbyte is non-zero.)
  2. I can't say that I'm impressed with Purr Pals. A lot of repetitive touchscreen scribbling to "care" for your kitten. My son hasn't gotten into the "petshow" portion yet though. SM64DS is an excellent port/update of the original, but really suffers from the lack of an analog control stick. (Why they didn't make the Dpad on the DS analog capable?)
  3. How many of these games are ports from other systems? A port automatically has three ways of going wrong. First, the usual differences between systems - resolution, colors, sound capabilities, different processor, etc. Second, the 7800 graphics system is very different from anything else so it's much more difficult to leverage the code from the source system. Finally, ports are often done as a quick money grab so the publishers don't want to sink a lot of development money into porting the game.
  4. Except that beer is a pretty poor substitute for scotch.
  5. I've spent a lot of time over a lot of years working at the assembly level on a wide variety of processors. It's kinda like knowing several spoken languages, each new one becomes easier to learn (assuming it's not radically different from what you know). Yeah, I saw a post on the Parallax forum on how to sync the cogs. It was a kind of a "duh" moment. WAITCNT to sync to a fixed time on all cogs, then a hubop to sync them to their position on the hub. Uh-oh. The video generator just grabs D&S even without a WAITVID? I was assuming the shift registers would just go to zero until the next WAITVID. Which means the cogs which aren't outputting video need to so something to the video generator so they don't corrupt the output of the cog which is generating video. Might be sufficent to simply change the direction register to input for the cogs which aren't putting out video.
  6. I think at some point there's a law of diminishing returns. You could very easily end up without enough cog power left to actually manipulate those sprites. Going with more video cogs might make it feasible to go back to the calculated byte->long translation for color, thus leaving half of the cog RAM for code which could do things during VSYNC. More time might also make a tiled background possible, but I think that would need too many hub cycles to be effective for anything more than lo-res. I think 3 cogs is a reasonable sweet spot for my design. I particularly like the 1/3 pixel side-effect.
  7. I've been doing a bunch of think-coding over on potatohead's Blog trying to work though making Propeller code capable of generating a 240x240 resolution sprite display. For those not familiar with the Propeller, it's an 8-way SMP processor in a very low cost ($13 each) package. Each processor (or cog) has 496x32 bits of RAM which functions as registers and code & data storage (self modifying code is almost required), with 32K of shared RAM accessed in round-robin fashion (very deterministic once it gets going). Code is either written in a high-level interpretted language called Spin, or in native cog assembly. Guess which one I'm using... Each cog also has a video generator, which leads to some interesting possibilities. The concept I'm working on is to use 240 entries of cog RAM as line RAM which gets written out in a very tight loop. Then once the line is displayed, the cog fetches sprite graphics for the next line while another cog is busy displaying the current line. The big advantage is each pixel is stored as a long and has the capability of covering the entire NTSC color gamut. The downside is I'm discovering how few sprites the system can actually display. The last straw was clearing the line RAM: LineRAM EQU $100 D1 LONG 0000_0000_0000_000000001_000000000 Black LONG $01010101 * 7.5IRE MOV count1, #240 MOVD ZeroLR, #LineRAM ZeroLR MOV LineRAM, Black ADD ZeroLR, D1 DJNZ count1, #ZeroLR This simple bit of code chews up 2892 cycles, or over half of the time per line. Ugh! The solution is obvious - use 3 cogs for video. That doubles the number of cycles available for the write Line RAM routines. I'm hoping is also will even out the overall output timing. The plan is for the output routine to finish after writing a set of synch pulse pixels. This should set the output bits to 0 so it won't interfere with the output of active cog. But I'm guessing the video generator is still running, even though the cog isn't feeding it any new pixel data. Which means when the code goes back to writing, it's going to resynch back to the video generator clock. So because the pixel clock is 4.77MHz, that means there will be 303 pixels per line, which is 1/3 of a pixel short versus the spec. (Not a huge crime, but it's better to be in spec if possible.) But since I'm using 3 cogs for video, then I can accumulate that extra 1/3 pixel across the 3 lines sequence. So the cog generates 303 pixels of output, and then spends 607 pixels of time generating the next line of output. And we're back in spec. I'm also hoping I can figure out how to synch the 3 cogs together so they are all starting together. Then I can use the round-robin access delay to start each cog 1/3 pixel from each other.
  8. "Up" is also an album by Great Big Sea. (Although I prefer their first album.)
  9. Okay, I've gotten my head wrapped around the counters. Given a reasonably accurate system clock crystal, it should be possible to generate that 14.31818MHz clock. I'm still not clear on what VCFG is doing under the covers, (I think I saw something stating it's better covered in the Hydra manuals.) but I can relax on the whole clocking issue. The following code is the sprite->LineRAM routine using a color lookup table store in cog RAM (not shown): ' Sprite Table format addr[16]:xpos[8]:ypos[8] (all 0 for unused) ' Sprites are 8x8 pixels (1 byte/pixel) stored in raster order ' pixel 0 is transparent, all others are color index ' xpos MUST be limitted to 0-232 - no wrap around or scrolling! ' vertical scrolling is possible (i.e. ypos=255 will scroll in from top, ypos=233 will scroll off bottom) sprtbl LONG $xxxx ' address of sprite table in main memory TBLSIZE EQU $xx ' number of entries in sprite table MAXSPR EQU $xx curYpos RES 1 ' current row (0=first active row) counter RES 1 ' multipurpose counter count2 RES 1 ' maximum number of active sprites sprptr RES 1 ' pointer to sprite table entry (in main memory) sprdata RES 1 ' sprite table entry / pointer to lineRAM (xPos) sprtemp RES 1 ' Ypos spraddr RES 1 ' pointer to sprite graphics (main memory) sprbyte RES 1 ' current pixel sprgfx0 EQU sprtemp ' left 4 pixels (LSByte = leftmost) sprgfx1 RES spraddr ' right 4 pixels (MSByte = rightmost) MOV counter, #TBLSIZE ' number of entries in sprite table MOV count2, #MAXSPR ' maximum number of active sprites MOV sprptr, sprtbl sprloop RDLONG sprdata, sprptr wz ' 7 get sprite table entry IF_Z JMP #:nxtspr ' 11 zero entry, go to next sprite MOV sprtemp, sprdata ' 15 format addr[16]:xpos[8]:ypos[8] AND sprtemp, #$0FF ' 19 mask off ypos SUB sprtemp, curYpos ' 23 relative to current row AND sprtemp, #$1F8 wz,nr ' 27 check for outside 0-7 IF_NZ JMP #:nxtspr ' 31 outside range, go to next sprite MOV spraddr, sprdata ' 35 calculate sprite address SHR spraddr, #16 ' 39 base address for top left SHL sprtemp, #3 ' 33 8 bytes per row ADD spraddr, sprtemp ' 47 RDLONG sprgfx0, spraddr ' 48->7 ADD spraddr, #4 ' 11 SHR sprdata, #8 ' 15 shift xpos to lsb RDLONG sprgfx1, spraddr ' 16->7 AND sprdata, #$0FF ' 11 mask off xpos OR sprdata, #$100 ' 15 add LineRAM base address MOV sprbyte, sprgfx0 ' handle each byte (LSB first!) AND sprbyte, #$0FF wz ' $00 is transparent MOVS :byte0, sprbyte ' set source MOVD :byte0, sprdata ' set destination :byte0 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx0, #8 MOV sprbyte, sprgfx0 AND sprbyte, #$0FF wz MOVS :byte1, sprbyte MOVD :byte1, sprdata :byte1 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx0, #8 MOV sprbyte, sprgfx0 AND sprbyte, #$0FF wz MOVS :byte2, sprbyte MOVD :byte2, sprdata :byte2 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx0, #8 wz MOVS :byte3, sprgfx0 MOVD :byte3, sprdata :byte3 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 MOV sprbyte, sprgfx1 AND sprbyte, #$0FF wz MOVS :byte4, sprbyte MOVD :byte4, sprdata :byte4 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx1, #8 MOV sprbyte, sprgfx1 AND sprbyte, #$0FF wz MOVS :byte5, sprbyte MOVD :byte5, sprdata :byte5 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx1, #8 MOV sprbyte, sprgfx1 AND sprbyte, #$0FF wz MOVS :byte6, sprbyte MOVD :byte6, sprdata :byte6 IF_NZ MOV sprdata, sprbyte ADD sprdata, #1 SHR sprgfx1, #8 wz MOVS :byte7, sprgfx1 MOVD :byte7, sprdata :byte7 IF_NZ MOV sprdata, sprbyte DJNZ count2, #:nxtspr JMP #:exit :nxtspr ADD sprptr, #4 DJNZ counter, #sprloop ' 48+16+219 = 287 (288) max cycles / sprite :exit ORG $100 LineRAM RES 240 ' bottom half of cog RAM If we assume the standard 80MHz system clock, then the input routine has 5084 cycles to populate the LineRAM. At 288 cyles/sprite, that's ~17 sprites per line. Better, but not hugely impressive. One item to note is it takes 35 cycles (effectively 48 due to hub delays) to handle a sprite not on the current line. Crunching the numbers, this means the routine could handle a 64 entry sprite table with 8 active sprites per line (i.e. NES equivalent). Smaller sprite tables mean more active sprites (i.e. a 32 entry table could handle 14 active sprites). Hmm.. just checked. This routine will take up 84 longs of cog RAM. And each long of code is one less entry in the color lookup table. (Yeah, you could use some of the code longs as pixel values, but I suspect there won't be many which will actually have the desired Y+U,Y+V,Y-U,Y-V property.)
  10. My vision is to have two cogs generating video, trading off during the sync pulse (which sets all outputs to 0). While the cog is generating output, it's doing little else. (Well, maybe some minor initialization.) I've done up the lookup table option and it still chews up far more cycles than I'd expect. I'm not sure that more bits per pixel in main RAM would help things, given the cost of doing RDLONGs. The Propeller ISA is part of the problem. It's really tuned for 32 bit register to register operations. So the lookup code turns into: MOV sprbyte, sprdata AND sprbyte, #$0FF MOVS :byte0, sprbyte MOVD :byte0, sprXpos :byte0 MOV sprXpos, sprbyte ADD sprXpos, #1 SHR sprdata, #8 7 instructions = 28 cycles per pixel. Three ops to extract a byte from a word, and three more ops for the indirect read/write. Hmm... only one cog for sound... I wonder whether how tough it would be to stick a simple tune player into the VSYNC routines for the video cog. That would give you 2 channel music for free. Read a frequency and counter from main memory and update the B oscillator every frame. Oh, which reminds me. One think thing I'm fighting with is clock generation. As I specified previously, the sub pixel clock is 14,318,182 Hz (4*colorburst), and the CPU clock has to be at least 62MHz (preferably higher for the sprite section). The question is whether it's possible to meet both objectives since 16*colorburst is only 57MHz, so you can't just strap a colorburst crystal to Xin/Xout. 4.77MHz (4/3 colorburst) would be fast enough, but I don't know whether those exist. (I know 14.31818MHz exists, I've used them.) And how feasible is it to generate the 14.31818MHz output clock from 4.77MHz?
  11. I love/hate when I get caught into an "ooh, shiney" moment. I know I should be focusing my attention on other things, but I can't resist playing with something new. Anyway, I've coded up 90+% of the sprite routine: ORG $000 LineRAM RES 256 sprtabl LONG $xxxx ' address of sprite table in main memory sprptr RES 1 ' pointer to sprite table (main memory) sprdata RES 1 ' sprite table entry / pointer to lineRAM (xPos) sprtemp RES 1 ' Ypos, temp for CLUT sprbyte RES 1 ' current pixel sprgfx0 RES 1 ' right 4 pixels sprgfx1 RES 1 ' left 4 pixels spraddr EQU sprgfx1 ' pointer to sprite graphics (main memory) counter RES 1 ' counter MOV counter, # MOV sprptr, sprtable :dospr RDLONG sprdata, sprptr wz ' 0 get sprite table entry IF_Z JMP #:nxtspr ' 7 zero entry, go to next sprite MOV sprtemp, sprdata ' 11 format addr[16]:xpos[8]:temp[8] AND sprtemp, #$0FF ' 15 mask off temp SUB sprtemp, curtemp ' 19 relative to current row AND sprtemp, #$1F8 wz,nr ' 23 check for outside 0-7 IF_Z JMP #:nxtspr ' 27 outside range, go to next sprite MOV spraddr, sprdata ' 31 calculate sprite address SHR spraddr, #16 ' 35 base address for top left SHL sprtemp, #3 ' 39 8 bytes per row ADD spraddr, sprtemp ' 43 RDLONG sprgfx0, spraddr ' 47->48 ADD spraddr, #4 ' 7 SHR sprdata, #8 ' 11 shift xpos to lsb RDLONG sprgfx1, spraddr ' 15->16 AND sprdata, #$0FF ' 7 mask off xpos MOV sprbyte, sprgfx0 ' handle each byte (LSB first!) CALL CLUT SHR sprgfx0, #8 MOV sprbyte, sprgfx0 CALL CLUT SHR sprgfx0, #8 MOV sprbyte, sprgfx0 CALL CLUT SHR sprgfx0, #8 MOV sprbyte, sprgfx0 CALL CLUT MOV sprbyte, sprgfx1 CALL CLUT SHR sprgfx1, #8 MOV sprbyte, sprgfx1 CALL CLUT SHR sprgfx1, #8 MOV sprbyte, sprgfx1 CALL CLUT SHR sprgfx1, #8 MOV sprbyte, sprgfx1 CALL CLUT :nxtspr ADD sprptr, #4 DJNZ counter, #:dospr ' 48+16+107+92*8 = 907 (912) max cycles / sprite CLUT AND sprbyte, #$0FF wz ' 4 IF_Z JMP #:next ' 8 $00 is transparent AND sprbyte, #$1F0 wz,nr ' 12 IF_Z JMP #:color ' 16 $01-$0F greyscale ADD sprbyte, #Greys-1 MOVS :grey, sprbyte :grey MOV sprbyte, Greys JMP #:wrbyte :color MOV sprtemp, sprbyte ' 20 $10-$1F color AND sprbyte, #$00F ' 24 format %lllscccc ADD sprbyte, #Colors ' 28 cccc is color index MOVS :clut, sprbyte ' 32 s is saturation :clut MOV sprbyte, Colors ' 36 llls is luma SHR sprtemp, #4 ' 40 AND sprtemp, #$001 wz,nr ' 44 IF_Z SHR sprbyte, #1 ' 48 %xxx0cccc = less color ADD sprbyte, sprtemp ' 52 add luma to each subpixel SHL sprtemp, #8 ' 56 ADD sprbyte, sprtemp ' 60 SHL sprtemp, #8 ' 64 ADD sprbyte, sprtemp ' 68 SHL sprtemp, #8 ' 72 ADD sprbyte, sprtemp ' 76 :wrbyte MOVD :write, sprdata ' 80 write pixel to [xpos] :write MOV LineRAM, sprbyte ' 84 :next ADD sprdata, #1 ' 88 next xpos CLUT_ret RET ' 92 cycles (max) Blank LONG $08080808 ' 0 IRE Sync LONG $00000000 ' -40 IRE Burst LONG $000C0004 ' 0/20/0/-20 IRE Greys LONG $09090909 ' 5 IRE (black) LONG $0B0B0B0B ' 15 IRE LONG $0C0C0C0C ' 20 IRE LONG $0D0D0D0D ' 25 IRE LONG $0F0F0F0F ' 35 IRE LONG $10101010 ' 40 IRE LONG $11111111 ' 45 IRE LONG $13131313 ' 55 IRE LONG $14141414 ' 60 IRE LONG $15151515 ' 65 IRE LONG $17171717 ' 75 IRE LONG $18181818 ' 80 IRE LONG $19191919 ' 85 IRE LONG $1B1B1B1B ' 95 IRE LONG $1C1C1C1C ' 100 IRE (white) Colors The big, BIG problem is the routine requires close to 1000 cycles per sprite. Even at 80MHz, that's only 5 sprites per line. (More like 4 active sprites plus N sprites not on the current line.) Ugh. Not good. The big cycle waster is the CLUT routine which needs almost 100 cycles per pixel to translate each byte to a long. Although some savings might be achieved by adding a luma lookup table to the color branch, that would still leave around 50 cycles per pixel which wouldn't do more than double the number of sprites. Which leads me back to the pure lookup table option, not my preferred choice (although it does mean the game could have a custom palette). The palette would be smaller since it would be limitted to the space not used by the code & line RAM.
  12. More thinky stuff: One cycle chewer is going to be the byte->long color translation. Something about only 512 longs of cog RAM to squeeze the 256 byte line RAM not leaving much space for a 256 byte CLUT :-) I had thought about how best to do a background. NES style tiles are relatively storage efficient, but need multiple RDLONGs. A simple static background would only need 32 RDLONGs per line, but would require 64K of main RAM for the 256x256 pixelmap. So for now it's foreground sprites only. Okay, back to the CLUTs. There's two ways of doing it. One is to store the bytes in the line RAM and do the translation later. Second is to translate the bytes before storing them to line RAM. I was leaning to the former, but I just realized that since there's no background, that 90% of the screen will need to have the long=black code. So any savings realized by not translating overlapping sprites will be lost to translating the black background (while initializing the background to the fixed value is no cost since it has to be done anyway). Each byte has three possible codings: $00 is transparent $01-$0F is greyscale (15 values - black to white) $10-$FF is color, with the first octet being saturation/value & the second a color index Output would be 5 bits: 80IRE, 40IRE, 20IRE, 10IRE and 5IRE although this may be the middle bits of the output so scaling doesn't overflow between subpixels.
  13. I've been doing some thinking, so now it's time to write it down. For the output logic, the system needs to be running at 62MHz or better (preferably some multiple of 4*colorburst). That gives 13 CPU cycles per pixel (or 2 normal instructions + WAITVID). That should be enough to handle the output logic. That also gives 3943 CPU cycles per line for the input logic (or max 246 hub accesses per line) Okay, then we need the input logic. I did think some about display lists, but I ran into two issues. First is because there are two cogs running the display code, one doing the odd lines and one doing the even lines, handling the # of lines per zone gets tricky. The second issue is I'm not sure the added complexity of having separate display lists buys you anything. Consider instead a basic sprite table in main RAM. Each entry would be a single 32-bit long containing a 16 bit address pointer to the sprite graphics and two bytes for horizontal and vertical position. Each sprite would be a fixed size (i.e. 8x8) and the graphics would include transparency. A zero entry would indicate the entry is unused and the code could skip to the next entry. So the code kinda looks like: .1 RDLONG sprdata, sprptr wz ADD sprdata, #4 IF_Z JMP #.1 Okay, then the code needs to figure out whether the sprite is on the current line. MOV sprYoff, sprdata AND sprYoff, #$0FF SUB sprYoff, curYpos AND sprYoff, #$1F8 wz,nr IF_NZ JMP #.1 Then it's just a matter of translating the address+Yoffset into RDLONGs, and then translating those bytes read into line RAM longs. MOV sprtemp, sprdata SHR sprtemp, #16 SHL sprYoff, #3 ADD sprYoff, sprtemp RDLONG sprtemp, sprYoff ADD sprYoff, #4 RDLONG sprYoff, sprYoff Each 8 pixel wide sprite will therefore need 3 RDLONGs or a max of 82 sprites @ 62MHz (probably less than 64 since it will take more than 2 instructions to decode the words into bytes.
  14. EricBall

    Digitize

    Keep the CDs. They're proof of "ownership" and an uncompressed source for future rips. For cars the mini FM transmitters work fairly well, although I'd recommend buying one which allows you to select any FM frequency. (Even then, it can be tough to find a usable station.) If you have an iPod, then I'd recommend using iTunes to handle the rip & organize.
  15. Hmm.. tough questions, especially since I don't have any way to scope an actual system. As per the 7800 Schematics it looks like the RAM CS is directly connected to MARIA. OE is tied low, while WE is the R/W and CLK1 outputs from the 6502 OR'd together. Since during DMA, MARIA asserts the 6502's RDY line, then I don't see any reason that CLK2 couldn't be free running during DMA. Of course, it should be possible to determine it from a software perspective. Simply set up a test wrapper around my ball demo which sets the timer for a value which will expire during a normal frame. Then see if the timer doesn't expire when DMA gets heavy.
  16. Start of the output code... d4 LONG #0000 0000 0000 000 000 100 000 000 000 pixcnt LONG #$00000000 LINERAM RES 256 MOV pixcnt, #240/4 MOVD pixel0, #LINERAM MOVD pixel1, #LINERAM+1 MOVD pixel2, #LINERAM+2 MOVD pixel3, #LINERAM+3 pixel0 WAITVID LINERAM,#%011100100 ADD pixel0, d4 pixel1 WAITVID LINERAM+1,#%010010011 ADD pixel1, d4 pixel2 WAITVID LINERAM+2,#1001110 ADD pixel2, d4 pixel3 WAITVID LINERAM+3,#0111001 ADD pixel3, d4 DJNZ pixcnt, #pixel0 I'll see if I can do some display list pseudo code.
  17. Ahh, so it's like the 8051, which I always thought of as having zero page RAM instead of registers. I was just basing my code on the sample you said, trying to show how to turn four [Y+U,Y+V,Y-U,Y-V] 14.31818Mhz samples into a 4.77Mhz pixel. Hmm... I wonder if you could set up two cogs with the same code. The code would have two phases: phase 1 would read the display list & sprite data from main memory and save the result to line RAM in cog memory. Second phase would bash that line RAM out to waitvid (along with generating sync). And although I said you'd only be able to generate 4 colors, rethinking this I'm fairly certain that you'd be able to generate the entire NTSC color gamut. I was thinking that you'd need more samples to generate an accurate color phase signal, but the TV is really just going to run the signal through a bandpass filter then two de-modulators to extract the U & V. And since you control the U & V exactly, it should be possible to generate any color.
  18. Yeah, I've been looking at the docs. Definitely interesting. You could easily do 3.58MHz (160 res) graphics with 4 colors (phase 0,90,180,270) + B&W and a huge number of shades via a single cog output driver. You might even be able to do 4.77MHz (240 res) graphics on a single cog. set VCFG so CMode = 1 (2 bbp) set VSCL so pixel clock = 14.31818MHz (4 * color burst) & frame length = 3 mov r1, #60 '240 pixels horizontal resolution :draw_pixels rdlong B, A 'get pixel (4 samples) from hub waitvid B, #%%3210 'draw them to screen add A, #4 'point to next pixel group rdlong B, A 'get pixel (4 samples) from hub waitvid B, #%%2103 'draw them to screen add A, #4 'point to next pixel group rdlong B, A 'get pixel (4 samples) from hub waitvid B, #%%1032 'draw them to screen add A, #4 'point to next pixel group rdlong B, A 'get pixel (4 samples) from hub waitvid B, #%%0321 'draw them to screen add A, #4 'point to next pixel group djnz r1, #:draw_pixels 'line done? Move to sync...
  19. Ahh, now I understand the video generation a little better. There's no separate chroma signal, it's just generating a signal with a bandwidth greater than 3.58MHz. How fast does the rdlong/waitvid loop run? (i.e. 4 pixels in x cycles at y MHz) (Or how many bytes per line?) Yep, the A7800 significantly decreases the typical sprite table issue of determining which sprites are on the line. One other advantage of the display list is the display list read cog could translate a single sprite byte into multiple line RAM bytes which the output COG would then read. This would simplify color translation. There's also the opportunity to add transparency.
  20. True, double buffering the DLL/DLs would avoid this issue, but at a significant cost in terms of RAM/display list length and display list builder code complexity / size. I was more thinking of something based on a DLI routine which would flag which display list MARIA is reading at any one time. Of course, the other alternative is to avoid updating the display lists during active video.
  21. The RIOT/TIA/CPU clock is generated by MARIA and is decoupled from the 7.16MHz clock. RAM/ROM don't have clock lines, MARIA just waits a fixed number of 7.16MHz (140ns) clock cycles after putting the address on the bus before latching the data.
  22. Interesting. How much contol do you have over the color amplitude? The main problem with the Atari colors, versus, the NES, was the Atari only had a single amplitude which was used for both burst and active video. This made the colors relatively dark. I think the NES also clicked up the base luma when not in greyscale. Would the Propeller be capable of A7800 style display list processing? Have two COGs working as the GPU, one reading the display list and writing to a line RAM buffer, the other reading from a second line RAM buffer kicking out the video. An A7800 display list goes like this: a register points to a series of display list list entries. Each DLL entry has a pointer to the display list and a byte with some flags and the number of lines the display list is used for. The display list is made up of a series of display list entries. Each entry has a pointer to the sprite data or a tile list, the number of bytes in the sprite or the tile list, and a horizontal position.
  23. Maybe. It depends on whether Kateteka has some kind of frame action loop (i.e. frame 1 create display list, frame 2 handle user input, frame 3 handle enemy AI . . .) which can be optimized to drop one of the frames from the sequence.
  24. Check the Stella archives. I attempted without success to create CC using the 2600. The big problem I ran into was lack of any way to validate the output other than through the CC decoder in my TV. So I might have been creating a valid signal, just on the wrong line. http://www.biglist.com/lists/stella/archiv...1/msg00081.html However, IIRC, the TIA isn't really able to generate a valid CC signal because some of the CC waveform (especially the initial timing pulses) lies outside the active portion of the line.
  25. EricBall

    Adios, Netflix

    I have a TiVo with a 300GB drive (100 hours at highest quality). There's movies on there which were recorded months ago. Heck, I'm two episodes behind on CSI & CSI:Miami. Which indicates to me that I don't have enough time to be adding more TV watching by subscribing to Netflix. If I'm really desperate, and can't find anything worth watching in my DVD collection (especially the ones still wrapped in plastic), the convenince store right around the corner rents DVDs. And to top it all off, the cableco recently added AMC & TCM to the list of channels we get. (Doubling the number of pages dedicated to movie listings in the local paper's weekly TV Guide.) Of course, my wife still wants a Netflix subscription for some reason.
×
×
  • Create New...