Jump to content
IGNORED

Back to the future


ZackAttack

Recommended Posts

Here is a ROM that uses the power of the Harmony cart to display 10 colored sprites per line. It uses a prototype driver that isn't supported in emulation so you'll have to put it on a Harmony cart to run it.

 

I'd like to get some feedback on how well this works on different systems. I've tested on a NTSC JR and 7800 and the results were good.

 

Thanks to rbairos for providing the converted audio and graphics.

 

Current Build:

back-to-the-future4.bin

 

Edit: 12/18/2017 - Uploaded version 4 with proper driver fix and an additional second of audio samples

Edit: 12/16/2017 - Uploaded version 3 with extra nops to increase hold time

 

Older Builds:

back-to-the-future3.bin

I've included a picture of it running for those who don't have a harmony and would like to see. There's more to it than what's in the picture though, so I'd recommend running it if you have the hardware handy.

 

 

post-40226-0-64708900-1513387587_thumb.jpg

 

 

Here is the code for the display kernel. It's pretty messy due to the extreme optimization and complete misuse of the 6507 JSR instruction. In order to compensate for artifacts from the JSR instruction the ball is used to mask some pixels. There wasn't enough time to both resize it and enable it every scan line. So CTRLPF is used to do both by changing the size and the PF priority. The ball is always enabled, but it is shown or hidden based on the PF priority. Since JSR is used to write to GRP1 and GRP0 it's called a second time to write to AUDV1 and AUDV0. This allows for 5bit sampled audio, though this demo is only using 4 bits because of space constraints. After the GRP and AUD registers are written to a TXS is performed to reset the SP back to GRP1. The X register is preloaded with the address GRP1 in vblank and remains that value during the entire frame. Y is used for the color of the right most sprite and is loaded on the previous scan line. JSR values are computed by subtracting the number of bytes consumed by the instructions until the next JSR. Each JSR is effectively loading the values that will be stored in the next JSR when the PC gets pushed to the stack. The JSR must always target an address in the ROM. So D12 is always set. Because there are about 30 bytes between each JSR there are some values which require D11 to be set as well in order to avoid starting outside of ROM space. This is why 0x800 is added if D12 was cleared by the previous subtraction. This also increases the ball size to 2 so it covers both pixels represented by D12 and D11. Whether or not the ball was enabled was determined by D12 in the original value. There is a slight artifact if you have the second to last sprite with the pattern xxx1000 and the last sprite has a value less than 32 or so. In this case you end up with xxx1100. There simply isn't enough time to move the ball over one in order to mask just D11, so D11 remains visible. This is a very small percentage of the time and isn't very noticeable so it should be acceptable. It takes about 6 lines of vblank and overscan to fill the audio buffer, position objects, and initialize everything for the next frame. The 6507 runs a routine from ZP RAM for the other 64 lines. This routine updates the audio registers and performs the vsync. During those 64 lines the ARM CPU is currently idle. All the display kernel lookups are done between putting bytes on the 6507 data bus. Hopefully this provides enough time to load in more data from the EEPROM or the SD card. It at least provides ample time for some game logic and audio calculations though.

 

