Raspberry Pi Pico 6502 emulator

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by BigDumbDinosaur »

jfoucher wrote:
Thanks for all the great info. Hopefully I can at least get load and save of prg files working

Don't forget that a PRoGram file has a two-byte, little-endian header that tells the kernel where to load the file. In the case of a PRG file that is a BASIC program, the header is normally ignored by loading with LOAD "0:<filename>",8 (assuming the floppy disk is device 8) and the program text is loaded to wherever in memory the start of BASIC has been defined for the target machine, e.g., $0801 in a Commodore 64. A non-relocating load is effected with LOAD "0:<filename>",8,1, which uses the header to define the address to which the file will be loaded.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
J64C
Posts: 239
Joined: 11 Jul 2021

Re: Raspberry Pi Pico 6502 emulator

Post by J64C »

What a fantastic project! Love it!
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

jfoucher wrote:
I recently received a few raspberry pi picos!
My original idea was to use one of them as a VGA output for my 6502 computer, but that did not really work out.

So I took a different tack about what to do with them and decided to run a 6502 emulator. The I/O is very simple and goes through the Pico's USB to serial capability.

For the emulation code, I started out with this and added support for 65C02 instructions to be able to run Taliforth on it. You can also choose to run it in 6502 mode by changing one #define statement.

It passes all of Klaus Dorman's 65C02 test suite.

I then added 6522 support from this repository.

Hi

And putting it on a breadboard, we get some blinkenlights !
output.gif
While running the tests, I get about 3.1 MHz of emulated speed if I overclock the Pico to 280 Mhz. That seems fairly slow, so I've been looking at Daryl's code for an ARM assembly 6502 emulator. I have absolutely no experience in ARM assembly though, so it will be a while before I can try and rewrite the emulator in ARM assembly that is compatible with the RP2040 microcontroller... If we go by Daryl's result (ARM: 900 MHz -> 6502: 97MHz) I should be able get more than 25 MHz 6502 emulated speed out of the Pico!

Here is the github repo if anyone is interested : https://github.com/jfoucher/pico-6502
Hi jfoucher - Would you happen to still have example code used to blink the lights? This is a very interesting project. I have played a little with it, loaded Krusader and had allot of fun, but I'm having trouble understanding how to talk to the emulated via. If I can come to understand this part, I'm thinking I can handle getting it to talk with my SD card.

To light up any LED I tried writing #$FF to $FF90 - $FF94 but no luck, then tried $#FF to all memory locations below $F000, which is where Krusader starts, but again no luck.

Thanks
Shaking out the dirty bits!

https://github.com/DonaldMoran
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

I was able to get output to work fine, it was just that in main, line

Code: Select all

gpio_dirs = 0;
was in place, while needing to be replaced by its comment

Code: Select all

gpio_dirs = GPIO_PORTB_MASK | GPIO_PORTA_MASK;
Looking now to get external input to work.

Thanks
Shaking out the dirty bits!

https://github.com/DonaldMoran
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

* This post has been updated after further work on this code*

External input/output is now working. To accomplish this, I heavily modified the read6502 routine within 6502emu.c. It may ultimately end up that this was not necessary, I still ponder if there was some small issue causing external input to not work as expected, however the below describes what works for me at present.

I connected up a 1602A display (not i2c), and executed a 6502 assembly Hello World program which printed to the screen as expected, with a small exception in that I had to delay in my assembly program after setting the data direction register.

Next I ensured I could read correct values when pulling GPIO's high or low from an external source and proceeded with testing spi from PORTA which was successful as well. For this I connected an SD card to PORTA and ran George Foot's full initialization, sending several commands then reads the first sector, printing the last byte back to the LCD, which on a FAT32 card was reported back correctly as 55AA. His example is at https://github.com/gfoot/sdcard6502/tree/master

From that same repo, I then staged the SUBFOLDR/DEEPFILE.TXT file and executed the test_dumpfile.s program, which successfully found the directory, the file and printed it's contents to the LCD.

I did not have to delay in assembly when setting the data direction registers for spi, but I did have to delay in any code setting the ddr which supported a 1602A display.

With this I have confidence that those changes (though they can be improved) are at least working.

There is more work to be done. Known ones are:
  • As mentioned above with a 1602A display, when setting it's associated data direction register, in the 65c02 assembly I find it must have a delay afterward, else the display will miss the first few characters. This is odd because if the port is instead to speak with a SD card interface over SPI, no delay is needed. The shortest delay that worked was to simply set x to #128, decrement and loop till zero. Another option to solve this was to set a 2ms sleep in the C code when it sets the data direction register, however this is wasteful and slows things down too much while it is more efficient to code a small assembly delay for any port ddr used with a 1602A display.

    Memory can be inspected for the via ports A and B, I "think" this may have worked in the original version and I will re-visit that code, however for now I have returned them in a custom way. I do need to make sure these are all returning correctly.
Below is the modified routine. I also I changed the address for getchar and putchar because I loaded Krusader / wozmon and the original addresses would interfere.

I have one additional global (I know) variable defined:

Code: Select all

uint8_t via_latch = 0;
Then a modified read6502 as:

Code: Select all

uint8_t read6502(uint16_t address)
{
#ifndef TESTING
    // if (address == 0xf004) { // Don, update to work easily with Krusader
    if (address == 0xe004)
    {
        int16_t ch = getchar_timeout_us(100);
        if (ch == PICO_ERROR_TIMEOUT)
        {
            return 0;
        }
        return (uint8_t)ch & 0xFF;
#ifdef VIA_BASE_ADDRESS
    }
    // else if ((address & 0xFF00) == VIA_BASE_ADDRESS)
    else if ((address & 0xFFF0) == VIA_BASE_ADDRESS) 
        {
        // MODIFICATION PORTA
        if (address == VIA_BASE_ADDRESS + 0x01) // PORTA
            // MODIFICATION PORTA
            {
            uint8_t pin_0_value, pin_1_value, pin_2_value, pin_3_value, pin_4_value, pin_5_value, pin_6_value, pin_7_value;
            uint8_t pins[] = {PIN_0, PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, PIN_6, PIN_7};
            via_latch = (gpio_get(PIN_7) << 7) | (gpio_get(PIN_6) << 6) | (gpio_get(PIN_5) << 5) | (gpio_get(PIN_4) << 4) | (gpio_get(PIN_3) << 3) | (gpio_get(PIN_2) << 2) | (gpio_get(PIN_1) << 1) | gpio_get(PIN_0);
            }
        // MODIFICATION PORTB
        if (address == VIA_BASE_ADDRESS) // PORTB
            {
            uint8_t pin_8_value, pin_9_value, pin_10_value, pin_11_value, pin_12_value, pin_13_value, pin_14_value, pin_15_value;
            uint8_t pins[] = {PIN_8, PIN_9, PIN_10, PIN_11, PIN_12, PIN_13, PIN_14, PIN_15};
            via_latch = (pin_8_value << 7) | (pin_9_value << 6) | (pin_10_value << 5) | (pin_11_value << 4) | (pin_12_value << 3) | (pin_13_value << 2) | (pin_14_value << 1) | pin_15_value;
            }
        if (address == VIA_BASE_ADDRESS + 2) // PORTB DDRB
            {
            // Access the value stored at M6522_REG_DDRB
            via_latch = via.pb.ddr;
            }   
        if (address == VIA_BASE_ADDRESS + 3) // PORTA DDRA
            {
            // Access the value stored at M6522_REG_DDRA
            via_latch = via.pa.ddr;
            }   
        if (address == VIA_BASE_ADDRESS + 4) // T1C-L 
            {
            via_latch = via.t1.counter & 0xff;
            }     
        if (address == VIA_BASE_ADDRESS + 5) // T1C-H 
            {
            via_latch = via.t1.counter >> 8;
            } 
        if (address == VIA_BASE_ADDRESS + 6) // T1L-L 
            {
            via_latch = via.t1.latch & 0xff;
            }   
        if (address == VIA_BASE_ADDRESS + 7) // T1L-H 
            {
            via_latch = via.t1.latch >> 8;
            }  
        if (address == VIA_BASE_ADDRESS + 8) // T2C-L 
            {
            via_latch = (uint8_t) (via.t2.counter & 0xff);
            } 
        if (address == VIA_BASE_ADDRESS + 9) // T2C-H  
            {
            via_latch = (uint8_t) (via.t2.counter >> 8);
            }   
        //if (address == VIA_BASE_ADDRESS + 0xa) // SR   
        //    {
        //    via_latch = via.sr); // FIX ME
        //    }  
        if (address == VIA_BASE_ADDRESS + 0xb) // ACR   
            {
            via_latch = via.acr; 
            } 
        if (address == VIA_BASE_ADDRESS + 0xc) // PCR    
            {
            via_latch = via.pcr;
            }         
        if (address == VIA_BASE_ADDRESS + 0xd) // IFR    
            {
            via_latch  = via.intr.ifr;
            }      
        if (address == VIA_BASE_ADDRESS + 0xe) // IER    
            {
            via_latch  =  via.intr.ier;
            }     
        if (address == VIA_BASE_ADDRESS + 0xf) // ORA/IRA Reg 1 but No handshake    
            {
            via_latch = (gpio_get(PIN_7) << 7) | (gpio_get(PIN_6) << 6) | (gpio_get(PIN_5) << 5) | (gpio_get(PIN_4) << 4) | (gpio_get(PIN_3) << 3) | (gpio_get(PIN_2) << 2) | (gpio_get(PIN_1) << 1) | gpio_get(PIN_0);
            }  
        // And in any case
        //if ((address == VIA_BASE_ADDRESS + 0x01) || (address == VIA_BASE_ADDRESS))
        //    {
        via_pins &= ~(M6522_RS_PINS | M6522_CS2); // clear RS pins - set CS2 low
        // Set via   RW high   set selected  set RS pins
        via_pins |= (M6522_RW | M6522_CS1 | ((uint16_t)M6522_RS_PINS & address));
        via_pins = m6522_tick(&via, via_pins);

        // MODIFICATION VDATA 
        //  Via trigrred IRQ
        // uint8_t vdata = M6522_GET_DATA(via_pins);
        uint8_t vdata = via_latch;
        // printf("reading from VIA: %04X %02X \n", address, vdata);
        //    }
        via_update();
        // old_ticks > 0 ? old_ticks-- : 0;
        return vdata;
        //}
#endif
        }
#endif
    return mem[address];
}
jfoucher > I forked the repo and will sync my changes tomorrow. Let me know if you would be interested in pull request back to your repo ?

I'm curious if Fake6502 is open source, as well as the work you've done with 6502emu.c, etc?

Thanks
Shaking out the dirty bits!

https://github.com/DonaldMoran
kuwatay
Posts: 4
Joined: 06 Aug 2021
Location: Muroran-shi, Hokkaido, JAPAN
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by kuwatay »

Hi,

I modified pico-6502 to emulate Apple1 (Replica1).
It worked with original binary of Wozmon, krusader, and 8K basic, which located at $E000-$FFFF.

I forked noneya's dev branch and create new branch.
https://github.com/kuwatay/pico-6502-apple1/tree/apple1

Thank you for your useful code.

-Yoshi
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by BigEd »

Welcome - and congratulations, and thanks for sharing!
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

Hi kuwatay - That is awesome and thanks for sharing!

You also beat me to it ! :-) I am putting the finishing touches on one which will have Taliforth 2, Krusader, Wozmon, and EHBasic. EHBasic will load from an sd card to RAM at $5000. This will actually (purposely) be 2 PICO's, one serving as the CPU, ACIA, RAM and ROM and the other serving as a disk controller for the sd card with future plans to incorporate PICOVGA on that one as well.

I have it all working well tonight with the only exception being I need to finish a little routine to allow for the saving of the basic code, I just finished load before checking the forum. I should finish up save and get this posted in the next few days.

I also used 2 PICO's purposely because I wanted to simulate a setup with a pico connected to a real via., i.e. such that the code written would pretty much be ready to move over to a setup with a real 6502 processor, etc.

kuwatay thanks, I look forward to downloading and playing with your contribution as well!

PS: Would you consider posting the assembly source for the 8KBasic_Monitor.h ? I was just working with apple 1 basic for my homebrew yesterday, I got it to run but everything I enter ends with SYNTAX ERROR. I am pretty sure it relates to the high bit handling but didn't solve it so moved on to other things. If I could review your source it may help me with mine.
Shaking out the dirty bits!

https://github.com/DonaldMoran
kuwatay
Posts: 4
Joined: 06 Aug 2021
Location: Muroran-shi, Hokkaido, JAPAN
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by kuwatay »

BigEd-san

Thank you for your worm welcome. I'll enjoy the forum with lots of 6502 experts.
kuwatay
Posts: 4
Joined: 06 Aug 2021
Location: Muroran-shi, Hokkaido, JAPAN
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by kuwatay »

