6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon Jul 01, 2024 1:51 am

All times are UTC




Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Feb 25, 2017 5:08 am 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
Hello everyone! My name is Craig, an avid electronics hobbyist. I'm brand new to the 6502 scene and have been working on the following project for the last 3-4 weeks. The DANI-I 6502 Microcomputer (named after my wife Danneille). Without further ado - here are the pictures with some explanations.

Attachment:
IMG_6764.JPG
IMG_6764.JPG [ 1.09 MiB | Viewed 1692 times ]

From left to right
Xilinx Spartan 3A - Used as the custom made VGA Controller - Called DANI-I VGA
Output is VGA @ 640x480 60Hz - but the pixel area is 320x240 or a 40x30 tile display of 8x8 tiles, with 16 sprites. 6bit Resistor DAC (64 Displayable colors) 2 Colors per 8x8 tile (for time being)
The the Right of that on bottom is 32Kb of Video RAM, it holds all the Tile and Sprite Data. Above that is the screen Index buffer and VGA command register which is 4k of Dual Port Ram. The Left port is accessed by the FPGA at 25mhz and Right side is accessed by the 6502 at 4mhz. During HSYNC optional commands can be sent to the VGA controller for storing or retrieving tile and sprite data, screen data can be accessed at any time.
In the middle is the address bus and data bus (I know im gonna get hate for doing this on a breadboard, but hey - it's what i had :) )
Next starting on the bottom is the main system SRAM Chip, 32Kb of it - above it is some address decoding and glue logic.
In the next column we have a reset circuit on top - it consists of a Hex Inverter and a 555 circuit for reset.
Below the Hex Inverter is the 6502! (So glad I went with this chip - it's been amazing) Below the 6502 is the ROM it's 32Kb but only 16Kb of it is accessible.
On the far right is nothing special yet... it's just glue logic for the additional IC's i will be adding this week, including the 6522.

Attachment:
IMG_6754.JPG
IMG_6754.JPG [ 1.14 MiB | Viewed 1692 times ]

This is a line debugger I created to watch the address and data lines to debug issues.

Attachment:
IMG_6765.JPG
IMG_6765.JPG [ 1 MiB | Viewed 1692 times ]

My homemade EEPROM programmer

And Finally - the thing that made everything worth it this weekend - the DANI-I 6502 first test of actual code!
Attachment:
IMG_6763.JPG
IMG_6763.JPG [ 759.01 KiB | Viewed 1692 times ]


The Memory map -
Code:
$0000 - $7FFF => SRAM    32k b0.xxxxxxxxxxxxxxx
$8000 - $8FFF => VRAM    04k b1000.xxxxxxxxxxxx
$9000 - $90FF => ACIA     1b b10010000.xxxxxxxx
$9100 - $91FF => VIA      1b b10010001.xxxxxxxx
$9200 - $92FF => PIA      1b b10010010.xxxxxxxx
$C000 - $FFFF => ROM     16k b11.xxxxxxxxxxxxxx


The initial ROM System Code -
Code:
;-------------------------------------------------
;-------------DANI-I-SYSTEM-ROM-------------------
;-------------------------------------------------

;-------------EQUATES-----------------------------
VRAM:            .SET $8000
VRAM_CMD:        .SET VRAM + $F00
VRAM_CHARSLOC:   .SET VRAM + $F10
VRAM_CHARSBUF:   .SET VRAM + $F20
CURSOR_LOC:      .SET $80            ; Cursor Location ZP: 40
;-------------EO-EQUATES--------------------------

    .ORG $C000
RESET:
    LDX #$FF            ; Initialize the Stack Pointer
    TXS                 ; Transfer X to Stack
START:
    JSR SYS_INIT        ; Initialize the System
    LDA #<S_HelloWorld
    STA $10
    LDA #>S_HelloWorld
    STA $11
    JSR DVGA_PUTS       ; Print out String
HALT:
    JMP HALT       ; Done: "halt" in an infinite loop

;----------SUB-ROUTINES---------------------------

;----------System Initialization -----------------
;-- Parameters - VOID
;-------------------------------------------------
SYS_INIT:
    LDX #<[CHAR_ROM+$400-8]    ; Store Low Byte of Char ROM (Last Character) in ZP 05
    STX $40
    LDX #>[CHAR_ROM+$400-8]    ; Store High Byte of Char ROM (Last Character) in ZP 06
    STX $41
    LDX #$7F                 ; Set X counter to 127 (128 total)
.loop
    STX $20                 ; Set Location of this character
    LDA $40                 ; Set Address of Char Rom in ZP 40
    STA $10
    LDA $41
    STA $11
    JSR DVGA_STORECHAR      ; Put Address of Character in ZP 10 and Location you want it stored in ZP 20
    LDA #$08                ; Put 8 bytes of dec
    STA $10                 ; Store it in param (ZP10)
    JSR MEM_SAFE_ZP40_DEC
    DEX                     ; deduct 1 from the location
    BPL .loop               ; loop until we hit go through 0 to FF
    JSR DVGA_BLANKSCREEN    ; Blank the Screen
    RTS
   
;----------Safe Memory Decrement -----------------
;-- Parameters - ZP10 = Amount to Dec ZP 40 by
;-------------------------------------------------
MEM_SAFE_ZP40_DEC:
    PHA                      ; Store A
    TXA              ;
    PHA              ; Push X to Stack
    LDX $10                  ; Get the amount we want to dec by
.loop
    DEC $40                  ; Deduct from Memaddress 40
    LDA $40                  ; Test A
    CMP #$FF
    BEQ .deduct41            ; If we hit FF, make sure we deduct from 41
.cont
    DEX              ; Decrease X Counter
    BNE .loop                ; Loop if we arent at 0 yet
    PLA                      ; Restore X
    TAX
    PLA                      ; Restore A
    RTS              ; Return from Sub
.deduct41
    DEC $41           ; Deduct from High Byte
    JMP .cont           ; Go Back

;----------DVGA Store Character ------------------
;-- Parameters - ZP10 = Address of Character
;-- Paramaters - ZP20 = Location that you want to store charater in
;-------------------------------------------------
DVGA_STORECHAR:              ;-- ptr to Character in ZP 10, stored in LDA, Location is in ZP 20
    PHA              ; Push A To Stack
    TYA
    PHA              ; Push Y To Stack
    LDY #$07                 ; Set up counter - put 7
.loop:                       ; Start of Loop
    LDA ($10),Y              ; Get StoreChar Byte
    STA VRAM_CHARSBUF,Y      ; Store it in VRAM
    DEY                      ; Decrement Y
    BPL .loop                ; Continue to loop until it wraps
    LDA $20                  ; Load location value
    STA VRAM_CHARSLOC        ; Store it in Vram Char location
    LDA #$01                 ; Set Store Command
    STA VRAM_CMD             ; in the VGA command location
.chkcmd:
;    LDA VRAM_CMD             ; Check to see if it was loaded in
;    BNE .chkcmd              ; It was? Okay were good
    PLA
    TAY              ; Restore Y
    PLA             ; Restore A
    RTS                      ; Return from subroutine
   
;----------DVGA Blank Screen ---------------------
;-- Parameters - VOID
;-------------------------------------------------
DVGA_BLANKSCREEN:
    LDA #<VRAM               ; Load Low Byte of VRAM address
    STA $40                  ; Store it in Zero Page 40
    LDY #$B0                 ; Last page + 1 only partially filled
    LDA #$00                 ; Set Accu To 0 (fill byte)
    LDX #>VRAM+4             ; Init X to last VRAM page number
.loop_outer:
    STX $41               ; Store it in Zero Page 41
.loop_inner:
    DEY                     ; (filling high to low is more efficient)
    STA ($40),Y             ; Store the fill byte
    BNE .loop_inner         ; ... down to the bottom of the page
    DEX                       ; Prepare to fill next-lower page
    CPX #>VRAM               ; Is X < VRAM_H?
    BCS .loop_outer         ; No: fill the next page
    LDA #<VRAM               ; Set Cursor Location to 0
    STA CURSOR_LOC           ; Store it into Cursor Location
    LDA #>VRAM
    STA CURSOR_LOC+1
    RTS              ; Return from Subroutine

;---------DVGA-Put-String--------------------------
;-- Parameters - ZP10 - Ptr to String to Put on Scr
;-- Desc: Puts String on Screen at Cursor Location
;--------------------------------------------------
DVGA_PUTS:
    TYA                       ; Save Y
    PHA                       ; Push Y on stack
    TXA                       ; Save X
    PHA                       ; Push X on Stack
    LDY #$00                  ; Set Y To Zero
.loop
    LDA ($10),Y               ; Load Byte of String
    BEQ .stringDone           ; If this is a NULL character We are done with string
    STA (CURSOR_LOC)          ; Store this character into Cursor Location
    INC CURSOR_LOC            ; Increase Cursor Location
    BMI .increaseCursorH
    LDA CURSOR_LOC
    CMP #$B0
    BEQ .checkCursor          ; Check to see if we are at 1200
.continueLoop
    INY                       ; Increase Y
    BMI .stringDone           ; Y Overflowed to 00 - String is over 256 Characers, Exit
    JMP .loop
.increaseCursorH
    INC CURSOR_LOC+1
    JMP .continueLoop
.checkCursor
    LDA CURSOR_LOC+1
    CMP #$84
    BNE .continueLoop
    LDA #$80
    STA CURSOR_LOC+1
    LDA #$00
    STA CURSOR_LOC
    JMP .loop
.stringDone
    PLA                       ; Grab X From Stack
    TAX                       ; Restore X
    PLA                       ; Grab Y from Stack
    TAY                       ; Restore Y
    RTS

;--------------------------------------------------
;---------Static STRINGS---------------------------
;--------------------------------------------------

S_HelloWorld:   .db "Hello World!", $00

;--------------------------------------------------
;---------BUILT IN ROM CHARS-----------------------
;--------------------------------------------------
CHAR_ROM:                    ; ASCII encoded - 128 Chars
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   
     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01001001
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01110111
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00100010
     .BYTE @01110111
     .BYTE @01111111
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00101010
     .BYTE @01111111
     .BYTE @00101010
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00000000

     .BYTE @11111111
     .BYTE @11111111
     .BYTE @11100011
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11100011
     .BYTE @11111111

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00011100
     .BYTE @00000000

; I removed the rest of the Characters to shorten post - you get the idea

;---------VECTORS----------------------------------
VECTORS:
    .ORG $FFFA           ; 6502 Starts reading its vectors here
    .word HALT     ; NMI
    .word RESET    ; RESET
    .word HALT     ; BRK
   
   .END


This is the first time ive written 6502 code or built such a project - but it has been absolutely amazing so far. Let me know your thoughts! I will continue to post as it evolves!


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 5:09 am 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
And of course all the pictures are upside down... :evil:


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 8:58 am 
Offline
User avatar

Joined: Sat Dec 07, 2013 4:32 pm
Posts: 246
Location: The Kettle Moraine
Not here, they're not.


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 12:09 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
ChaseHQ85 wrote:
And of course all the pictures are upside down... :evil:


It seems to depend on the browser. Edge displays both preview and magnified image upside down. In Firefox only the preview is upside down and the magnified image is correctly oriented.

EXIF Orientation should be top left. There is no EXIF with the preview, so it cannot be corrected.


Attachments:
EXIF.png
EXIF.png [ 31.84 KiB | Viewed 1667 times ]

_________________
6502 sources on GitHub: https://github.com/Klaus2m5
Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 4:05 pm 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
The pics work well in chrome as well. Hey Mike B, or anyone can I get a code review pretty please? :mrgreen: it's my first real attempt at writing 6502 code id like to keep.


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 4:19 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1938
Location: Sacramento, CA, USA
I have to go to work right now, but I'll try to take a peek at your source this weekend and give you a friendly critique.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 8:57 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8460
Location: Southern California
Welcome.

I don't know if this is a bit premature, but I'd like to nudge you to look into macros as soon as you're ready. Your first loop there for example,
Code:
SYS_INIT:
    LDX #<[CHAR_ROM+$400-8]    ; Store Low Byte of Char ROM (Last Character) in ZP 05
    STX $40
    LDX #>[CHAR_ROM+$400-8]    ; Store High Byte of Char ROM (Last Character) in ZP 06
    STX $41
    LDX #$7F                 ; Set X counter to 127 (128 total)
.loop
    STX $20                 ; Set Location of this character
    LDA $40                 ; Set Address of Char Rom in ZP 40
    STA $10
    LDA $41
    STA $11
    JSR DVGA_STORECHAR      ; Put Address of Character in ZP 10 and Location you want it stored in ZP 20
    LDA #$08                ; Put 8 bytes of dec
    STA $10                 ; Store it in param (ZP10)
    JSR MEM_SAFE_ZP40_DEC
    DEX                     ; deduct 1 from the location
    BPL .loop               ; loop until we hit go through 0 to FF
    JSR DVGA_BLANKSCREEN    ; Blank the Screen
    RTS


can be shortened to:
Code:
SYS_INIT:  PUT2  CHAR_ROM+$400-8, INTO, $40  ; The PUT2 macro uses A instead of X; but you re-init A and X below anyway.
           FOR_X  $7F, DOWN_TO, NEG_NRs      ; Set X counter to 127 (128 total, dropping through when X dec's to $FF)
               STX   $20                     ; Set Location of this character
               COPY2 $40, TO, $10            ; Set Address of Char Rom in ZP 40
               JSR   DVGA_STORECHAR          ; Put addr of Char in ZP 10 and Location you want it stored in ZP 20
               PUT   8, INTO, $10            ; Put 8 bytes of dec and Store it in param (ZP10)
               JSR   MEM_SAFE_ZP40_DEC
           NEXT_X                            ; NEXT_X assembles DEX, BPL because that's what FOR_X and its parameters dictated.
           JMP  DVGA_BLANKSCREEN             ; Blank the Screen (Combine JSR, RTS, saving one byte and 9 clocks.

and this last version brings a slight improvement in both performance and memory. The macros offload some of your work to the assembler, work that you were doing by hand before. You're still in total control since you write the macros (or adapt others' macros) and you know what they do; but you don't have to look at the mundane innards every time anymore. You become more productive, and since you can see what you're doing better, you get fewer bugs to fix.

The first small change is that "PUT2" uses LDA# instead of LDX# which I figured is no problem because you re-initialize both A and X right below anyway, without re-using what's in either of them. If you really had to have it use X, you could write another version of PUT2, or re-write the existing one to use a parameter telling which register to use. The other change is that I removed your RTS by replacing your last JSR with JMP, using the RTS at the end of subroutine DVGA_BLANKSCREEN to return to the right place. The only time you can't do that is when passing parameters on the hardware stack, since the routines need a consistent number of return addresses on the stack above the data so they can find the data where it's expected. (Passing parameters on the hardware stack (or even on a virtual stack) can remove the need for a lot of variables though. This is covered in my stack treatise, especially section 6.)

If you don't feel ready for the macros yet, no problem. Just keep it in the back of your mind for later.

If you have a 65c02, you can shorten things up further. A couple of key things that pop out at me right away in your code is that LDA#0, STA can be replaced with just STZ (STore Zero) which is shorter and does not disturb any registers; and the 65c02 can push and pull the index registers without going through A. I have a list of the differences between the CMOS and NMOS 6502 here.

If your assembler can handle lots of bytes on each .BYTE line, you can shorten up your source code a lot there, too. The part at the end becomes:
Code:
CHAR_ROM:                    ; ASCII encoded - 128 Chars
     .BYTE  @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000
     .BYTE  @00000000, @00111110, @01000001, @01010101, @01000001, @01010101, @01001001, @00111110
     .BYTE  @00000000, @00111110, @01111111, @01101011, @01111111, @01101011, @01110111, @00111110
     .BYTE  @00000000, @00100010, @01110111, @01111111, @01111111, @00111110, @00011100, @00001000
     .BYTE  @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00011100, @00001000
     .BYTE  @00000000, @00001000, @00011100, @00101010, @01111111, @00101010, @00001000, @00011100
     .BYTE  @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00001000, @00011100
     .BYTE  @00000000, @00000000, @00011100, @00111110, @00111110, @00111110, @00011100, @00000000
     .BYTE  @11111111, @11111111, @11100011, @11000001, @11000001, @11000001, @11100011, @11111111
     .BYTE  @00000000, @00000000, @00011100, @00100010, @00100010, @00100010, @00011100, @00000000

instead of the 90 or so lines you had.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 10:23 pm 
Offline

Joined: Tue Nov 01, 2016 12:28 pm
Posts: 59
you made an eprom programmer with a pickit3?


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 6:52 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10837
Location: England
Great project Craig - thanks for posting about it!


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 10:41 pm 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 136
Here's a version with assorted changes - pick & choose the parts you like.

Code:
;-------------------------------------------------
;-------------DANI-I-SYSTEM-ROM-------------------
;-------------------------------------------------

;-------------Memory locations-----------------------------

Temp1:      .SET $10   ;unpreserved scratch
Temp2:      .set $12   ;unpreserved scratch

DVGA_Cursor:   .SET $80   ;Cursor Location - ptr to VRAM



               ;$0000 - $7FFF => SRAM    32k b0.xxxxxxxxxxxxxxx
VRAM:            .SET $8000      ;$8000 - $8FFF => VRAM    04k b1000.xxxxxxxxxxxx
VRAM_CMD:        .SET VRAM + $F00
VRAM_CHARSLOC:   .SET VRAM + $F10
VRAM_CHARSBUF:   .SET VRAM + $F20

               ;$9000 - $90FF => ACIA     1b b10010000.xxxxxxxx
               ;$9100 - $91FF => VIA      1b b10010001.xxxxxxxx
               ;$9200 - $92FF => PIA      1b b10010010.xxxxxxxx
               ;$C000 - $FFFF => ROM     16k b11.xxxxxxxxxxxxxx


;-------------ROM--------------------------

   .ORG $C000
RESET:
   LDX #$FF      ; Initialize the Stack Pointer
   TXS
   CLD

   JSR DVGA_Init      ; Initialize DVGA
   LDA #<S_HelloWorld   ; Print out String on DVGA
   LDY #>S_HelloWorld
   JSR DVGA_Put_String
.HALT:   JMP .HALT      ; Done: "halt" in an infinite loop


S_HelloWorld:   .db "Hello World!", 0


;============== DVGA ======================================

DVGA_Put_Char: ;---------------------------------------------
; Puts char on Screen at Cursor Location
; Parameters - A = char to Put on Scr
; Registers X & Y preserved, A destroyed, preserves Temp1

;   cmp #$20      ; ASCII control char?
;   bcc .ctl
   STA (DVGA_Cursor)   ; Store the character
   INC 0+DVGA_Cursor   ; Increment DVGA_Cursor
   BNE .inc9
   INC 1+DVGA_Cursor
.inc9
   LDA 0+DVGA_Cursor   ; if DVGA_Cursor = VRAM+1200
   CMP #>[VRAM+1200]
   BNE .cmp9
   LDA 1+DVGA_Cursor
   CMP #<[VRAM+1200]
   BNE .cmp9
   LDA #>VRAM      ;    DVGA_Cursor = VRAM
   STA 0+DVGA_Cursor
   LDA #<VRAM
   STA 1+DVGA_Cursor
.cmp9

.cur   ; display cursor???

   RTS

;.ctl   cmp #$0d      ; carriage return?
;   beq .cr
;   cmp #$0a      ; line feed?
;   beq .lf
;   cmp #$08      ; backspace?
;   beq .bs
;   rts

;.cr   ;move cursor to begin of current line???
;   bra .cur

;.lf   ;move cursor to next line???
;   bra .cur

;.bs   ;move cursor back 1 char???
;   bra .cur


DVGA_Put_String: ;-------------------------------------------
; Puts String on Screen at Cursor Location
; Parameters - YA - Ptr to String to Put on Scr
; Registers X preserved, A & Y destroyed, Temp1 set to YA

   STA 0+Temp1
       STY 1+Temp1

   LDY #0
.loop
   LDA (Temp1),Y      ; Load Byte of String
   BEQ .Done      ; If this is a NULL character We are done with string
   JSR DVGA_Put_Char   ; type it
   INY
   BNE .loop      ; if Y not Overflowed to 0 then loop
.Done
   RTS


DVGA_STORECHAR: ;---------------------------------
; Parameters - Y & A = Address of Character
; Paramaters - X= Location that you want to store charater in
; Registers X preserved, A & Y destroyed, Temp1 set to YA

   STA 0+Temp1
   STY 1+Temp1

   LDY #7         ; for(X=7; X>=0; X--)
.loop:
   LDA (Temp1),Y      ;   move char pattern byte
   STA VRAM_CHARSBUF,Y
   DEY         ;   next X
   BPL .loop

   STX VRAM_CHARSLOC   ; Set Vram Char location
   LDA #$01      ; Start Store command
   STA VRAM_CMD
.chkcmd:
;   LDA VRAM_CMD      ; Check to see if it was loaded in
;   BNE .chkcmd      ; It was? Okay were good
   RTS


DVGA_Init: ;---------------------------------------
; Parameters - VOID
; All registers destroyed, Temp1 destroyed

   ; load character generator patterns
   LDA #<[CHAR_ROM+$400-8]   ; YA=&CHAR_ROM[127]
   LDY #>[CHAR_ROM+$400-8]
   LDX #$7F      ; for(X=127; x>=0; x--)
.loop
   JSR DVGA_STORECHAR   ;   load the char pattern from (YA) into DVGA at X

   LDY 1+Temp1      ;   YA=Temp1-8
   LDA 0+Temp1
   SEC
   SBC #8
   BCS .sub9
   DEY
.sub9
   DEX         ;   next X
   BPL .loop

;   BRA DVGA_BlankScreen   ; Blank the Screen & RTS


DVGA_BlankScreen: ;---------------------------------
; Clear VRAM
; Parameters - none
; Register X perserved, A & Y destroyed

   lda #0         ; fill value
   ldy #240      ; 240 is 1200/5
.loop
   sta 0*240+VRAM-1,Y
   sta 1*240+VRAM-1,Y
   sta 2*240+VRAM-1,Y
   sta 3*240+VRAM-1,Y
   sta 4*240+VRAM-1,Y
   dey
   bne .loop

;   bra DVGA_Home      ; Home the cursor & RTS


DVGA_Home: ;------------------------------------------
; Move the cursor to the start of VRAM
; Parameters - none
   LDA #<VRAM      ; DVGA_Cursor = VRAM
   STA 0+DVGA_Cursor
   LDA #>VRAM
   STA 1+DVGA_Cursor

   RTS
   

;--------------------------------------------------
;---------BUILT IN ROM CHARS-----------------------
;--------------------------------------------------
CHAR_ROM:                    ; ASCII encoded - 128 Chars
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   
     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01001001
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01110111
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00100010
     .BYTE @01110111
     .BYTE @01111111
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00101010
     .BYTE @01111111
     .BYTE @00101010
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00000000

     .BYTE @11111111
     .BYTE @11111111
     .BYTE @11100011
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11100011
     .BYTE @11111111

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00011100
     .BYTE @00000000

; I removed the rest of the Characters to shorten post - you get the idea

;---------VECTORS----------------------------------
VECTORS:
    .ORG $FFFA           ; 6502 Starts reading its vectors here
    .word HALT     ; NMI
    .word RESET    ; RESET
    .word HALT     ; BRK
   
   .END


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 3:25 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8236
Location: Midwestern USA
leepivonka wrote:
Here's a version with assorted changes - pick & choose the parts you like.

Which assembler are you using?

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 5:03 pm 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
Wow I really appreciate all the suggestions, examples and rewrites leading me to faster and more efficient code!

Thanks, this has been great!


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 5:03 pm 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
BigDumbDinosaur wrote:
leepivonka wrote:
Here's a version with assorted changes - pick & choose the parts you like.

Which assembler are you using?


Yes... Which assembler is this for?

Thanks!


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 5:05 pm 
Offline

Joined: Tue Feb 21, 2017 8:32 pm
Posts: 38
EugeneNine wrote:
you made an eprom programmer with a pickit3?


Yes but im sure it's not what you think. I use a PIC18f with 64k of programming memory. So i turn the ROM in to a C style const in a rom.h header and have the uController program the ROM. I use the debugging feature of the PICKit3 to ensure that all the bytes are checked and verified.


Top
 Profile  
Reply with quote  
PostPosted: Tue Feb 28, 2017 7:10 am 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 136
Quote:
Which assembler are you using?


I was trying to match the syntax of your original post.
For other projects I've been using CA65 from http://cc65.github.io/cc65/ - it supports several 6502 variants and the 65816 too.
If you haven't already looked at the 65816, it's interesting. Its a 6502 + more instructions + more addressing modes + 16bit operations + 24bit addresses.

Here's the result of modifying it some more & assembling with CA65:
Code:
ca65 V2.15
Main file   : dani_65c02.txt
Current file: dani_65c02.txt

000000r 1               ;-------------------------------------------------
000000r 1               ;-------------DANI-I-SYSTEM-ROM-------------------
000000r 1               ;-------------------------------------------------
000000r 1               
000000r 1                  .list on
000000r 1                  .listbytes unlimited
000000r 1                  .pc02   ;select 65c02 CPU - I assume you do have this CPU
000000r 1               
000000r 1               ;-------------Memory locations-----------------------------
000000r 1                  .org 0 ; direct page
000000  1  xx xx        Temp1:   .res 2   ;unpreserved scratch
000002  1               ;Temp2:   .res 2   ;unpreserved scratch
000002  1  xx xx        DVGA_Cursor: .res 2   ;Cursor Location - ptr to VRAM
000004  1               
000004  1               
000004  1               DVGA_DimX = 40   ;X display dimension
000004  1               DVGA_DimY = 30   ;Y display dimension
000004  1               
000004  1                           ;$0000 - $7FFF => SRAM   32k b0.xxxxxxxxxxxxxxx
000004  1               VRAM      = $8000      ;$8000 - $8FFF => VRAM  04k b1000.xxxxxxxxxxxx
000004  1               VRAM_E      = DVGA_DimX*DVGA_DimY + VRAM ; end of display chars
000004  1               VRAM_CMD   = VRAM + $F00
000004  1               VRAM_CHARSLOC   = VRAM + $F10
000004  1               VRAM_CHARSBUF   = VRAM + $F20
000004  1               
000004  1               ACIA1      = $9000      ;$9000 - $90FF => ACIA    2b b10010000.xxxxxxxx
000004  1               VIA1      = $9100      ;$9100 - $91FF => VIA   16b b10010001.xxxxxxxx
000004  1               PIA1      = $9200      ;$9200 - $92FF => PIA    4b b10010010.xxxxxxxx
000004  1                  .org $c000      ;$C000 - $FFFF => ROM   16k b11.xxxxxxxxxxxxxx
00C000  1               
00C000  1               RESET:
00C000  1  A2 FF           LDX #$FF      ; Initialize the Stack Pointer
00C002  1  9A              TXS
00C003  1  D8              CLD
00C004  1               
00C004  1  20 AC C0        JSR DVGA_Init      ; Initialize DVGA
00C007  1  A9 10           LDA #<S_HelloWorld   ; Print string on DVGA
00C009  1  A0 C0           LDY #>S_HelloWorld
00C00B  1  20 84 C0        JSR DVGA_Put_String
00C00E  1  80 FE        HALT:   bra HALT      ; "halt" in an infinite loop
00C010  1               
00C010  1               
00C010  1  48 65 6C 6C  S_HelloWorld: .byte "Hello World!", 0
00C014  1  6F 20 57 6F 
00C018  1  72 6C 64 21 
00C01C  1  00           
00C01D  1               
00C01D  1               
00C01D  1               ;============== DVGA ======================================
00C01D  1               
00C01D  1               DVGA_Put_Char: ;---------------------------------------------
00C01D  1               ; Puts char on Screen at Cursor Location
00C01D  1               ; Parameters - A = char to Put on Scr
00C01D  1               ; Registers X & Y preserved, A destroyed, preserves Temp1
00C01D  1               
00C01D  1  5A              phy         ;save callers Y
00C01E  1  A4 03           ldy 1+DVGA_Cursor
00C020  1  C9 20           cmp #$20      ; ASCII control char?
00C022  1  90 20           bcc @ctl
00C024  1  92 02           sta (DVGA_Cursor)   ; Store the character
00C026  1  A5 02           lda 0+DVGA_Cursor   ;YA=DVGA_Cursor
00C028  1  1A              ina         ;YA+=1
00C029  1  D0 01           bne @inc9
00C02B  1  C8              iny
00C02C  1               @inc9:
00C02C  1  C0 84        @wrap:   cpy #>VRAM_E      ; if(YA>=VRAM_E)
00C02E  1  90 0E           bcc @cur
00C030  1  D0 04           bne @sub
00C032  1  C9 B0           cmp #<VRAM_E
00C034  1  90 08           bcc @cur
00C036  1  E9 B0        @sub:   sbc #<(DVGA_DimX*DVGA_DimY) ;   YA-=DVGA_DimX*DVGA*DimY
00C038  1  48              pha
00C039  1  98              tya
00C03A  1  E9 04           sbc #>(DVGA_DimX*DVGA_DimY)
00C03C  1  A8              tay
00C03D  1  68              pla
00C03E  1               
00C03E  1  85 02        @cur:   sta 0+DVGA_Cursor   ;DVGA_Cursor=YA
00C040  1  84 03           sty 1+DVGA_Cursor
00C042  1               
00C042  1                  ; display cursor???
00C042  1               
00C042  1  7A              ply         ;restore Y
00C043  1  60              rts
00C044  1               
00C044  1  C9 0D        @ctl:   cmp #$0d      ; carriage return?
00C046  1  F0 0A           beq @cr
00C048  1  C9 0A           cmp #$0a      ; line feed?
00C04A  1  F0 1E           beq @lf
00C04C  1  C9 08           cmp #$08      ; backspace?
00C04E  1  F0 24           beq @bs
00C050  1  80 EC           bra @cur
00C052  1               
00C052  1               @cr:   ;move cursor to begin of current line
00C052  1  A9 B0           lda #<VRAM_E      ;YA=VRAM_E
00C054  1  A0 84           ldy #>VRAM_E
00C056  1               @cr2:            ;do
00C056  1  38              sec         ;  YA-=DVGA_DimX
00C057  1  E9 28           sbc #DVGA_DimX
00C059  1  B0 01           bcs @cr3
00C05B  1  88              dey
00C05C  1               @cr3:
00C05C  1  C4 03           cpy 1+DVGA_Cursor   ;  while(YA>DVGA_Cursor)
00C05E  1  90 DE           bcc @cur
00C060  1  D0 F4           bne @cr2
00C062  1  C5 02           cmp 0+DVGA_Cursor
00C064  1  90 D8           bcc @cur
00C066  1  D0 EE           bne @cr2
00C068  1  80 D4           bra @cur
00C06A  1               
00C06A  1               @lf:   ;move cursor to next line
00C06A  1  A5 02           lda 0+DVGA_Cursor   ;YA=DVGA_Cursor
00C06C  1  18              clc         ;YA+=DVGA_DimX
00C06D  1  69 28           adc #DVGA_DimX
00C06F  1  90 01           bcc @lf1
00C071  1  C8              iny
00C072  1               @lf1:
00C072  1  80 B8           bra @wrap
00C074  1               
00C074  1               @bs:   ;move cursor back 1 char
00C074  1  A5 02           lda 0+DVGA_Cursor   ;YA=DVGA_Cursor
00C076  1  D0 01           bne @bs1      ;YA-=1
00C078  1  88              dey
00C079  1  3A           @bs1:   dea
00C07A  1  C0 80           cpy #>VRAM      ;if(YA<VRAM)
00C07C  1  B0 C0           bcs @cur
00C07E  1  A9 AF           lda #<(VRAM_E-1)   ;  YA=VRAM_E-1
00C080  1  A0 84           ldy #>(VRAM_E-1)
00C082  1  80 BA           bra @cur
00C084  1               
00C084  1               
00C084  1               DVGA_Put_String: ;-------------------------------------------
00C084  1               ; Puts String on Screen at Cursor Location
00C084  1               ; Parameters - YA - Ptr to String to Put on Scr
00C084  1               ; Registers X preserved, A & Y destroyed, Temp1 set to YA
00C084  1               
00C084  1  85 00           STA 0+Temp1
00C086  1  84 01           STY 1+Temp1
00C088  1               
00C088  1  A0 00           LDY #0
00C08A  1               @loop:
00C08A  1  B1 00           LDA (Temp1),Y      ; Load Byte of String
00C08C  1  F0 06           BEQ @Done      ; If this is a NULL character We are done with string
00C08E  1  20 1D C0        JSR DVGA_Put_Char   ; type it
00C091  1  C8              INY
00C092  1  D0 F6           BNE @loop      ; if Y not Overflowed to 0 then loop
00C094  1               @Done:
00C094  1  60              RTS
00C095  1               
00C095  1               
00C095  1               DVGA_STORECHAR: ;---------------------------------------------
00C095  1               ; Parameters - Y & A = Address of Character
00C095  1               ; Parameters - X= Location that you want to store character in
00C095  1               ; Registers X preserved, A & Y destroyed, Temp1 set to YA
00C095  1               
00C095  1  85 00           STA 0+Temp1
00C097  1  84 01           STY 1+Temp1
00C099  1               
00C099  1  A0 07           LDY #7         ; for(X=7; X>=0; X--)
00C09B  1               @loop:
00C09B  1  B1 00           LDA (Temp1),Y      ; move char pattern byte
00C09D  1  99 20 8F        STA VRAM_CHARSBUF,Y
00C0A0  1  88              DEY         ; next X
00C0A1  1  10 F8           BPL @loop
00C0A3  1               
00C0A3  1  8E 10 8F        STX VRAM_CHARSLOC   ; Set Vram Char location
00C0A6  1  A9 01           LDA #$01      ; Start Store command
00C0A8  1  8D 00 8F        STA VRAM_CMD
00C0AB  1               @chkcmd:
00C0AB  1               ;   LDA VRAM_CMD      ; Check to see if it was loaded in
00C0AB  1               ;   BNE @chkcmd      ; It was? Okay were good
00C0AB  1  60              RTS
00C0AC  1               
00C0AC  1               
00C0AC  1               DVGA_Init: ;---------------------------------------
00C0AC  1               ; Parameters - VOID
00C0AC  1               ; All registers destroyed, Temp1 destroyed
00C0AC  1               
00C0AC  1               ; load character generator patterns
00C0AC  1  A9 D9           LDA #<(CHAR_ROM+$400-8)   ; YA=&CHAR_ROM[127]
00C0AE  1  A0 C4           LDY #>(CHAR_ROM+$400-8)
00C0B0  1  A2 7F           LDX #$7F      ; for(X=127; x>=0; x--)
00C0B2  1               @loop:
00C0B2  1  20 95 C0        JSR DVGA_STORECHAR   ;load the char pattern from (YA) into DVGA at X
00C0B5  1               
00C0B5  1  A4 01           LDY 1+Temp1      ;YA=Temp1-8
00C0B7  1  A5 00           LDA 0+Temp1
00C0B9  1  38              SEC
00C0BA  1  E9 08           SBC #8
00C0BC  1  B0 01           BCS @sub9
00C0BE  1  88              DEY
00C0BF  1               @sub9:
00C0BF  1  CA              DEX         ;  next X
00C0C0  1  10 F0           BPL @loop
00C0C2  1               
00C0C2  1               ;   BRA DVGA_BlankScreen   ; Blank the Screen & RTS
00C0C2  1               
00C0C2  1               
00C0C2  1               DVGA_BlankScreen: ;---------------------------------
00C0C2  1               ; Clear VRAM
00C0C2  1               ; Parameters - none
00C0C2  1               ; Register X preserved, A & Y destroyed
00C0C2  1               
00C0C2  1                  .assert DVGA_DimX*DVGA_DimY=1200, error, "Assumes 1200 bytes"
00C0C2  1  A9 00           lda #0      ; fill value
00C0C4  1  A0 F0           ldy #240   ; 240 is 1200/5
00C0C6  1               @loop:
00C0C6  1  99 FF 7F        sta 0*240+VRAM-1,Y
00C0C9  1  99 EF 80        sta 1*240+VRAM-1,Y
00C0CC  1  99 DF 81        sta 2*240+VRAM-1,Y
00C0CF  1  99 CF 82        sta 3*240+VRAM-1,Y
00C0D2  1  99 BF 83        sta 4*240+VRAM-1,Y
00C0D5  1  88              dey
00C0D6  1  D0 EE           bne @loop
00C0D8  1               
00C0D8  1               ;   bra DVGA_Home   ; Home the cursor & RTS
00C0D8  1               
00C0D8  1               
00C0D8  1               DVGA_Home: ;------------------------------------------
00C0D8  1               ; Move the cursor to the start of VRAM
00C0D8  1               ; Parameters - none
00C0D8  1  A9 00           LDA #<VRAM   ; DVGA_Cursor = VRAM
00C0DA  1  85 02           STA 0+DVGA_Cursor
00C0DC  1  A9 80           LDA #>VRAM
00C0DE  1  85 03           STA 1+DVGA_Cursor
00C0E0  1               
00C0E0  1  60              RTS
00C0E1  1               
00C0E1  1               ;--------------------------------------------------
00C0E1  1               ;---------BUILT IN ROM CHARS-----------------------
00C0E1  1               ;--------------------------------------------------
00C0E1  1               CHAR_ROM: ; ASCII encoded - 128 Chars
00C0E1  1  00              .BYTE %00000000
00C0E2  1  00              .BYTE %00000000
00C0E3  1  00              .BYTE %00000000
00C0E4  1  00              .BYTE %00000000
00C0E5  1  00              .BYTE %00000000
00C0E6  1  00              .BYTE %00000000
00C0E7  1  00              .BYTE %00000000
00C0E8  1  00              .BYTE %00000000
00C0E9  1               
00C0E9  1  00              .BYTE %00000000
00C0EA  1  3E              .BYTE %00111110
00C0EB  1  41              .BYTE %01000001
00C0EC  1  55              .BYTE %01010101
00C0ED  1  41              .BYTE %01000001
00C0EE  1  55              .BYTE %01010101
00C0EF  1  49              .BYTE %01001001
00C0F0  1  3E              .BYTE %00111110
00C0F1  1               
00C0F1  1  00              .BYTE %00000000
00C0F2  1  3E              .BYTE %00111110
00C0F3  1  7F              .BYTE %01111111
00C0F4  1  6B              .BYTE %01101011
00C0F5  1  7F              .BYTE %01111111
00C0F6  1  6B              .BYTE %01101011
00C0F7  1  77              .BYTE %01110111
00C0F8  1  3E              .BYTE %00111110
00C0F9  1               
00C0F9  1  00              .BYTE %00000000
00C0FA  1  22              .BYTE %00100010
00C0FB  1  77              .BYTE %01110111
00C0FC  1  7F              .BYTE %01111111
00C0FD  1  7F              .BYTE %01111111
00C0FE  1  3E              .BYTE %00111110
00C0FF  1  1C              .BYTE %00011100
00C100  1  08              .BYTE %00001000
00C101  1               
00C101  1  00              .BYTE %00000000
00C102  1  08              .BYTE %00001000
00C103  1  1C              .BYTE %00011100
00C104  1  3E              .BYTE %00111110
00C105  1  7F              .BYTE %01111111
00C106  1  3E              .BYTE %00111110
00C107  1  1C              .BYTE %00011100
00C108  1  08              .BYTE %00001000
00C109  1               
00C109  1  00              .BYTE %00000000
00C10A  1  08              .BYTE %00001000
00C10B  1  1C              .BYTE %00011100
00C10C  1  2A              .BYTE %00101010
00C10D  1  7F              .BYTE %01111111
00C10E  1  2A              .BYTE %00101010
00C10F  1  08              .BYTE %00001000
00C110  1  1C              .BYTE %00011100
00C111  1               
00C111  1  00              .BYTE %00000000
00C112  1  08              .BYTE %00001000
00C113  1  1C              .BYTE %00011100
00C114  1  3E              .BYTE %00111110
00C115  1  7F              .BYTE %01111111
00C116  1  3E              .BYTE %00111110
00C117  1  08              .BYTE %00001000
00C118  1  1C              .BYTE %00011100
00C119  1               
00C119  1  00              .BYTE %00000000
00C11A  1  00              .BYTE %00000000
00C11B  1  1C              .BYTE %00011100
00C11C  1  3E              .BYTE %00111110
00C11D  1  3E              .BYTE %00111110
00C11E  1  3E              .BYTE %00111110
00C11F  1  1C              .BYTE %00011100
00C120  1  00              .BYTE %00000000
00C121  1               
00C121  1  FF              .BYTE %11111111
00C122  1  FF              .BYTE %11111111
00C123  1  E3              .BYTE %11100011
00C124  1  C1              .BYTE %11000001
00C125  1  C1              .BYTE %11000001
00C126  1  C1              .BYTE %11000001
00C127  1  E3              .BYTE %11100011
00C128  1  FF              .BYTE %11111111
00C129  1               
00C129  1  00              .BYTE %00000000
00C12A  1  00              .BYTE %00000000
00C12B  1  1C              .BYTE %00011100
00C12C  1  22              .BYTE %00100010
00C12D  1  22              .BYTE %00100010
00C12E  1  22              .BYTE %00100010
00C12F  1  1C              .BYTE %00011100
00C130  1  00              .BYTE %00000000
00C131  1               
00C131  1               ; I removed the rest of the Characters to shorten post - you get the idea
00C131  1               
00C131  1               ;---------VECTORS----------------------------------
00C131  1                  .ORG $FFFA      ; 6502 Starts reading its vectors here
00FFFA  1  0E C0           .word HALT      ; NMI
00FFFC  1  00 C0           .word RESET      ; RESET
00FFFE  1  0E C0           .word HALT      ; BRK
010000  1               
010000  1                  .END


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: