PROCESSOR 6502
;-------------------------------------------------
;-------------DANI-I-SYSTEM-ROM-------------------
;-------------------------------------------------
;-------------EQUATES-----------------------------
VRAM: EQU $8000
VRAM_H: EQU $80
VRAM_L: EQU $00
VRAM_CMD: EQU VRAM + $F00
VRAM_CHARSLOC: EQU VRAM + $F10
VRAM_CHARSBUF: EQU VRAM + $F20
;-------------EO-EQUATES--------------------------
ORG $C000
RESET:
LDX #$FF ; Initialize the Stack Pointer
TXS ; Transfer X to Stack
SETUP_BLANKCHAR:
LDA #$00 ; Store Null in Accu
LDY #$00 ; Set Y to 00
LDX #$00 ; Set X to 00
LOOP_BLANKSTORE:
STA VRAM_CHARSBUF,X ; Store Accu into VRAM_CHARSBUF+X
INX
CPX #$08
BNE LOOP_BLANKSTORE
STA VRAM_CHARSLOC ; Set the Character Store Location
LDA #$01 ; Set the Character Store Command
STA VRAM_CMD
CHECK_CMDCOMPLETE:
LDX VRAM_CMD ; Keep Loading and Check VRAM_CMD to see if VGA picked up Character
CPX #$00
BNE CHECK_CMDCOMPLETE ; Keep Checking if it's not been set to 00
BLANKOUT_START:
LDA #$00 ; Set Accu to 0
LDX #$00 ; Set X Counter to 0
LDY #$00 ; Set Y Counter to 0
LDA #VRAM_L ; Load Accu to Low Byte of VRAM
STA $05 ; Store it in Zero Page 5
LDA #VRAM_H ; Load Accu to High Byte of VRAM
STA $06 ; Store it in Zero Page 6
LOOP_BLANKOUT:
LDA #$00 ; Set Accu To 0
STA ($05),Y ; Store it in VRAM + Y
CPY #$B0 ; Does Y eq B0 ?
BEQ CHECK_X ; it does? Got to Check_X
LOOP_CONTINUE:
CPY #$FF ; X is not 04 and Y is not B0 Is Y FF?
INY ; Increase Y
BNE LOOP_BLANKOUT ; It's not FF yet Go to LOOP_BLANKOUT
LOOP_INC_X: ; Y = FF
LDY #$00 ; Set Y back to 0
INX ; Add 1 to X
INC $06 ; Add 1 to Address 6
JMP LOOP_BLANKOUT ; Back to the LOOP_BLANKOUT
CHECK_X:
CPX #$04 ; Is X 04? Making this 2820?
BNE LOOP_CONTINUE
LOOP_DONE:
JMP BLANKOUT_START ; we hit 2820 - done
VECTORS:
ORG $FFFA ; 6502 Starts reading it's vectors here
.word LOOP_DONE ; NMI
.word RESET ; RESET
.word LOOP_DONE ; BRK
END
The problem is with the indirect addressing when "STA ($05),Y", it all works as expecting until Y = the High Byte Address, "06", when that happens 05 gets overwritten with the value of address 06 and then it continues to count as expected. If I change the ZP addresses it does the same with the new address's. For example when I had the addresses set to 10 and 11, whenever Y = 11 the value of 10 was overwritten with the value of 11 and then it continues to count as expected. When I run this code in a simulator it works fine. Any help in any direction would be huge, as this has brought my project to a halt for the time being.
Thanks!
Last edited by ChaseHQ85 on Tue Feb 21, 2017 9:22 pm, edited 1 time in total.
CPY #$FF ; X is not 04 and Y is not B0 Is Y FF?
INY ; Increase Y
INC $06
BNE LOOP_BLANKOUT ; It's not FF yet Go to LOOP_BLANKOUT
In an inner loop, you'd increment Y. You'd only increment your high byte if Y wrapped. But here, you're performing a comparison but doing nothing about it - probably you intend a branch here.
As it is, it looks like you always increment both Y and the high byte, which means your pointer is probably advancing much faster than you intend.
Perhaps it's just that the INC $06 is superfluous at this point?
Sorry that line of code is not in the working copy im using now. That was accidentally left in here from debugging and trying to see if there was a different method i should be using for increasing the deref address. I've changed it so it actually reflects what is happening. But as it stands im still having that same issue
CPY #$FF ; X is not 04 and Y is not B0 Is Y FF?
INY ; Increase Y
BNE LOOP_BLANKOUT ; It's not FF yet Go to LOOP_BLANKOUT
Better, but still a little fishy. The CPY will update the flags but so too will the INY. So really the BNE tests whether Y is zero.
It's part of the learning curve for 65xx assembly language. Many of the instructions update the flags! The chip is made that way for good reasons. But sometimes it catches people off guard.
Last edited by Dr Jefyll on Tue Feb 21, 2017 9:51 pm, edited 1 time in total.
Yes i know the code looks a little funky (as im brand new to 6502) but it is intended to check to see if its FF then roll it to 0 and branch back to beginning. The problem im having is not so much with that section of the code but when Y is equal to the High Byte Index of the Indirect Address. For some reason it sets the Low Byte to the same value of the High Byte at that point and im not really understanding why.
Here is an example
ZP 05 = 00
ZP 06 = 80
Y = 00
STA (05),Y = $8000
Y = 01
STA (05),Y = $8001
and etc...
Except when Y = 06 Then
STA (05),Y = $8080 ???
Then
Y = 07
STA (05),Y = $8087 ... continues on normally
I cannot for the life of me figure out why it does this. Even when i adjust the ZP indexes to some other numbers, when Y equals the High Byte Address it sets the Low Byte to that value.
It does seem very odd!
Are you running on hardware or an emulation? What assembler do you use?
One reason for tidying up oddities and inconsistencies is to make it easier to understand what's going on - even more important to those of us who are coming to the code cold.
(If you've previously programmed other micros you might have the wrong model of which operations affect flags. Not that this explains the gross misbehaviour.)
It does seem very odd!
Are you running on hardware or an emulation? What assembler do you use?
One reason for tidying up oddities and inconsistencies is to make it easier to understand what's going on - even more important to those of us who are coming to the code cold.
(If you've previously programmed other micros you might have the wrong model of which operations affect flags. Not that this explains the gross misbehaviour.)
You guys are really a welcoming community! I appreciate that. Im running on hardware that I have built. The assembler is DASM and ive tested the BIN in Symon and it seems to work normally there. The code writes to the Video RAM at located at $8000-$8FFF - It's a custom FPGA VGA controller i created. 8x8 Characters on a 320x240 resolution screen. $8F20-$8F27 is a buffer to write a character to that you want to store in the VGA controllers RAM, $8F10 is a byte to assign that character to a location, and $8F00 is a register where if you put 0x01 there then during the next HSYNC it will write that to it's character RAM and clear that flag after its complete. $8000-$84B0 is 1200 bytes (ROW,COL) to assign a character index to. (First time ive ever created a VGA Controller but it seems to work very well when i drive it off a uController). All this code is supposed to do is blank the screen - writes a blank character to index 0 and set the entire screen to that index. It works well until it comes into this nasty weirdness that ive described in previous posts.
Sorry for the long post but I figured i'd give you as much background as possible.
Do you have a logic analyser or some kind of monitor which is catching these odd writes?
Often the answer is some kind of shorted address lines or build error. Is that possible?
Yes, ive created a bus watching device. Basically it just breaks into the bus lines for data and address and shows whats on it on some 7 seg LEDs. I was thinking it was a short as well but it follows the High Byte around. Ive tested each of the lines and address decoding and it all checks out. I used a 555 timer and made a 50% duty cycle every second to watch the lines and it's the weirdest thing. Only on indirect ref do i see it.
Sure! I bought two from Mouser, you wouldn't think that it could be a bad batch though could it? Is that common. Im going to switch it out now. Be right back!
So, not only has it misread the high byte of the pointer, it's written back the wrong version.
Perhaps it could be an issue with your address decoding, chip select and write enable. There is a thing you have to do to make sure writes are safe, and not started when the addresses might still be changing. Have you checked the relevant part of Garth's primer? Can you share a sketch of your RAM control signals?