Dan's 6502 build, aka, The WOPR Jr.

Building your first 6502-based project? We'll help you get started here.
Post Reply
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by floobydust »

Dan Moos wrote:
Ok, that's kinda what I figured. I had wondered if the was fine other trick that I want privy to.

What's the best way to put my address in the pointer? Basically, say I have my pointer at $0000, and my message at some address in ROM. Do I have to put the high and low bytes of the address in one at a time?

I think that is the thing I'm most stuck on. How do I take a 16 bit address, and place that address in my pointer location?
Look at my code snippet above, PROMPTL and PROMPTH are consecutive page 0 memory locations that make up the 16-bit pointer. I would strongly urge you to start reading a programming manual for the 65(c)02 and get better acquainted with opcodes and addressing modes. That and reading through some existing code listings would aid your understanding of how to structure some of this stuff.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by GARTHWILSON »

The '02 only handles 8 bits at once, so yes, you'll need two operations, and you'll need an address variable, whether it's in ZP or not.

The 65816 can handle both bytes at once, and then also has more cool addressing modes to do stuff with it. You could even use a single instruction to push the address of the string onto the stack, and use the added stack addressing modes to more-efficiently handle it in the subroutine. Another possibility would be to have X (in 16-bit mode) point to the address itself and do an indirect X where X holds the address, by doing LDA 0000,X, (making sure you assemble an absolute, not ZP, instruction). Each INX gets you to the next byte of the string. You'll want the index registers in 16-bit mode and the accumulator in 8-bit. See what you have to look forward to? :D

The Liechty & Eyes programming manual (note the new link) is outstanding for explaining all this stuff really well.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by floobydust »

As Garth noted, the Liechty and Eyes manual is excellent. I still have my original hardcopy and a PDF version. I still reference it for instructions and addressing modes to this day. I guess I hinted to it without a link. Here's the current link from WDC:
http://wdc65xx.com/Programming-Manual/

You're can also download a copy of my CO2Monitor 1.0 source code. It's heavily commented so the code should be fairly easy to follow. viewtopic.php?f=2&t=3523#p41861
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Dan Moos »

I am absolutely reading books, including the Liechty and Eyes book mentioned. In fact I have a hardcopy of that one coming Monday day. It may seem like I'm not reading stuff, but I assure you I am. Things that may look obvious to you guys in these books aren't so much to folks who haven't been living this stuff for decades.

I don't come here first for the answers, but if I don't get what I need after a pass through the relevant sections of my books, I come here rather the belabor the issue. I think it's a fine strategy.

But don't don't worry, I'm reading. Honestly, I have yet to find a text who's authors are really gifted at exclaiming things. Most seen to spend pages over explaining the obvious, then spend one cryptic paragraph explaining the complicated. Stuff like spending pages on what an instruction is, but a terse paragraph on pre-indexed addressing.

Garth's stuff is ten times more readable than allot of these books. The info is in them, just often poorly exposed. Admittedly I've spent less time with Liechty and Eyes, but that will change when my hardcopy comes.

All this to say, have patience :D I promise I'm studying this stuff!
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Dan Moos »

Ok, I noticed a detail in Garth's example that I missed on my first reading.

I had never seen that you could use the "<" and ">" operators to access the LOW and HIGH bytes of and address separately. I tried it out in the Kowalski sim, and it works great!

My difficulty was never understanding indexed addressing. It was being unsure that I knew the most efficient way to do what I wanted. Those operators change everything.

A question about them. What is happening behind the scenes here? What does the assembler do when it sees this? Is it just a short hand for doing 8 bit shifts in a row, and the assembler puts the full deal in?
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Dan Moos »

Nevermind, its actually obvious when I look at the disassembly! I kinda forgot that the assembler would know at assemble time exactly what address I need to separate into its halves. Its just decoding my label. Dumb and obvious now that I actually think about it.

What did throw me for a loop at first was a whole bunch of strange instructions in my disassembly. Then it dawned on me that the disassembler wouldn't know data from instructions, so all my constants were displayed as instructions. I imagine a disassembler that also shows an ascii interpretation of the data would make it more obvious to the user what code was actually just strings.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Arlet »

Dan Moos wrote:
My notion is to write a byte to memory, read it back, and compare it to some value in the X or Y register. Maybe just use X as a counter, load the current count into the memory address under test, read it back into the accumulator, and compare it to the X register, and so on through memory.
A problem with this kind of test: suppose A0 to the RAM is disconnected, so writes to address 0 and 1 both go to the same place. If you test one byte at a time, you'll never notice.

A simple test I like is to use a pseudo random generator, fill the entire memory with random data, reset the seed, and read the entire ram back. Repeat with different seed until satisfied.
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by BigDumbDinosaur »

Dan Moos wrote:
Another dumb question. I am reading Garth's interrupt primer, specifically the section on RS232 usage, and have a question about how he reserved memory for the Rx buffer.

He uses a .DFS directive to set aside memory for the buffer.

Question 1: this is the same as the .DS directive that the Kowalski assembler uses, right?

Question 2: there doesn't seem to be any starting point in RAM mentioned. For instance, the buffer itself is set aside with:

Code: Select all

BUFFER: .DFS    $100 


Where specifically in RAM does this buffer reside? How do you tell it where?
The search tools are your friend. I posted the full set of Kowalski pseudo-ops several years ago.

The alternative to .DS is *=*+<size>, where <size> is the number of locations to reserve. There is also .RMB, but should not be used unless you want to reserve storage and initialize it to some assembly-time value.

The program counter is typically set with *=<address>.

Also see here for the operators recognized by the Kowalski assembler.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by BigDumbDinosaur »

Arlet wrote:
Dan Moos wrote:
My notion is to write a byte to memory, read it back, and compare it to some value in the X or Y register. Maybe just use X as a counter, load the current count into the memory address under test, read it back into the accumulator, and compare it to the X register, and so on through memory.
A problem with this kind of test: suppose A0 to the RAM is disconnected, so writes to address 0 and 1 both go to the same place. If you test one byte at a time, you'll never notice.

A simple test I like is to use a pseudo random generator, fill the entire memory with random data, reset the seed, and read the entire ram back. Repeat with different seed until satisfied.
The RAM test Dan wants is a RAM test, not a PCB test. :D
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by BigDumbDinosaur »

GARTHWILSON wrote:
Another possibility would be to have X (in 16-bit mode) point to the address itself and do an indirect X where X holds the address, by doing LDA 0000,X, (making sure you assemble an absolute, not ZP, instruction).
In 16 bit mode on a machine with no more than 64KB of RAM, LDA 0,X will work fine. Where absolute mode becomes necessary is if the current data bank is non-zero.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Arlet »

BigDumbDinosaur wrote:
The RAM test Dan wants is a RAM test, not a PCB test. :D
Problems on the board are much more likely than problems in the chip...
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by Dan Moos »

ok, still a little hung up on the .DS directive and its various brethren.

Does a directive like that have any use if your program is going in ROM?

I guess what still confuses me is, with my code in ROM, why would I even have to set aside any block of memory in RAM, if nothing goes anywhere in RAM that I don't specifically designate. So if I want $0200 to $02FF to be4 a buffer for instance, I could just not ever use it for anything else.

But If the program resides in RAM, i can see why it would be needed, because the code and data share address space, so the assembler would need to know where it couldn't put code.

Is that about it?

Also, I had read BDD's exposition of the Kowalski directives and operators. I didn't se mention of the use of the "<" and ">" operators being used that way. I did see the bit wise shift operators "<<" and "<<". The help is a dead link in the program too, which my searching seems reveal is due to an English version not existing. Is there a way to find the original language version, such that one could see if Google translate could make heads or tails of it? I'm really loving this software, and would like to know its details best as I can.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by GARTHWILSON »

Dan Moos wrote:
ok, still a little hung up on the .DS directive and its various brethren.

Does a directive like that have any use if your program is going in ROM?

I guess what still confuses me is, with my code in ROM, why would I even have to set aside any block of memory in RAM, if nothing goes anywhere in RAM that I don't specifically designate. So if I want $0200 to $02FF to be4 a buffer for instance, I could just not ever use it for anything else.

But If the program resides in RAM, i can see why it would be needed, because the code and data share address space, so the assembler would need to know where it couldn't put code.

Is that about it?
If everything lined up on neat boundaries and were never to change, you could assign by hand the addresses of variables and arrays. But if you commit to that, you'll probably find yourself needing to change something later on down the road, and then it will have been easier if you had let the assembler take care of the assignment of addresses of RAM-resident stuff. In the case of the RS-232 buffer, a page works out very conveniently. Most variables' sizes won't work out so conveniently; and if you try to manage the inventory of variables by hand, it will be harder to make changes later without resulting in unused spaces or the risk of one variable accidentally stepping on another one. My recommendation is to let the assembler do what it's good at.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
GaBuZoMeu
Posts: 660
Joined: 01 Mar 2017
Location: North-Germany

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by GaBuZoMeu »

Dan,

I think you haven't fully realized, that there is no operating system unless you wrote some. There is no second or third usage of an area of RAM you designate to one program - not because you did use it, but because there is no other program running!

It requires an operation system, a scheduler, a memory manager and more to get into the trouble you envisioned.

Take a C64 or an Apple: there is a ROM containing the reset vector and initial setup code. Then there is a small monitor, allowing to verify/change single memory contents. You can use the monitor to start manually say BASIC. Then BASIC is running - the monitor still resides in ROM but it is not used anymore (perhaps parts of it like character I/O, but then these are subroutines called by BASIC). Usually in these small machines there is just one program operating, having full control, no need to care about other programs.

To have a second program lurking in the background, say a printer spooler (back in that days a common background task) requires careful planning and special ways to set it up correctly. Usually the spooler was started, taking some of the memory (high end) for buffering, and sets a new "memory end" value in a location, that is referenced by BASIC during startup. This was the only protection from double use of that RAM. The spooler then initiates a timer that periodically interrupts any other program. The spooler checks the buffer do perhaps some printing and then reschedules (return from interrupt) to whatever program was actually running.

What I wish to describe is, that all and evrything that is going on on your machine, is under your control - or at least it should. ;)
For every possible situation you have to prepare your system with adeqaute software. It is (usually) no good idea, to terminate one program, leaving valuable data in RAM, and believe that this data is "later" intact - unless you write an operating system AND cooperative software. Obviously that isn't trivial.

So far OK ?
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Dan's 6502 build, aka, The WOPR Jr.

Post by BigDumbDinosaur »

Arlet wrote:
BigDumbDinosaur wrote:
The RAM test Dan wants is a RAM test, not a PCB test. :D
Problems on the board are much more likely than problems in the chip...
True that. However, that would be a construction issue, which would presumably be corrected early on in the project.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply