Heaven/TQA Posted January 15, 2004 Share Posted January 15, 2004 finally i have realised how this mode works... unfortunatly MARIA description & programming docs aren't so large as I wish. thanks to Dan's vertical sprite movement example (without any comments... ) i figured out how this works... most of you know that the 7800 architecture is different to 2600,5200, Lynx and 800... and is more like on older arcade games... and works with "zones" & object lists for scanlines... quote from the atari 7800 dev guide: "The group of rasters specified by one DLL entry is called a "zone." Again, the number of rasters in a zone equals OFFSET+1. Larger zones mean less RAM is needed for DLLs, Display Lists and Character Maps (see DMA MODES below). But upon consideration of how to use zones, you will realize that to achieve smooth vertical motion each stamp must be padded at top and bottom with zeros. For example, if the top raster of an object is to appear on the last line of a 16 high zone, it must have 15 lines of zeros above it. If that object is 8 pixels (2 bytes) wide, and its top line of data is located at x'CF04', then you will need two bytes of zeros at x'D004', x'D104', x'D304',..., and x'DE04' (remember that OFFSET decrements). As this can add up to many pages of zeros, you can specify that MARIA should interpret certain data as zeros, even if it isn't. This is called "Holey DMA" because DMA will see "holes" in the data that aren't really there. This can be enabled and disabled on a zone by zone basis via a DLL entry. Holey DMA has been aimed at 8 or 16 raster zones, but will have the same effect for other zone sizes. MARIA can be told to interpret odd 4K blocks as zero, for 16 high zones, or odd 2K blocks as zeros for 8 high zones. This will only work for addresses above x '8000'. This means that these blocks can hold meaningful code, or tables, or graphics data used in a zone where Holey DMA is not on." so... my 1st mistake was... i mixed up "odd" with "even"... which wasn't good... then i went through Dan's vertical sprite demo and tried to understand how vertical sprite posititioning works on 7800 in detail. the basics are clear... but the holey DMA issue drove me crazy... so... assuming you have build up the screen with zones covering each 16 scanlines. your sprite is f.e. 16x16 pixel... remember that gfx data has to be layed out in ram with 256 bytes "scanlines"... f.e. the sprite would cover the adress space: $a000-$a003 $a100-$a103 $a200-$a203 $a300-$a303 ... $af00-$af03 (16 pixel are in 160x2 mode, similar to antic e, 4 bytes as each byte holds 4 pixels) for vertcial sprite positioning we have to modify the DLs for the zone(s) the sprite would appear... which means the starting adress of the sprite data... as it is written in the dev document... to avoid a lot of wasting ROM space because of the "0" each sprite would need to be positioned smoothly... MARIA has the holeyDMA feature... assuming holeyDMA16 (for 16 scanline zones) is set in the display list list (DLL) the dev doc says that now every odd 4k block above $8000 will be interpreted by MARIA as 0 even if there is no zero data... ok... what does this mean? now my bad logical brain confused me... for me each 4k block is even, not odd... 4096 is even... but then i found this bit in the dev doc: DLI - Display List Interrupt flag. 0 => No DLI. 1 => Interrupt after DMA on last line of previous zone. H16 - 16 high zone Holey DMA enable. 0 => Not enabled. 1 => Enabled. DMA interprets odd 4K blocks as zeros. (A12 high => data=0) H8 - 8 high zone Holey DMA enable. 0 => Not enabled. 1 => Enabled. DMA interprets odd 2K blocks as zeros. (A11 high => data=0) OFFSET - OFFSET starting value. 4 bits only. DL ADDRESS - Address of Display List for this zone. the interesting part is "A12 high => data=0" in the H16 section... now we have to think "binary". so let us perform a CLD in our brain... A12 means the Bit12 of the sprite data adress (A0-A15) now... let us check: Bit counting from left to right 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 $a000 = %10100000 00000000 (high low) $a100 = %10100001 00000000 $a200 = %10100010 00000000 ... etc... Bit 12 is always 0 = even in MARIA definition so gfx data is being visible on screen. now...for vertical movement we would need data "on top of our sprite at $b000-$bf00 for being possible to set the sprite on scanline basis... so... let us write $b000 etc... in binary mode $b000 = %10110000 00000000 $b100 = %10110001 00000000 $b200 = %10110010 00000000 ... and voila... Bit 12 is set for the whole range $b000 - $bfff ergo is this ROM space "odd" for Maria when holeyDMA16 is enabled... so data lying here will not be interpreted as sprite data but instead as "zero" = 0 so... now your code has just to calculate on which zone(s) your sprite appears and has to modify the DL entries including the sprite adress pointer... but this is not more complicated then it looks...check out dan's sprite demo... it's still not so comfortable like on "real hardware sprite" systems... where you just need to alter x,y hardware adresses but with this method is very similar as you move the sprites by altering the "high byte" of your sprite pointer... and this is similar to the above system...you have just to add the starting adress of your sprite data to the y-position... and voila... MARIA designes had really fast gfx in mind... as the chip seems designed for speed (and having the 6502 in mind as well...) all counters count downwards, gfx data has to be stored "top-down", gfx data has to be stored with "256 bytes" long scanlines in mind... all neat tricks by hardware which we demo coder would use in our own productions... i hope i could explain a little bit to the newbies... Quote Link to comment Share on other sites More sharing options...
EricBall Posted January 15, 2004 Share Posted January 15, 2004 On the 7800 the screen is broken up into "zones" of 1-16 scanlines (typically 8 or 16), based on the 3 byte DLL header. The DLL header contains a 16 bit address pointer to the display list for the zone. The display list is made up of a sequence of 4 or 5 byte sprite headers ended by a 2 byte null header. Each direct sprite header contains a 16 bit address pointer to the graphics data drawn on the last scanline of the zone. (Indirect sprites, or tiles, are a little different.) Graphics data is laid out "upside down" with the last scanline on the lowest address and each scanline on a separate page. e.g. for a 2 byte x 16 line sprite $e000-$e001 bottom line $e100-$e101 2nd last line ... $ee00-$ee01 2nd line $ef00-$ef01 top line Horizontal motion on the 7800 is easy 'cause each sprite header contains a 1 byte horizontal position (though this means only 160 onscreen positions even in 320 modes). Vertical motion requires a little more work. Assume we are using 16 line sprites and zones. If the sprite is "on grid" then we have the following line 0-15 DLL -> sprite header -> $e000 Now say that the sprite moves down one scanline, then the sprite is overlaps two zones and we need the following line 0-15 DLL -> sprite header -> $e100 line 16-31 DLL -> sprite header -> $d100 Some of this seems counter-intuitive, but remember that the sprite header points to the bottom of the sprite. So the top scanline of the second zone will draw the graphics stored at $d100 + 15*256 = $e000 or the last scanline of the sprite. So the sprite has moved down one scanline. This is also where "Holey DMA" comes into play. In the above example the top scanline of the first zone will draw the graphics stored at $e100 + 15*256 = $f000. In the DLL there are two flags, one which treats odd 4K segment of ROM as full of zeros. So when that flag is set, graphics reads from $dxxx and $fxxx will be treated as zeros. Thus we can store code and non-graphics data in those segments. Now that we know how to handle vertical motion, the next challenge is building that silly display list. (See the mega sprite demo I posted to the Atari 7800 Programming mailing list.) Quote Link to comment Share on other sites More sharing options...
DanBoris Posted January 15, 2004 Share Posted January 15, 2004 it's still not so comfortable like on "real hardware sprite" systems... where you just need to alter x,y hardware adresses but with this method is very similar as you move the sprites by altering the "high byte" of your sprite pointer... and this is similar to the above system...you have just to add the starting adress of your sprite data to the y-position... and voila... The nice thing about the 7800 hardware is that you can simulate a "real hardware sprite system", or any other type of graphics hardware you like. You would create a display engine that reads a table of sprite X,Y positions and generate the DL's from this table. Once this is done, you game logic only has to deal with the sprite table and not directly with the display lists. This also gives you the flexibility to design different display engines for different games. You might have an engine for just doing sprites, an engine for a tiled background with sprites, an engine for a side scrolling background, etc. Dan Quote Link to comment Share on other sites More sharing options...
DEBRO Posted January 15, 2004 Share Posted January 15, 2004 This is the type of thing I'd like to see on the mailing list. Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted January 15, 2004 Author Share Posted January 15, 2004 i would be very interested in the sprite demo you have mentioned... is the 7800 discussion list archived? Quote Link to comment Share on other sites More sharing options...
+Mitch Posted January 16, 2004 Share Posted January 16, 2004 i would be very interested in the sprite demo you have mentioned... is the 7800 discussion list archived? The 7800 list archive is here. Mitch Quote Link to comment Share on other sites More sharing options...
DEBRO Posted January 16, 2004 Share Posted January 16, 2004 Thanks Mitch. Apparently they don't archive attachments though Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted January 16, 2004 Author Share Posted January 16, 2004 just for comparison attachted the source code of my playstation1 intro... it's pure R3000 assembler... huj... it's from 1999... long time ago... ; basic psx-routines by Silpheed of HITMEN ; Heaven/Taquart 1st intro on psx!!! ; ; start: several weeks ago... ; end : 05th jun 1999 ; ; still playing around with 256 color-images... ; ; greetinx to all at napalm message-board ; and of course to all members of Taquart !!! ; - 06/05 dolphin sprite rendered ; lets try to include it in demo... ; yeah... i got it... ; - 06/05 try to fade the logo in... ; yeah... works... ; - 06/05 now moving dolphin-head works, too ; - 06/05 added some gouraud-lines moving around ; - 06/06 after going out night i have new ideas to improve intro ; i will add a lensflare moving behind the logo... org $80010000 li sp, $801fff00 li k1, $1f800000 ; set to hardware base li a0, $08000009 ; a0 = display-mode ; 8 = pal jal InitGPU ; initialise the GPU nop la a0, image ; transfer image data to VRAM li a1, 320 ; 320 position in vram li a2, $8000a0 ; image-size y,x/2 li a3, 10240 ; (x/2)*y div 2 jal MEM2VRAM_IO nop la a0, clut ; transfer clut data to VRAM li a1, $1000140 li a2, $10100 li a3, 128 jal MEM2VRAM_IO nop nop la a0, dolphin ; transfer dolphin to vram li a1, 512 ; at (320,256) li a2, $640028 ; size 80x100 li a3, 2000 jal MEM2VRAM_IO nop la a0, clut2 li a1, $0000300 li a2, $10100 li a3, 128 jal MEM2VRAM_IO nop ;exit nop ; j exit ; nop jal InitPads ; init pads, also the wait vsync routine nop la a0, module jal HM_Init ; init the mod player nop part1 ; fade logo in... li s0,$64000000 li s1,$00111111 li s3, 0 part1_loop0 li s2, 0 part1_loop jal HM_Poll ; call mod player nop jal WaitIdle ; wait for GPU to finish processing nop jal WaitVSync ; wait for vertical retrace period nop la a0, list jal SendList ; send display list to GPU nop addiu s2,1 slt t0, s2, 2 ; wait for 2 frames before continuing bnez t0, part1_loop nop addu s3,1 ;crash j crash ; nop addu s0, s1,s0 sw s0, fade1 sw s0, fade2 slt t0, s3, 15 bnez t0, part1_loop0 nop ;crash j crash ; nop part2 li s0,$009cffc0 ; move dolphin li s3,0 part2_loop jal HM_Poll ; call mod player nop jal WaitIdle ; wait for GPU to finish processing nop jal WaitVSync ; wait for vertical retrace period nop la a0, list jal SendList ; send display list to GPU nop sh s0, dolphin_pos addu s0,1 addu s3, 1 slt t0, s3, 80 bnez t0, part2_loop nop ; Main parts of the intro: li s1, 0 li s3,0 li s4,0 part3 ; draw the thetraeder... ; verry basic...;) ; there are 4 primitives, 3 sides and one top-one to "close" the thetraeder ; lineposnx means n=primitive nr; x which vertice of the triangle ;set all 4 primitives on the sin-tables to make nice moving... la s0, SinTab1 addu s0,s1 addu s1,2 and s1,$000000ff lb s2, (s0) sb s2, linepos11 sb s2, linepos41 sb s2, linepos32 sb s2, line_color31+2 sb s2, line_color22+1 lb s2, (s0) lb s2, 64(s0) sb s2, linepos12 sb s2, linepos43 sb s2, linepos21 sb s2, line_color21+1 sb s2, line_color11 lb s2, 128(s0) sb s2, linepos22 sb s2, linepos42 sb s2, linepos31 sb s2, line_color32+2 sb s2, line_color12 ;now move them a little bit vertical ;and set the vertice colors... la s0, SinTab2 addu s0,s1 lb s2, (s0) sb s2, linepos11+2 sb s2, linepos22+2 sb s2, linepos32+2 sb s2, linepos41+2 lb s2, 64(s0) sb s2, linepos12+2 sb s2, linepos43+2 sb s2, linepos21+2 lb s2, 128(s0) addu s2, 48 sb s2, linepos31+2 sb s2, linepos42+2 jal HM_Poll ; call mod player nop skipupdate jal WaitIdle nop jal WaitVSync nop la a0, list jal SendList nop j part3 ; loop forever nop include silph.inc ; some useful routines align 4 image incbin logo31.raw ; the raw image data for the logo and chars clut incbin logo31.clt ; clut info for above align 4 dolphin incbin dolphin.raw ; 80x100x256 head of dolphin clut2 incbin dolphin.clt ; clutinfo for dolphin align 4 list include hvelist3.inc ; the display list align 4 module incbin thesong.hit align 4 include hitmod.inc align 4 include sintab.inc and here is the interesting part... the "Object list" for the grafix processor of the PSone... prim291 ; SPRT db prim292, prim292>>8, prim292>>16, $4 fade1 dw $64000000 lpos1 dw $00000004 dw $40140000 dw $800100 prim292 ; DR_TPAGE db prim293, prim293>>8, prim293>>16, $1 dw $E1000086 prim293 ; SPRT db prim294, prim294>>8, prim294>>16, $4 fade2 dw $64000000 lpos2 dw $00000104 dw $40140080 dw $800040 prim294 ; dr_tpage db prim295, prim295>>8, prim295>>16, $1 dw $e1000088 prim295 ; dolphin ; db $ff,$ff,$ff, $4 db prim100, prim100>>8, prim100>>16, $4 dw $64aaaaaa dolphin_pos dw $009cffb0 dw $00300000 ; clut at $00003000 dw $640050 prim100 ; gouraud triangle db prim101, prim101>>8, prim101>>16, $6 line_color11 dw $30000080 linepos11 dw $00800080 dw $00ffffff dw $00f000c0 line_color12 dw $00000080 linepos12 dw $00800080 prim101 ; gouraud triangle db prim102, prim102>>8, prim102>>16, $6 line_color21 dw $30000000 linepos21 dw $00800080 dw $00ffffff dw $00f000c0 line_color22 dw $00000000 linepos22 dw $00800080 prim102 ; gouraud triangle db prim103, prim103>>8, prim103>>16, $6 line_color31 dw $30800000 linepos31 dw $00800080 dw $00ffffff dw $00f000c0 line_color32 dw $00800000 linepos32 dw $00800080 prim103 ; gouraud triangle db $ff, $ff, $ff, $6 line_color41 dw $30115011 linepos41 dw $00800080 dw $00ffffff linepos43 dw $00f000c0 line_color42 dw $00ffffff linepos42 dw $00800080 prim999 ; BLOCK FILL db $ff, $ff, $ff, $3 dw $02634522 dw $0 dw $F0140 ; End of display list and you see it's the main concept as MARIA chip has... and it's even called display list... ok...you have more possibilities but basicly it's the same... but each object in the list can have every postion on the screen... sorry...don't know why i have posted that... Quote Link to comment Share on other sites More sharing options...
conda Posted April 19, 2005 Share Posted April 19, 2005 This is also where "Holey DMA" comes into play. In the above example the top scanline of the first zone will draw the graphics stored at $e100 + 15*256 = $f000. In the DLL there are two flags, one which treats odd 4K segment of ROM as full of zeros. So when that flag is set, graphics reads from $dxxx and $fxxx will be treated as zeros. Thus we can store code and non-graphics data in those segments. Wow, I've been trying to understand Holey DMA and almost gave up. This post cleared it right up. Thanks for this. Damn, it's really simple. Quote Link to comment Share on other sites More sharing options...
Bruce Tomlin Posted April 20, 2005 Share Posted April 20, 2005 I dunno, I understood it right away, and got it right the first time when I actually wrote some code that used it. Basically it just handles going over the top or bottom edge of your sprites for you. Every other zone-sized memory block is a "no-mans land" which the Maria pretends always contains nothing. So you either start or end outside your graphics memory block far enough to show just the scan lines you need. The Maria is a really nice design, if it weren't for stuff like the wierd pixel mappings, the horribly low-res 160-pixel mode, and the cycle-stealing DMA. (And the pathetic 2K SRAM when the 5200 and ColecoVision already had 16K DRAM.) If the 7800 had been released in 1984 and if it had become a success, Atari would probably have had to release an upgraded Maria+ system of some sort just to stay competitive. Heaven/TQA: could you please edit your post to not have all those extra blank lines? There's something wierd about this BB software that it throws a bunch extra blank lines into CODE tags. Horizontal motion on the 7800 is easy 'cause each sprite header contains a 1 byte horizontal position (though this means only 160 onscreen positions even in 320 modes). Vertical motion requires a little more work. A little more work? Not only do you have to decide how many zones your sprite fits into, you have to figure out which zones and then insert into variable-length display lists. Quote Link to comment Share on other sites More sharing options...
conda Posted April 20, 2005 Share Posted April 20, 2005 Maybe you can explain this to me regarding video resolution. Why does the NES have a better resolution than the Atari's? From the Atari docs I've read, they seem to imply that you cannot exceed the 160x192 resolutions. But the NES has a 256x224 resolution--much better. After reading this, I changed my DLL to use 224 lines (14 zones, 16 high), and it worked in the emulator, but I don't have an MMC card for my CC2 yet, so I could not test it on real hardware. How does the NES pull this off where Atari cannot? Quote Link to comment Share on other sites More sharing options...
DEBRO Posted April 20, 2005 Share Posted April 20, 2005 (edited) Maybe you can explain this to me regarding video resolution. Why does the NES have a better resolution than the Atari's? From the Atari docs I've read, they seem to imply that you cannot exceed the 160x192 resolutions. But the NES has a 256x224 resolution--much better. After reading this, I changed my DLL to use 224 lines (14 zones, 16 high), and it worked in the emulator, but I don't have an MMC card for my CC2 yet, so I could not test it on real hardware. How does the NES pull this off where Atari cannot? 840559[/snapback] Atari recommends using 192 scan lines because that would fit with every NTSC TV. IIRC you can fit 200 scan lines inside a modern TV frame without issues. Outside of that the full screen may not show. Also, remember MARIA handles VSYNC for you (unlike STELLA). So the 7800 truly has a vertical resolution of 243 scan lines. Edited April 20, 2005 by DEBRO Quote Link to comment Share on other sites More sharing options...
Bruce Tomlin Posted April 21, 2005 Share Posted April 21, 2005 Atari recommends using 192 scan lines because that would fit with every NTSC TV. IIRC you can fit 200 scan lines inside a modern TV frame without issues. Outside of that the full screen may not show.840605[/snapback] Also, the more lines you show, the less CPU time you get to do computations, because of the DMA cycle stealing. Emulators will generally not show the effect of this. And don't forget the 320 pixel modes. Not a lot of colors (320B gives you a total of seven, and another 320 mode gives you a total of nine, but you can only use three+background at most in any object), and lots more of a DMA hit, but it's got nice square pixels. I wish they had made a 240 pixel mode for Maria. 160 is low enough to be ugly, even with 4 bit pixels (which is what, 13 colors due to the palette mapping?), and 320 is just too hungry. Quote Link to comment Share on other sites More sharing options...
conda Posted April 21, 2005 Share Posted April 21, 2005 And don't forget the 320 pixel modes. Not a lot of colors (320B gives you a total of seven, and another 320 mode gives you a total of nine, but you can only use three+background at most in any object), and lots more of a DMA hit, but it's got nice square pixels. In essance you are saying the 7800 should be able to run in a 320x200 mode with a palette selection of seven or nine colors? Quote Link to comment Share on other sites More sharing options...
EricBall Posted April 27, 2005 Share Posted April 27, 2005 Maybe you can explain this to me regarding video resolution. Why does the NES have a better resolution than the Atari's? From the Atari docs I've read, they seem to imply that you cannot exceed the 160x192 resolutions. But the NES has a 256x224 resolution--much better. A standard NTSC field has 262 lines (312 for PAL), however 9 of those lines are part of the vertical sync and some of the remaining lines are not visible onscreen. There's nothing preventing a 7800 game from outputting 224 lines (or even 240) of graphics data. The horizontal resolution is more of a design decision. The 7800 video signal is driven by a clock which is a even multiple of the colorburst frequency (x1 for 160, x2 for 320), while the NES uses a 1.5 multiplier. More pixels also increase the on-chip line RAM requirements. Quote Link to comment Share on other sites More sharing options...
EricBall Posted April 27, 2005 Share Posted April 27, 2005 In essance you are saying the 7800 should be able to run in a 320x200 mode with a palette selection of seven or nine colors? See http://atari7800.xwiki.com/xwiki/bin/view/Main/GraphicsModes for the nitty-gritty details. 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.