Page 1 of 3
Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 12:23 pm
by speculatrix
Hi folks.
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
I have this hair-brained scheme of replacing the EEPROM with flash memory. The CPU board of my (backplane-based) machine would have a small microcontroller that talks to my PC via serial. So when I assemble a new ROM binary on the PC, it would automatically push it to the 6502 machine's flash via the MCU.
I have a proof of concept prototype up and running, but here's the key bit. This prototype has its own RAM. The PC first pushes the binary to the RAM (via the MCU) before instructing the MCU to move the contents into flash. I can't fully remember why I do this as a two-stage process, but let's go with it for now.
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
I'd just like to know if this is sane or if there are snags.
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 12:44 pm
by drogon
Hi folks.
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
OK... I am currently doing similar, however:
- Push and hold Reset Button
- Remove EEPROM from ZIF socket and put it in programmer
- Optional: release reset button
- Burn EEPROM
- Push and hold Reset Button
- Remove EPROM from programmer and put back into board ZIF socket
- Release Reset button
Please don't bother to tell me how bad this is. I know it's
potentially bad and I'll just ignore your comments and keep on doing it. In the past year or so I've had precisely zero issues. Sometimes I even forget to push the reset button. It's disposable as far as I'm concerned. I've not had to dispose of one yet. I sometimes use a 2nd and put that in the programmer and program it before I do the swapsies.
I have this hair-brained scheme of replacing the EEPROM with flash memory. The CPU board of my (backplane-based) machine would have a small microcontroller that talks to my PC via serial. So when I assemble a new ROM binary on the PC, it would automatically push it to the 6502 machine's flash via the MCU.
Leave the EEPROM and write code inside it to allow in-circuit reprogramming. Most EEPROMs ought to be capable of this. I already store data into the EEPROM when it's running in my board and that's fine - however I have limited RAM so would have to download the EEPROM images 1KB at a time - do-able, but not a priority right now.
I have a proof of concept prototype up and running, but here's the key bit. This prototype has its own RAM. The PC first pushes the binary to the RAM (via the MCU) before instructing the MCU to move the contents into flash. I can't fully remember why I do this as a two-stage process, but let's go with it for now.
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
If it works then it works. It's very similar to how my Ruby 65xxx boards work. I have a tiny bit of shared RAM (mutually exclusive) which is used to bootstrap the 65xx which can then use the same area to poke commands to the MCU to load more and more, ...
-Gordon
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 1:31 pm
by gfoot
As drogon said, it is not very hard to allow writes to EEPROM from the 6502 side of things - no harder than for Flash I believe - you just need to (a) connect its "WE" pin in the usual way, qualified by the PHI2 clock; (b) be careful with the timing of the writes; and (c) maybe execute write-protect-disable magic sequences. In practice (b) means you really need to run the code from RAM while you're doing this, as while you're writing to it (and for a while afterwards) the EEPROM won't respond correctly to read operations.
If you do it right, you can write pages of 64 bytes to the EEPROM at a very fast speed (just like your EEPROM programmer does) and you can also deal with the EEPROM being "locked" (which means that unintentional writes will be mostly ignored unless you send a prefix code first).
Here is a piece of code I've used for this, to write a single 64-byte page to ROM, including executing the "let me write" magic sequenc to temporarily unlock the EEPROM for this operation. Again note that this code must execute from RAM, though you can have ROM code copy this code to RAM before executing it.
Code: Select all
jsr waitromidle
; Execute the temporary unprotect sequence
lda #$aa : sta $d555
lda #$55 : sta $aaaa ; 6 cycles since previous write
lda #$a0 : sta $d555 ; 6 cycles since previous write
; Write all the data
byteloop:
lda (zp_readptr),y : sta (zp_writeptr),y ; 11 or 18 cycles since previous write
iny
dex
bne byteloop
As noted the largest gap between writes here is 18 cycles - you can multiply that by your clock period to check you're not going over the limit for the EEPROM (as if you wait too long, it starts to commit the write and blocks further access for a while). It is quite generous though, e.g. 150us - quite a lot of cycles even at a low clock speed.
waitromidle is a routine that checks whether the EEPROM is currently processing a previous write operation:
Code: Select all
waitromidle:
pha
poll:
lda $8000 : cmp $8000 : bne poll
pla
rts
While the ROM is busy, it toggles one of the data bits high and low during any read operations you perform, meaning that two reads in a row never produce the same value; this loop just checks for that state and waits for the bit toggling to stop. This can take several milliseconds.
In my system I generally leave the initial boot code in the ROM alone, so writing bad code will never totally brick the system.
Going back to your original idea - I think you could also use a microcontroller for this, especially if it already has full bus access - however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 1:56 pm
by speculatrix
however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
Okay, but this is where I get confused (it's not difficult). If the 6502 is writing to the EEPROM, where is the 6502 code to do that (bearing in mind that I'm replacing the entire contents of ROM)? And where's the code that's transferring the ROM code from PC to 6502 machine?
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 2:00 pm
by drogon
If you do it right, you can write pages of 64 bytes to the EEPROM at a very fast speed (just like your EEPROM programmer does) and you can also deal with the EEPROM being "locked" (which means that unintentional writes will be mostly ignored unless you send a prefix code first).
What I found - and this was thanks to a hint from Ed, is that writing to a locked EEPROM does "weird stuff". Because the EEPROM has an internal CPU/Microsequence engine that's running a finite state machine to control the locking and unlocking is that if you write to a locked EEPROM then the next access results in reading garbage - often zero, but I never was able to pin-point it precisely.
However it did protect the EEPROM correctly. At the expense of crashing.
This might not be an issue if everything is running in RAM, but it is an issue if you're running code in EEPROM.
Code: Select all
Project-28/Ruby 6507 Startup
============================
*@
P28: GIBL v6
>REM Poke EEPROM...
>?&1000 = 99
At this point the system has locked-up and needs a reset..
-Gordon
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 2:04 pm
by drogon
however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
Okay, but this is where I get confused (it's not difficult). If the 6502 is writing to the EEPROM, where is the 6502 code to do that (bearing in mind that I'm replacing the entire contents of ROM)? And where's the code that's transferring the ROM code from PC to 6502 machine?
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
You copy code into RAM to do it.
that's what I need to do in my 6507 system, however that's only because the way I treat the EEPROM - as 8 'banks' of 4K. I do not have 32K of linear address space (it's a 6507 with only 13 address lines and I see 4K of RAM and 4K of ROM at any time).
One way would be like the various AVR (Arduino) systems do it: Have the bootloader "locked" in the upper few (100) bytes and arrange your download into RAM then to EEPROM - while we can't lock regions of the EEPROM like you can on the AVR with careful code, it will work. Just don't ever overwrite the bootstrap/downloader part..
Of-course if/when you need to update the bootloader then you might need to get off the sofa...
-Gordon
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 3:12 pm
by gilhad
Okay, but this is where I get confused (it's not difficult). If the 6502 is writing to the EEPROM, where is the 6502 code to do that (bearing in mind that I'm replacing the entire contents of ROM)? And where's the code that's transferring the ROM code from PC to 6502 machine?
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
On my SBC I have the 3pin jumper, which connects the /WR line from EEPROM else to +5V or to normal /WR line (R/W qualified by PHI2).
In the first position EEPROM is just ROM and cannot be modified (so no problems) - normal operations.
In the second place the EEPROM may be written into (with all the related issues) - risky life, but may be also use normally (who write to ROM anyway?)
So leaving the jumper in second place enables for anything (including normal usage).
I have in my "monitor" in ROM command, which copy some code to RAM and then jump there. The code read Serial and decode INTEL HEX lines to either write into RAM or write into buffer in RAM and then copy that buffer to EEPROM with later waiting for the write to finish and read it and compare with the buffer. This way I am able to rewrite any part in EEPROM I wish, eventually rewrite the whole EEPROM part by part (as my buffer allows).
After the HEX sequence ends, the RAM code simply jumps to start of command loop in ROM (I have some jumppoints at the begin of ROM as entrypoints to the Monitor system) - but it would be easy to jump into reset vector instead.
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 8:18 pm
by plasmo
You can structure your ROM code such that the booting up, enabling file load portion of the software is stable and always a part of your ROM code. This way you can mess up rest of the ROM program, but always have the ability to load an updated version to correct the previous mistakes. Another word, as long as you have the ability to load and run a file, you don’t have to remove your EEPROM to reprogram it. Load and run file does not necessarily require a ROM; it can also be a state machine, battery backed RAM, lookup table in programmable logic, or a separate file loading MCU.
Bill
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 11:03 pm
by Michael
Food for thought...
NO PROGRAMMER REQUIRED.
I designed an SBC with a 64K RAM IC and a $2 Arduino Nano clone to form the essence of a custom ROM Emulator & Programmer on the SBC. A 128K Flash ROM is used as an "image store". I thought this design might be an economical alternative to the Ben Eater 6502 design since it doesn't require purchasing an EPROM Programmer.
The SBC has two modes of operation; ROM Emulator mode and Run mode.
Programming a Flash ROM (via Nano USB serial @115200 bps and Terminal software on Host PC);
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2)
Load one or more hex files via Nano USB serial into 64K RAM
(3)
Program 64K 'A' or 'B' portion of Flash ROM from the 64K image in RAM (about 10 seconds)
Running, and testing iterative code changes;
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2)
Load one or more hex files via Nano USB serial into 64K RAM
(3) press 'mode' switch to enter 'RUN' mode (LED = green)
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
I've had a working prototype for several years and it runs fine at 8 MHz. I've just never finished up the Arduino ROM Emulator code into a sharable form.
I can use the prototype area on the SBC to test other address decoder schemes by removing the jumper on the JP1 "HI/LO IO" jumper block and driving the /IO line directly from the new decoder circuitry.
Re: Flash ROM idea - sanity check
Posted: Wed Sep 10, 2025 11:31 pm
by gilhad
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
The ROM Emulator just uses its own internal count to decide, if it should suppose the 6502 wants to read instruction, disables RAM+ROM and provide data, or if the 6502 wants read and then connect ROM or if 6502 wants to write and the connects RAM? Without having other indicator then its internal "count"?
Re: Flash ROM idea - sanity check
Posted: Thu Sep 11, 2025 1:05 am
by Michael
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
The ROM Emulator just uses its own internal count to decide, if it should suppose the 6502 wants to read instruction, disables RAM+ROM and provide data, or if the 6502 wants read and then connect ROM or if 6502 wants to write and the connects RAM? Without having other indicator then its internal "count"?
Yeah, that's basically correct. The emulator keeps track of each clock cycle within each instruction going to the 65C02. The Emulator code builds off the lowest level
single-clock uPush() and uPull() functions which specify which memory is active. A brief Emulator code excerpt;
Code: Select all
******************************************************************************
* low level 'blind interface' single-clock uPush() and uPull() functions *
* allow the Nano to 'push' or 'pull' data to/from the CPU data bus. The *
* uPush() function is used to 'push' data from the Nano to the 6502 over *
* data bus during a 6502 read clock cycle (with RAM and ROM disabled). *
* The uPull() function reads data on the bus during a 6502 read or write *
* clock cycle, usually with either RAM or ROM enabled. *
******************************************************************************/
void uPush(byte data) // ****************************************
{ clk(0); busOut(); // clock lo, Nano bus to 'output' {1}{4} *
PORTB = (PORTB&0xFC)|(data>>6); // set D7..D6 pins (PB1 & PB0) *
PORTD = (PORTD & 3)|(data << 2); // set D5..D0 pins *
clk(1); nop(); nop(); nop(); // clock hi *
} // ****************************************
byte uPull(byte mem) // ****************************************
{ byte data = 0; // *
clk(0); busInp(); // clock lo, Nano bus 'input' (hi-z) *
PORTC &= mem; nop(); nop(); // RAM (PC5) or ROM (PC4) enabled (lo) *
clk(1); nop(); nop(); nop(); // clock hi (plus 187.5-nSecs) *
data = (PIND >> 2); // read/collect D5..D0 bits *
data |= (PINB << 6); // read/collect D7..D6 bits *
PORTC |= 0b00110000; // RAM (PC5) & ROM (PC4) /CE 'off' (hi) *
return data; // *
} // ****************************************
Some basic 'core' functions use those low-level functions to read and write RAM or ROM by "pushing" LDA <imm>, LDA <abs>, and STA <abs> instructions and data to the 6502;
Code: Select all
/******************************************************************************
* core 'blind interface' functions *
* */
void uReset() // ****************************************
{ clk(1); // clock = 1 *
res(0); // reset = 0 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
uPull(nul); // (1) *
uPull(nul); // (2) *
res(1); // reset = 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
uPull(nul); // (1) *
uPull(nul); // (2) *
uPull(nul); // (3) *
uPull(nul); // (4) *
uPull(nul); // (5) *
uPush(lo(0x1000)); // address $FFFC (reset vector lo) (6) *
uPush(hi(0x1000)); // address $FFFD (reset vector hi) (7) *
} // ****************************************

Code: Select all
void wrROM(u16 addr,byte data) // ****************************************
{ uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> *
uPush(lo(addr)); // " address lo *
uPush(hi(addr)); // " address hi *
uPull(rom); // " 6502 write op' *
} // ****************************************
byte rdMEM(byte mem) // ****************************************
{ uPush(0x4C); // jmp $1000 reset PC (avoid I/O area) *
uPush(lo(0x1000)); // " abs address lo *
uPush(hi(0x1000)); // " abs address hi *
uPush(0xAD); // lda <abs> *
uPush(lo(addr)); // " abs address lo *
uPush(hi(addr)); // " abs address hi *
return uPull(mem); // " 6502 read op' *
} // ****************************************
void wrRAM(byte data) // ****************************************
{ uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> (uses global 'addr' var) *
uPush(lo(addr)); // " abs address lo *
uPush(hi(addr)); // " abs address hi *
uPull(ram); // " 6502 write op' *
} // ****************************************
void wrRAM(u16 addr,byte data) // **********{ overload function }*********
{ uPush(0x4C); // jmp $1000 reset PC (avoid I/O area) *
uPush(lo(0x1000)); // " abs address lo *
uPush(hi(0x1000)); // " abs address hi *
uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> *
uPush(lo(addr)); // " address lo *
uPush(hi(addr)); // " address hi *
uPull(ram); // " 6502 write op' *
} // ****************************************
Building off of the 'core' functions;
Code: Select all
/******************************************************************************
* load 64K RAM from 64K 'A' or 'B' half of ROM at 'power-up' or 'reset' at *
* a nice leisurely 1-MHz rate. *
* */
void bootload() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{ putSer(' '); // ~
run(1); // remove I/O from address space ~
uReset(); // reset 6502 (synchronize uC to cpu) ~
addr = 0x0000; // global 'addr' = $0000 ~
do // copy 64K 'A' or 'B' ROM to RAM ~
{ if((addr & 0x0FFF) == 0) // if 4K sector boundary ~
{ putSer('.'); // indicate progress ~
} // ~
wrRAM(rdMEM(rom)); // ROM -> RAM ($0000..$FFFF) ~
} while(++addr); // until roll-over to $0000 (full 64K) ~
} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code: Select all
/******************************************************************************
* program 64K RAM image onto 64K 'A' or 'B' half of the 128K Flash ROM. *
* */
void flash() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{ putSer(' '); // ~
uReset(); // reset 6502 (synchronize uC to cpu) ~
run(1); // remove I/O from address space ~
addr = 0x0000; // start address $0000 ~
do // ~
{ if((addr & 0x0FFF) == 0) // if 4K sector boundary ~
{ wrROM(0x5555,0xAA); // erase sector sequence ~
wrROM(0x2AAA,0x55); // " ~
wrROM(0x5555,0x80); // " ~
wrROM(0x5555,0xAA); // " ~
wrROM(0x2AAA,0x55); // " ~
wrROM(addr,0x30); // " ~
_delay_ms(25); // required delay ~
putSer('.'); // indicate progress ~
} // ~
wrROM(0x5555,0xAA); // write byte 'unlock' sequence ~
wrROM(0x2AAA,0x55); // " ~
wrROM(0x5555,0xA0); // " ~
wrROM(addr,rdMEM(ram)); // write byte ~
_delay_us(20); // required write delay ~
} while(++addr); // until roll-over to 0 (full 64K) ~
} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code: Select all
/******************************************************************************
* hex file download to RAM (ROM emulator mode, 115200 baud) *
* */
byte loadHex() // ****************************************
{ byte bytecnt; // hex record length *
byte type; // hex record type *
byte data; // *
byte cksum; // hex record checksum *
byte error = 0; // *
uReset(); // reset 6502 (synchronize uP to CPU) *
run(1); // remove I/O from address space *
do // process hex file *
{ do // process hex record *
{ putSer(data = getSer()); // echo & flush <cr> and <lf> chars *
} while(data != ':'); // until we see a ':' record header *
cksum = (bytecnt = getByte()); // get 'byte' (not character) count *
cksum += (data = getByte()); // get address hi *
addr = (data << 8); // " *
cksum += (data = getByte()); // get address lo *
addr += data; // " *
cksum += (type = getByte()); // get record type (0, 1, or 4) *
if(type == 4) // if <extended address> record *
{ cksum += getByte(); // *
cksum += getByte(); // *
} // *
if(type == 0) // if <data> record *
{ while(bytecnt--) // *
{ data = getByte(); // *
cksum += data; // *
wrRAM(data); addr++; // write byte to RAM, bump address *
} // *
} // *
data = getByte(); // get record checksum byte *
if(-data != cksum) error = 1; // test for error *
} while(type != 1); // loop until <end-of-file> record *
return error; // *
} // ****************************************
Several additional functions provide serial routines and a menu for the Terminal (Load, Prog, Run), the CPU clock, code to support the switch between Emulator mode and Run mode, etc.
Hope that helps. Cheerful regards...
Re: Flash ROM idea - sanity check
Posted: Thu Sep 11, 2025 4:20 am
by gilhad
Wow!
That is really impressive

Thank you very much

Re: Flash ROM idea - sanity check
Posted: Thu Sep 11, 2025 8:02 am
by speculatrix
a $2 Arduino Nano clone to form the essence of a custom ROM Emulator & Programmer on the SBC.
I did consider using an MCU as a ROM emulator, and it's something I might still explore just for fun. Your work provides many useful points of departure - thanks.
Re: Flash ROM idea - sanity check
Posted: Thu Sep 11, 2025 8:42 am
by Michael
You're welcome. Should also mention you could go ROM-less and simply use the emulator to load programs via serial and run. Or you can load RAM with a small 6502 boot-loader code from an array placed in the Emulator program. Here's an example where I load an array of Nick Gammon's gPascal image into RAM;
Code: Select all
const uint8_t gPascal[] PROGMEM =
{ 0x4C,0x80,0xDC,0x4C,0x9C,0xDC,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, // 8000
0x60,0x60,0x60,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, // 8010
~~~
}
Code: Select all
/******************************************************************************
* copy 'gPascal' array to 64K RAM @ $8000..$DCB7 & vectors @ $FFFA..$FFFF *
* */
void loadImage() // ****************************************
{ uint16_t ndx = 0; // *
addr = 0x8000; // G-Pascal start address *
uReset(); // reset 6502 (synchronize uC to cpu) *
do // copy G-Pascal array to RAM *
{ wrRAM(pgm_read_word_near(gPascal+ndx));
addr++; ndx++; // *
} while(ndx < sizeof(gPascal)); // *
wrRAM(0xFFFA,lo(0xDC9C)); // NMI vector ($FFFA-$FFFB) = $DC9C *
wrRAM(0xFFFB,hi(0xDC9C)); // *
wrRAM(0xFFFC,lo(0xDC80)); // RES vector ($FFFC-$FFFD) = $DC80 *
wrRAM(0xFFFD,hi(0xDC80)); // *
wrRAM(0xFFFE,lo(0xC74E)); // IRQ vector ($FFFE-$FFFF) = $C74E *
wrRAM(0xFFFF,hi(0xC74E)); // *
} // ****************************************
The Emulator can also access the 65C02 peripherals like the VIA (or the SDcard connected to the VIA?). Silly example;
Code: Select all
/******************************************************************************
* simple VIA Test ~ toggle a Red/Green LED on VIA pins PA7 & PA6 (doesn't *
* require RAM or ROM, just the CPU, the VIA, the 74HC139, and the Nano). *
* */
#define PORT_B 0x6000
#define PORT_A 0x6001
#define DDIR_B 0x6002
#define DDIR_A 0x6003
void testVIA() // ****************************************
{ uReset(); // reset 6502 (synchronize uC to cpu)
run(0); // insert I/O into address space
wrRAM(DDIR_A,0b11111111); // PA7..PA0 outputs
while(1) //
{ uPush(0x4C); // jmp $1000 (avoid PC in I/O area)
uPush(lo(0x1000)); // "
uPush(hi(0x1000)); // "
wrRAM(PORT_A,0b01000001); // green
_delay_ms(500); // delay 500-mS
uPush(0x4C); // jmp $1000 (avoid PC in I/O area)
uPush(lo(0x1000)); // "
uPush(hi(0x1000)); // "
wrRAM(PORT_A,0b10000010); // red
_delay_ms(500); // delay 500-mS
} //
} // ****************************************
Re: Flash ROM idea - sanity check
Posted: Thu Sep 11, 2025 6:55 pm
by plasmo
If you can feed parallel 8-bit data directly to 6502 from your PC, like using a FT245R, then a microcontroller is not needed. Your PC acts as a ROM feeding instructions to 6502.
https://www.retrobrewcomputers.org/doku ... og65r2home
Also see this rather long discussion,
viewtopic.php?f=4&t=6841
Bill