Eventually I'll be posting the entire source to GitHub for everyone to enjoy, but I want to stabilize the design some more first.

		for(; i < 192;)
		{
			// Left group starts cycle 0
			vcsJsr6(jsrl);  // G, I Graphics <-e1 results in I=$ff
			vcsWrite5(GRP0, pGraphics[i*10]); // A graphic
			vcsWrite5(GRP1, pGraphics[i * 10 + 2]); // C graphic
			vcsWrite5(GRP0, pGraphics[i * 10 + 4]); // E graphic
			vcsWrite5(COLUP0, pColors[i * 10 + 0] << 1); // A color
			vcslda2(pColors[i * 10 + 2] << 1); // C color
			vcssta4(COLUP1); // C color
			vcslda2(pColors[i * 10 + 4] << 1);	// E color
			vcstxs2();
			// Should be 36 cycles prior to here
			vcssta3(COLUP0); // E color
			vcslda2(pColors[i * 10 + 6] << 1);   // G Color - 41
			// 0x20 - 23 = 0x09 => sample will offset range by 0-15 giving 0x20-0x2f
			vcsJsr6(0x1009 + ((sampleOffset & 1) ? pAudioSamples[sampleOffset >> 1] >> 4 : (pAudioSamples[sampleOffset >> 1] & 0xf)));
			sampleOffset++;
			vcssta3(COLUP1); // G Color
			vcssta3(GRP1);   // Flush delay register
			vcssty3(COLUP0); // I Color - 56

			i++;
			jsrr = (((unsigned short)pGraphics[i * 10 + 7]) <<  | pGraphics[i * 10 + 9]; // H and J graphics bytes
			vcsWrite5(HMP0, 0x80);
			ctrlpfr = ((jsrr & 0x1000) >> 10) ^ 0x5;
			vcssta3(HMP1);
			jsrr = (jsrr | 0x1000) - 33; //31 bytes between JSRs
			vcssta4(HMBL);
			if ((jsrr & 0x1000) == 0)
			{
				jsrr += 0x800;
				ctrlpfr |= 0x10;
			}
			vcsldy2(pColors[i * 10 + 9] << 1);	// J Color
			vcsWrite5(HMOVE, 2);

		StaggeredFrame:
			if (i >= 192)
			{
				break;
			}
			// Right group starts cycle -1
			vcsJsr6(jsrr);  // H, J Graphics <-de results in J=$ff
			vcsWrite5(GRP0, pGraphics[i * 10 + 1]); // B graphic
			vcsWrite5(GRP1, pGraphics[i * 10 + 3]); // D graphic
			vcsWrite5(GRP0, pGraphics[i * 10 + 5]); // F graphic
			vcsWrite5(COLUP0, pColors[i * 10 + 1] << 1); // B color
			vcsWrite5(COLUP1, pColors[i * 10 + 3] << 1); // D color
			vcslda2(ctrlpfr);
			vcssta3(CTRLPF);
			vcslda2(pColors[i * 10 + 5] << 1);	// F color
			vcstxs2();
			// Should be 39 cycles prior to here
			vcssta3(COLUP0); // F color
			vcslda2(pColors[i * 10 + 7] << 1);   // H Color - 44
	      // 0x20 - 22 = 0x0a => sample will offset range by 0-15 giving 0x20-0x2f
			vcsJsr6(0x100a + ((sampleOffset & 1) ? pAudioSamples[sampleOffset >> 1] >> 4 : (pAudioSamples[sampleOffset >> 1] & 0xf)));
			sampleOffset++;
			i++; 
			jsrl = (((unsigned short)pGraphics[i * 10 + 6]) <<  | pGraphics[i * 10 + 8]; // G and I graphics bytes
			vcssta3(COLUP1); // H Color
			ctrlpfl = ((jsrl & 0x1000) >> 10) ^ 0x5;
			vcssta3(GRP1);   // Flush delay register
			jsrl = (jsrl | 0x1000) - 30; //28 bytes between JSRs
			vcssty3(COLUP0); // J Color - 59
			if ((jsrl & 0x1000) == 0)
			{
				jsrl += 0x800;
				ctrlpfl |= 0x10;
			}
			vcsWrite5(CTRLPF, ctrlpfl);
			vcsWrite5(HMCLR, 0x00);
			vcsWrite5(HMOVE, 2);
			vcsldy2(pColors[i * 10 + 8] << 1);	// I Color
		}
Edited by ZackAttack
  • Like 6
Link to comment
Share on other sites

doesn't work on my light sixer, I get a blank screen or various lines:

Would you please try again with the next build in the first post? I changed the driver to wait for the correct ZP address to appear on the bus before tri-stating the data bus. Previously it was tri-stating the data bus as soon as the address changed away from the current ROM location. It's possible that your system is more sensitive to violating the hold time than the ones I'm testing on.

 

Another possibility is that there is a bad bit in the RIOT RAM. Currently there are instructions executed form $80 to $B1. If the driver change doesn't help I can send you a different program that doesn't ever jump execution to RIOT RAM.

 

Thanks for testing this.

Link to comment
Share on other sites

Ah, yes. It's strange though. This really doesn't do anything questionable, especially not compared to the bus stuffing drivers we experimented with. It should just look like a normal bank switched rom to the 6507 and the 6507 is in charge of all the writes.

 

Darrell are you flashing the harmony or loading via menu from SD card? There's a good chance this only works when loading it from the menu.

Link to comment
Share on other sites

Same for me on my wood-grain 4-switch. First build shows either black ar dark brown screen, sometimes with a few vertical stripes. Second build is black with dots scrolling up both edges of the screen.

 

Note, I am still using Harmony version 1.06. I am on Arch Linux, and there is no AUR package for HarmonyCart. I am reading up on making PKGBUILD files, so I can add it to the AUR for other Arch users, although the handful of people who use Arch has very little crossover with the handful of people who have a Harmony.

Link to comment
Share on other sites

With the new build both Harmony & Encore show this, and the lines moves upward on the display.

 

attachicon.gifIMG_9580.jpg

 

 

Awesome demo! Though I get the same as Spiceware on my 4 Switch VCS with the new build.

 

 

Same for me on my wood-grain 4-switch. First build shows either black ar dark brown screen, sometimes with a few vertical stripes. Second build is black with dots scrolling up both edges of the screen.

 

Note, I am still using Harmony version 1.06. I am on Arch Linux, and there is no AUR package for HarmonyCart. I am reading up on making PKGBUILD files, so I can add it to the AUR for other Arch users, although the handful of people who use Arch has very little crossover with the handful of people who have a Harmony.

 

Thanks for all the feedback. This was certainly a tricky one. Turns out the problem was the hold time of the last ROM byte injected before a switch to zeropage. The driver change that I made in version 2 was correct, but it resulted in a breaking change to the JSR function. Unfortunately I ran the wrong bin file and thought version 2 was working with the driver change. Turns out version 2 doesn't work anywhere :(

 

I'm still trying to figure out how to fix the JSR function to work with the fixed driver, but for now I just hacked the original driver to waste some cycles before tristating the data bus. This seems to resolve it, but it's not as robust as it should be and I will fix it right once I figure out this JSR problem.

 

What's interesting is why it worked in my testing but doesn't work for anyone else. I still had the harmony cart plugged into my test harness which allows the logic analyzer to be attached to the Atari busses. As CPUWIZ pointed out a long time ago, these "mile long" wires could cause problems. In this case it caused the hold time to increase artificially and compensated for the flawed driver. I plugged my harmony cart directly into the 7800 and then the problem appeared for me as well. I apologize for this testing failure on my part. Obviously I will test in this configuration from now on and reserve the harness for debugging purposes only.

 

I've uploaded version 3 which uses the hack to extend the hold time and works when plugging the harmony directly into the Atari. Hopefully this will work for everyone now and serve as a reward for helping me find this problem.

Link to comment
Share on other sites

Working for me now, too!

 

That is so weird. Just yesterday I was looking up information on doing a composite mod, and I noticed that when some people do it, they use rather long wires. Of course, this causes no issues because it is only the video/audio signal, but it made me wonder what kinds of critically-timed scenarios could be negatively affected by using long wires, wires of differing lengths, etc. Deja vu, huh?

  • Like 1
Link to comment
Share on other sites

Figured out the problem with the JSR function. Forget to account for mirroring. Was waiting for it to access $1a instead of $011a. Version 4 has the properly fixed driver and updated JSR function. At this point I believe this should be compatible with all systems. I'm thinking about under clocking the ARM processor during development just to add some margin for error.

 

There's also some additional audio in version 4. Turns out I had a lot more space left in the ROM than I realized. There's still some things to work out with the linker script.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...