Hi! I think I have found a bug in Christian Bauer's explanation of sprites and $D017. I have found it quite a long time ago, and I hoped I could investigate further to find what the correct explanation is, but there has not been enough time so far. To make it short, try the following program by Andreas Boose: begin 644 sp.prg M`,!XJ7^-#=RM#=RI4XT4`ZG`C14#J1N-$="I8XT2T*D!C1K0K1G0C1G0HC^I M59W``\H0^JD/C?@'J8B-`-"I9HT!T*D`C1#0C1S0J0&-%]"-%=!88,X9T.X1 GT,X1T"3_HC'*T/VI`(T7T*D!C1?0H@G*T/VI`(T7T*D!C1?03#'J ` end Here is the assembly listing: C000 SEI C001 LDA #$7F C003 STA $DC0D C006 LDA $DC0D C009 LDA #$53 C00B STA $0314 C00E LDA #$C0 C010 STA $0315 C013 LDA #$1B C015 STA $D011 C018 LDA #$63 C01A STA $D012 C01D LDA #$01 C01F STA $D01A C022 LDA $D019 C025 STA $D019 C028 LDX #$3F C02A LDA #$55 C02C STA $03C0,X C02F DEX C030 BPL $C02C C032 LDA #$0F C034 STA $07F8 C037 LDA #$88 C039 STA $D000 C03C LDA #$66 C03E STA $D001 C041 LDA #$00 C043 STA $D010 C046 STA $D01C C049 LDA #$01 C04B STA $D017 C04E STA $D015 C051 CLI C052 RTS C053 DEC $D019 C056 INC $D011 C059 DEC $D011 C05C BIT $FF C05E LDX #$31 C060 DEX C061 BNE $C060 C063 LDA #$00 C065 STA $D017 ; first $D017 write C068 LDA #$01 C06A STA $D017 ; second $D017 write C06D LDX #$09 C06F DEX C070 BNE $C06F C072 LDA #$00 C074 STA $D017 ; third $D017 write C077 LDA #$01 C079 STA $D017 ; fourth $D017 write C07C JMP $EA31 Basically, this code activates an y-expanded sprite starting at line $67; then, using an IRQ, it writes $01 to $D017 at cycle 15 and $00 at cycle 21, once at line $69 and once at line $6a. According to the "VIC article", 1. The expansion flip flip is set as long as the bit in MxYE in register $d017 corresponding to the sprite is cleared. (so the flip flop is always 1 if the sprite is not y-expanded) 3. In the first phases of cycle 55 and 56, the VIC checks for every sprite if the corresponding MxE bit in register $d015 is set and the Y coordinate of the sprite (odd registers $d001-$d00f) match the lower 8 bits of RASTER. If this is the case and the DMA for the sprite is still off, the DMA is switched on, MCBASE is cleared, and if the MxYE bit is set the expansion flip flip is reset. (so the flip flop is always 0 on the first line of an y-expanded sprite) I have checked "sp.prg" on my 64C at home. I have figured out which memory locations are displayed in which pixels, and it looks like there is really something wrong with this description. +-----+-----+-----+ | 0 | 1 | 2 | +-----+-----+-----+ | 0 | 1 | 2 | +-----+-----+-----+ | 3 | 4 | 5 | <- First $D017 write +-----+-----+-----+ | 7 | 8 | 9 | <- Third $D017 write +-----+-----+-----+ | 7 | 8 | 9 | +-----+-----+-----+ | 7 | 8 | 9 | +-----+-----+-----+ | 10 | 11 | 12 | +-----+-----+-----+ | 10 | 11 | 12 | +-----+-----+-----+ : : : : Each rectangle represents 8 pixels, and the number represents the offset of the memory location that contains the bitmap for those 8 pixels, relative to the start of the sprite (in this case, $03C0). The $D017 writes are the ones "sp.prg" makes at cycle 15 and 21, after the `DEX' loop. The flip flop before the first write is 0 (because the sprite starts expanded), and writing 0 to the register should (according to the article) set the flip flop to 1. As the write happens at cycle 15, the memory pointer should be incremented by 1 instead of 3 (as explained in 3.14.7). As "sp.prg" also writes 0 into $D017 afterwards, at cycle 54 the flip flop would be inverted (3.8.1, rule 2), so its value would be zero before the third $D017 write, which thus should cause another 1-byte shift in the memory pointer. So the beginning of the map would be like this: +-----+-----+-----+ | 0 | 1 | 2 | +-----+-----+-----+ | 0 | 1 | 2 | +-----+-----+-----+ | 3 | 4 | 5 | <- First $D017 write +-----+-----+-----+ | 4 | 5 | 6 | <- Third $D017 write +-----+-----+-----+ | 5 | 6 | 7 | +-----+-----+-----+ | 5 | 6 | 7 | +-----+-----+-----+ | 8 | 9 | 10 | +-----+-----+-----+ | 11 | 12 | 13 | +-----+-----+-----+ : : : : That's what FrodoSC does, indeed, but it is clearly not correct. VICE does this right instead. This happens because the "Xayne's Birthday Party" disk by Crest contains a routine showing this effect, and even a table of the values that should be added to the sprite memory pointer when this effect is used; I have just copied it and implemented things accordingly. The table looks like the following (grabbed from `src/c64/sprcrunch.h'): static const int sprite_crunch_table[64] = { 1, 4, 3, /* 0 */ 4, 1, 0, /* 3 */ -1, 0, 1, /* 6 */ 4, 3, 4, /* 9 */ 1, 8, 7, /* 12 */ 8, 1, 4, /* 15 */ 3, 4, 1, /* 18 */ 0, -1, 0, /* 21 */ 1, 4, 3, /* 24 */ 4, 1, -8, /* 27 */ -9, -8, 1, /* 30 */ 4, 3, 4, /* 33 */ 1, 0, -1, /* 36 */ 0, 1, 4, /* 39 */ 3, 4, 1, /* 42 */ 8, 7, 8, /* 45 */ 1, 4, 3, /* 48 */ 4, 1, 0, /* 51 */ -1, 0, 1, /* 54 */ 4, 3, 4, /* 57 */ 1, -40, -41, /* 60 */ 0 }; Using this table is quite straightforward: whenever $D017 is written to I do the following (I just include the C source here, as I think it's clearer than words): sprites[i].y_expanded = value & (1 << i) ? 1 : 0; if (!sprites[i].y_expanded && !sprites[i].exp_flag) { /* Sprite crunch! */ if (cycle == 15) sprites[i].memptr_inc = sprite_crunch_table[sprites[i].memptr]; else if (cycle < 15) sprites[i].memptr_inc = 3; sprites[i].exp_flag = 1; } `value' is the value being written to $D017, `i' is the number of the sprite, `exp_flag' is the status of the expansion flip flop, and `memptr_inc' is the value that is being added to the sprite memory pointer on this line, after the DMA is done. Of course this is done for every sprite. Now, this has no theoretical foundations; I have no explanation for those values, that actually look like black magic. Is there anybody who has tried to explain this effect? Another problem is that I am pretty sure there is still something wrong with this. I have at least two demos that do not behave correctly yet. Maybe trying to explain the internals could help, but so far we have not had the time to investigate this further. Is there anybody out there who could help? Btw, CCS64 does that right. Too bad it does not come with source code. :-) Bye Ettore. - This message was sent through the cbm-hackers mailing list. To unsubscribe: echo unsubscribe | mail cbm-hackers-request@dot.tcm.hut.fi.
Archive generated by hypermail 2.1.1.