-
Posts
2,262 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
Gallery
Events
Store
Community Map
Everything posted by Al_Nafuur
-
If it is a read/write to the TIA or RIOT it is on the cartridge port a "write" to the cartridge too. The "lastAccessWasWrite" flag is only to exit early and let Stella do its thing and then check at the next peek/poke if we may have to wait for the cart to read/peek the data (e.g. for banking). That's why a timer is better than a delay, because with a time we would only wait the remaining time before the next cycle.
-
I think 64 bit is the better choice, but currently I can't get the 64bit version CartPort running on my setup. Even installing on a fresh SD-Card didn't worked. I tested the 32bit SD-Card and it still works. maybe using a fixed hotspot is better: sta $f800 You can write the failed address to a second hotspot: sty $f801 To make the thing more visual you also might write the two values to player0 and player1. But we can trap $f800 in Stella and then check A and Y. So we @MarcoJ and I can use this ROM to debug SC RAM with out a logic analyzer.
-
But the cartridge.. 👍 I only made a rough estimate Indeed! We don't need the ghost read, but the real amount of 6502 cycles and the address of each cycle when doing a data read. Currently our cycles aren't much shorter than the 6502! Obviously not! Otherwise code execution in SC-RAM would work! SC-RAM needs more than one 6502 cycle to set the data bus. We also shouldn't do data reads in one cycle! That is what the 2600 does and it is what we should do too.
-
unknown hotspots? The delay loop doesn't account for the time Stella has consumed for the emulation between the write (ghost read) and the next access. As you already have pointed out, accessing SC-RAM in a real cart is always 2 or more 6502 cycles. The SC-RAM is starting to response when the address is set (first cycle), but it hasn't set the data bus at the end of the cycle (like normal ROM or faster RAM does). This doesn't matter because since no code is executed in SC-RAM the read from the 6502 is at the end of the second (or third) cycle. We would imitated that with the ghost reads. Which I suspect are currently not coming to the CartPort driver, so we are trying to read SC-RAM in one cycle! Does the 2600 has that?
-
Not with every cartridge, but in the CartPort can be any cartridge. Peeking and poking around blindly like that can be dangerous. The 7800 is doing a ROM scan of some sort at startup, maybe we can imitate this and get some information about the cartridge.🤷♂️ No, we need a real timer. A delay like that will lead to unnecessary waits for us in our writes (and ghost reads).
-
Unfortunately this will again reduce our performance. 🤔 Maybe if we for the ghost reads only set the timer for the next request and not wait for the response (like we want to do for the writes) we might reduce the performance impact. But this means we need a reliable precise timer (internal or external). Currently my 64bit PiOS Stella is not working with any delay/timer version we have tested. I can't get stable reads and the emulation always stops with "Invalid instruction". I first suspected a hardware issue with the breadboard again, but switching back (multiple times!) to the 32bit SD-Card resulted in a working emulation.
-
Unfortunately we cannot (like a real 2600) know about SC-RAM. Yes, No. I have long suspected that the ghost reads and writes do not arrive at the driver. I can't really see them in the screenshots @Kroko has posted: So if SC-RAM and some bankings (FA?) need these ghost writes or the extra cycles, we will have to check if they are really requested from the CartPort driver by Stella.
-
The Debugger had "crashed" bank switched cartridges before which resulted in an "Invalid Instruction", but it never crashed Stella. Yes cartridges without hotspot in the 4K ROM area will work with the debugger, but others will not. I thought about how the debugger should behave with the CartPort, but I have postponed this for the time being until we have a running CartPort driver. My conclusion is that the debugger cannot simply scan the ROM area of the CartPort in the future. It can only make assumptions about the banking from the addresses (ROM mirrors) requested by the 6502 and the reads/writes to the ROM area at runtime. These assumptions can be displayed in the debugger, but shouldn't be the base for any ROM scans of the debugger.
-
I think the CPU is fooling us about these timers/cycle counters! No matter what delay I choose (8000 - 20000), i can't get my test routine running for a very long time. Sooner or later a read fails! The longest run was about 20 minutes, but usually it fails in the first 4 minutes. I am currently testing the same hardware setup with the NOP delay routine and it is running for nearly 2 hours now (without any failed read!)
-
This is the NOP count delay, which makes the write count longer than they need to be. That's why we want to switch to a real timer or cpu cycle counter. But I have the guts feeling they are not reliable on the Pi or the way we are trying to get these values from the CPU. I will modify my test routine to let it run for hours with a fixed value of ~8000 (Pi CPU cycles?? !!) and test for bad reads from the ROM.
-
Yes, ~1000 cycles was what I expected at 1400Mhz a cycle is ~0.7ns. The ~7000 in my test routine was very stable and I tested it multiple times. Something is very strange here. Stella even crashes with the very long delay > 100,000 when I let it run for a longer time. The reads and writes look a little different. We are only checking the time left when the last cycle included a write to the cartridge (which is also true for reads/writes from RIOT and TIA). For a read cycle we are waiting the full ~700ns (like the 6502) before we read the data bus. I pushed my tests to the branch "feature/cartridgeportpmccntr": https://github.com/Al-Nafuur/stella/tree/feature/cartridgeportpmccntr
-
Does the emulation runs stable at full speed? We are clearing the bus first and then setting the active address bits (+data bits on writes). After a write cycle I am setting the data bus to read in between these two steps. The Raspberry Pi CPU cannot set/unset the GPIO port with one write, so we first have to clear all bits and then set the value we want to set. Bits that are 0 in both steps (clear or set) will be ignored and stay as they are. If the OS scheduler is interrupting us between these two steps the address ($00) looks like a ZP read/write for the cartridge.
-
The performance counter example now works on the Pi3B+ with 64bit PiOS: output: 124784971079 124784971099 : 20 124784971112 : 13 124784971125 : 13 124784971138 : 13 124784971144 : 6 124784971150 : 6 124784971156 : 6 124784971162 : 6 124784971168 : 6 124784971174 : 6 124784971180 : 6 124784971186 : 6 124784971192 : 6 124784971198 : 6 124784971204 : 6 124784971210 : 6 124784971216 : 6 124784971222 : 6 124784971228 : 6 124784971234 : 6 124784971240 : 6 124784971246 : 6 124784971252 : 6 124784971258 : 6 124784971264 : 6 124784971270 : 6 124784971276 : 6 124784971282 : 6 124784971288 : 6 124784971294 : 6 124784971300 : 6 I have a small test programme with which I determine from which delay value the readings from a simple ROM like Combat are stable: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <stdint.h> #define BCM2708_PERI_BASE 0x3F000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) // GPIO controller #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) int mem_fd; void *gpio_map; // I/O access volatile unsigned *gpio; // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 #define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH #define GET_DATA_BUS() ((*(gpio+13)&0x1fe000)>>13) // GPIO 13 - 20 ( 0b000111111110000000000000 ) #define GPIO_PULL *(gpio+37) // Pull up/pull down #define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock void setup_io(); static inline uint64_t read_pmccntr(void) { uint64_t val; asm volatile("mrs %0, pmccntr_el0" : "=r"(val)); return val; } int main(int argc, char **argv) { uint64_t t0, t1; char pp[1]; int g,rep, delay_counter = 1000; uint8_t a[0x200], b; // Set up gpi pointer for direct register access setup_io(); // Set GPIO pins 0-12 to output (6502 address) for (g=0; g<=12; g++){ INP_GPIO(g); // must use INP_GPIO before we can use OUT_GPIO OUT_GPIO(g); } // Set GPIO pin 21 to output (Level shifter dir) *(gpio+(2)) = 0b001000; // Set GPIO pin 21 to Low (ls dir read) GPIO_CLR = 1<<21; for (rep=0x000; rep<0x200; rep++){ GPIO_CLR = 0b1111111111111; GPIO_SET = rep | 0x1000; g = 10000; while(g--){asm volatile("nop"); } a[rep] = (uint8_t)GET_DATA_BUS(); if(rep < 0x10){ printf("Read %d on address: %d \n", a[rep], rep ); } } // scanf("Start %s", &pp); start_the_test: for (g=0; g<1000; g++){ for (rep=0x000; rep<0x200; rep++){ GPIO_CLR = 0b1111111111111; GPIO_SET = rep | 0x1000; t0 = read_pmccntr(); do{ t1 = read_pmccntr() - t0; } while( t1 < delay_counter); b = (uint8_t)GET_DATA_BUS(); if ( b != a[rep]){ printf("Readings differ with delay_counter %d in round %d on address: %d a: %d b: %d !\n", delay_counter, g, rep, a[rep], b ); delay_counter += 100; goto start_the_test; } } printf("."); } printf("\nAll the Same!! delay_counter %d \n", delay_counter); return 0; } // // Set up a memory regions to access GPIO // void setup_io() { // open /dev/mem if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem \n"); exit(-1); } // mmap GPIO gpio_map = mmap( NULL, //Any adddress in our space will do BLOCK_SIZE, //Map length PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory MAP_SHARED, //Shared with other processes mem_fd, //File to map GPIO_BASE //Offset to GPIO peripheral ); close(mem_fd); //No need to keep mem_fd open after mmap if (gpio_map == MAP_FAILED) { printf("mmap error %d\n", (long)gpio_map);//errno also set! exit(-1); } // Always use volatile pointer! gpio = (volatile unsigned *)gpio_map; } // setup_io According to this routine the readings are stable with a performance counter > 7000 (cpu cycles?). However when I use the performance counter and this delay value in Stella the emulation crashes really fast. The emulation gets somewhat stable with delays > 100,000 but it is extremely slow!
-
I rebooted a few times and tried different things like configure without host=rtstella and building the master branch or just using make and eventually it finished the build. There are a few fixes needed in the driver for the 64bit build. (hint: use long instead of int in line 99 and 124) I am currently testing @DirtyHairy's counter.
-
The new Atari 2600+ w/HDMI out and 2600/7800 support
Al_Nafuur replied to tremoloman2006's topic in Atari 2600+
Online gaming on the 2600 is already possible with PlusROM enabled devices like the PlusCart and emulators like Stella, Gopher2600 and Javatari. Do you mean something like the PlusROM High Score Club?