Hi, noneya

Your project sounds very interesting. I'm looking forward to see it.

Actually, I didn't write any 6502 code for pico-6502-apple1, just wrote a1 PIA emulator in C code.
The binary in 8KBasic_Monitor.h came from RC6502 replica 1 project.

https://github.com/tebl/RC6502-Apple-1- ... e/firmware

Anyway, if you need a1basic source code, here the link of asm source code by Eric Smith.

https://github.com/brouhaha/a1basic/blo ... 1basic.asm

Hope this helps.

-Yoshi
User avatar
jfoucher
Posts: 94
Joined: 27 Dec 2020
Location: France
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by jfoucher »

noneya wrote:
jfoucher > I forked the repo and will sync my changes tomorrow. Let me know if you would be interested in pull request back to your repo ?

I'm curious if Fake6502 is open source, as well as the work you've done with 6502emu.c, etc?

Thanks
Sorry for not responding earlier. As far as I can tell fake6502 is GPL licensed. I usually license my code with the MIT license, but I noticed that I did not have any license set on the picovic or the pico-6502 repositories, which has now been corrected.
Jonathan Foucher

Take a look at the Planck 6502 computer.
User avatar
jfoucher
Posts: 94
Joined: 27 Dec 2020
Location: France
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by jfoucher »

kuwatay wrote:
Hi,

I modified pico-6502 to emulate Apple1 (Replica1).
It worked with original binary of Wozmon, krusader, and 8K basic, which located at $E000-$FFFF.

I forked noneya's dev branch and create new branch.
https://github.com/kuwatay/pico-6502-apple1/tree/apple1

Thank you for your useful code.

-Yoshi
Very nice, thank you for this!
Jonathan Foucher

Take a look at the Planck 6502 computer.
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

jfoucher wrote:
noneya wrote:
jfoucher > I forked the repo and will sync my changes tomorrow. Let me know if you would be interested in pull request back to your repo ?

I'm curious if Fake6502 is open source, as well as the work you've done with 6502emu.c, etc?

Thanks
Sorry for not responding earlier. As far as I can tell fake6502 is GPL licensed. I usually license my code with the MIT license, but I noticed that I did not have any license set on the picovic or the pico-6502 repositories, which has now been corrected.
Hi jfoucher,

Thanks much. This is a neat project, though there are great emulators out there, this approach provides a way to mimic the interaction with the via in a real world way. As mentioned earlier I've connected up to a LCD, interfaced with an SD card over SPi / parallel, etc. This provides a quick and easy platform to develop against prior to burning roms, and overall a great way to share back with others in our hobby.

Thanks for sharing!
Shaking out the dirty bits!

https://github.com/DonaldMoran
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: Raspberry Pi Pico 6502 emulator

Post by noneya »

kuwatay wrote:
Hi, noneya

Your project sounds very interesting. I'm looking forward to see it.

Actually, I didn't write any 6502 code for pico-6502-apple1, just wrote a1 PIA emulator in C code.
The binary in 8KBasic_Monitor.h came from RC6502 replica 1 project.

https://github.com/tebl/RC6502-Apple-1- ... e/firmware

Anyway, if you need a1basic source code, here the link of asm source code by Eric Smith.

https://github.com/brouhaha/a1basic/blo ... 1basic.asm

Hope this helps.

-Yoshi
Yoshi > Thank you! Looking further into a1basic, though possible, re-locating to other memory addresses is a little involved. Jeff Tranter has done some heavy lifting in that regard ( https://github.com/jefftranter/6502/tree/master/asm ), but alas, I still have the syntax error. I will re-visit later, for now I need to get back to cleaning up the code for the PICO. I got side tracked playing with AppleSoft-lite. I got that one working but now need to also write the save and load routines for it as well. :-) ( https://git.applefritter.com/Apple-1-SW )

Thanks,
Shaking out the dirty bits!

https://github.com/DonaldMoran
okwatts
Posts: 110
Joined: 11 Nov 2020
Location: Kelowna Canada

Re: Raspberry Pi Pico 6502 emulator

Post by okwatts »

Hi looking forward to this topic. Look also at Oscar V's KIM-UNO also has apple integer basic. Re the syntax error is it as simple as needing all CAPS?
Post Reply