I'm proud to show here my first assembly program
I tried to find informations about NES PPU in the forums (because well I don't fully understand it) and then I found this simulator in a thread I don't remember. The online simulator can be found here : http://www.6502asm.com
Press '0' to '9' to print digits to the screen.
Press 'f' to change the font color, 'b' to change the background color.
Press 'c' to clear the screen.
In fact, it's only printing small 4x6 bitmaps 1-bit depth color. when pressing 'b' or 'f' it simply inc the color entry for the conresponding bit value in the bitmap, where '0' is for background and '1' is for the font.
Speaking of which, I proved that I know very well 6502 assembly language, but I still don't know assembler directives (like doing macros, naming memory location, etc). Is directives unique to each assemblers?
What are they? Maybe just put some links to read about. Thanks and thank for reading...
I tried to find informations about NES PPU in the forums (because well I don't fully understand it) and then I found this simulator in a thread I don't remember. The online simulator can be found here : http://www.6502asm.com
Press '0' to '9' to print digits to the screen.
Press 'f' to change the font color, 'b' to change the background color.
Press 'c' to clear the screen.
In fact, it's only printing small 4x6 bitmaps 1-bit depth color. when pressing 'b' or 'f' it simply inc the color entry for the conresponding bit value in the bitmap, where '0' is for background and '1' is for the font.
Code:
; $8000= back color
; $8001= font color
; $8002= column
; $8003= row
lda #$0
sta $8000 ;back=0 (black)
lda #$1
sta $8001 ;font=1 (white)
lda #0
sta $8002 ;column=0
lda #0
sta $8003 ;row=0
main:
jsr GetKey
is_b:
cmp #$62 ;key is 'b'?
bne is_c
inc $8000 ;inc color back
jmp main
is_c:
cmp #$63 ;key is 'c'?
bne is_f
jsr ClrScr ;Clear screen
jmp main
is_f:
cmp #$66 ;key is 'f'?
bne call_Putch
inc $8001 ;inc color font
jmp main
call_Putch:
jsr PutCh
jmp main
;-------------------------------------------
GetKey:
lda #0 ;reset key read
sta $ff
while_not_kbhit:
lda $ff ;read key
beq while_not_kbhit
;loop if NULL
rts ;leave key read in A
;-------------------------------------------
ClrScr:
lda #2
sta $11 ;HI address of screen begin
lda #0
sta $10 ;LO address
tay
Next_Pts:
sta ($10),y
inc $10 ;increment LO address
bne Next_Pts
inc $11 ;increment HI address
lda $11
cmp #6 ;if HI address==6
beq exit_ClrScr ;exit
tya ; same as lda #0
jmp Next_Pts
exit_ClrScr:
rts
;-------------------------------------------
PutCh:
; $10 = screen write
; $12 = chr read index
; $13 = temp mem for display
; $14 = down counter for shift reg
sec
sbc #$30 ;subtract by '0'
bmi Error_Exit ; if negative,
; the ASCII value
;is less than '0',
; so it isn't a
;number
cmp #10
bmi OK_Continue
;this time, if the
;value in accumula-
;tor is less than
;10, it's a number
Error_Exit:
jmp exit
OK_Continue:
sta $12
ldy #2
Multiply_chr: ;this loop multiplies
;by three the number.
;this is for calcula-
;ting the offset from
adc $12 ;the first bitmap.
dey
bne Multiply_chr
sta $12
;
; Calculate the memory offset of the first pt
;
lda $8002 ;load X coord
jmp while_greater_than_8
; while(col>=8)
;{
; col-=8;
; row++;
;}
Subtract:
sec
sbc #8
inc $8003
while_greater_than_8:
cmp #8
bpl Subtract
sta $8002
asl ;multiply by four
asl
sta $10 ;the 3 LSB of address
;are now calculated
lda #0
sta $11 ;clear the HI address
;this is important because
;later a value will be ROL'ed
;in.
lda $8003
cmp #5 ;if row is greater than 4,
bmi Continue;row will be set to 0
lda #0
sta $8003
Continue:
clc
ldy #5
multiply_1: ;this loop multiplies by 6
;the row's value
adc $8003
dey
bne multiply_1
ldy #5
multiply_2: ;this loop multiplies by 32 the
;previous value calculated in
;the accumulator.
;since the screen is 32x32,
;and the bitmap 6 pts height,
;row*6*32 will give the
;correct memory offset for
;a vertical position.
asl
rol $011 ;since rol zeropage is buggy,
;I use absolute mode instead
dey
bne multiply_2
ora $10
sta $10
lda $11
clc
adc #2 ;add 2 to HI address so it
;effectively access screen
sta $11
;
; Display the bitmap
;
ldx $12 ;x holds offset from
;CHR_0
inc $12 ;and $12 then holds the
;offset of the next
;caracter
inc $12
inc $12
ldy #0
loop_fetch_byte:
lda #8
sta $14 ;this memory location
;holds the remaining
;bit to shift
lda CHR_0,x ;load a byte of
;bitmap
loop_byte_scan:
asl
sta $13 ;save accumulator for
;later use
bcs FontPoint ; if Carry=1, Font
;else Background
lda $8000 ;Load background
;color
jmp Next_Point
FontPoint:
lda $8001 ;Load Font color
Next_Point:
sta ($10),y ;store color to
;pixel
iny
cpy #4
bne cccontinue
;if y==4
ldy #0 ;reset y
lda $10
clc
adc #$20 ;and add 32 to
;LO address, thus
;moving down
sta $10
bcc cccontinue
inc $11 ;if crossing page
;boundary ;)
cccontinue:
dec $14 ;dec the bit counter
;for shifter
bne load_0x13
;if the shifter is
;empty
inx ;increment offset
cpx $12 ;finished?
beq done ;yes quit
jmp loop_fetch_byte
load_0x13:
lda $13 ;reload value to
;shift
jmp loop_byte_scan
done:
inc $8002 ;increment column
exit:
rts
;-------------------------------------------
;characters from '0' to '9', bitmaps 1-bit 4x6
CHR_0:
dcb $02,$55,$52
CHR_1:
dcb $02,$62,$27
CHR_2:
dcb $06,$13,$47
CHR_3:
dcb $06,$12,$16
CHR_4:
dcb $05,$57,$11
CHR_5:
dcb $07,$47,$16
CHR_6:
dcb $03,$47,$57
CHR_7:
dcb $07,$12,$44
CHR_8:
dcb $07,$57,$57
CHR_9:
dcb $07,$57,$16
; $8001= font color
; $8002= column
; $8003= row
lda #$0
sta $8000 ;back=0 (black)
lda #$1
sta $8001 ;font=1 (white)
lda #0
sta $8002 ;column=0
lda #0
sta $8003 ;row=0
main:
jsr GetKey
is_b:
cmp #$62 ;key is 'b'?
bne is_c
inc $8000 ;inc color back
jmp main
is_c:
cmp #$63 ;key is 'c'?
bne is_f
jsr ClrScr ;Clear screen
jmp main
is_f:
cmp #$66 ;key is 'f'?
bne call_Putch
inc $8001 ;inc color font
jmp main
call_Putch:
jsr PutCh
jmp main
;-------------------------------------------
GetKey:
lda #0 ;reset key read
sta $ff
while_not_kbhit:
lda $ff ;read key
beq while_not_kbhit
;loop if NULL
rts ;leave key read in A
;-------------------------------------------
ClrScr:
lda #2
sta $11 ;HI address of screen begin
lda #0
sta $10 ;LO address
tay
Next_Pts:
sta ($10),y
inc $10 ;increment LO address
bne Next_Pts
inc $11 ;increment HI address
lda $11
cmp #6 ;if HI address==6
beq exit_ClrScr ;exit
tya ; same as lda #0
jmp Next_Pts
exit_ClrScr:
rts
;-------------------------------------------
PutCh:
; $10 = screen write
; $12 = chr read index
; $13 = temp mem for display
; $14 = down counter for shift reg
sec
sbc #$30 ;subtract by '0'
bmi Error_Exit ; if negative,
; the ASCII value
;is less than '0',
; so it isn't a
;number
cmp #10
bmi OK_Continue
;this time, if the
;value in accumula-
;tor is less than
;10, it's a number
Error_Exit:
jmp exit
OK_Continue:
sta $12
ldy #2
Multiply_chr: ;this loop multiplies
;by three the number.
;this is for calcula-
;ting the offset from
adc $12 ;the first bitmap.
dey
bne Multiply_chr
sta $12
;
; Calculate the memory offset of the first pt
;
lda $8002 ;load X coord
jmp while_greater_than_8
; while(col>=8)
;{
; col-=8;
; row++;
;}
Subtract:
sec
sbc #8
inc $8003
while_greater_than_8:
cmp #8
bpl Subtract
sta $8002
asl ;multiply by four
asl
sta $10 ;the 3 LSB of address
;are now calculated
lda #0
sta $11 ;clear the HI address
;this is important because
;later a value will be ROL'ed
;in.
lda $8003
cmp #5 ;if row is greater than 4,
bmi Continue;row will be set to 0
lda #0
sta $8003
Continue:
clc
ldy #5
multiply_1: ;this loop multiplies by 6
;the row's value
adc $8003
dey
bne multiply_1
ldy #5
multiply_2: ;this loop multiplies by 32 the
;previous value calculated in
;the accumulator.
;since the screen is 32x32,
;and the bitmap 6 pts height,
;row*6*32 will give the
;correct memory offset for
;a vertical position.
asl
rol $011 ;since rol zeropage is buggy,
;I use absolute mode instead
dey
bne multiply_2
ora $10
sta $10
lda $11
clc
adc #2 ;add 2 to HI address so it
;effectively access screen
sta $11
;
; Display the bitmap
;
ldx $12 ;x holds offset from
;CHR_0
inc $12 ;and $12 then holds the
;offset of the next
;caracter
inc $12
inc $12
ldy #0
loop_fetch_byte:
lda #8
sta $14 ;this memory location
;holds the remaining
;bit to shift
lda CHR_0,x ;load a byte of
;bitmap
loop_byte_scan:
asl
sta $13 ;save accumulator for
;later use
bcs FontPoint ; if Carry=1, Font
;else Background
lda $8000 ;Load background
;color
jmp Next_Point
FontPoint:
lda $8001 ;Load Font color
Next_Point:
sta ($10),y ;store color to
;pixel
iny
cpy #4
bne cccontinue
;if y==4
ldy #0 ;reset y
lda $10
clc
adc #$20 ;and add 32 to
;LO address, thus
;moving down
sta $10
bcc cccontinue
inc $11 ;if crossing page
;boundary ;)
cccontinue:
dec $14 ;dec the bit counter
;for shifter
bne load_0x13
;if the shifter is
;empty
inx ;increment offset
cpx $12 ;finished?
beq done ;yes quit
jmp loop_fetch_byte
load_0x13:
lda $13 ;reload value to
;shift
jmp loop_byte_scan
done:
inc $8002 ;increment column
exit:
rts
;-------------------------------------------
;characters from '0' to '9', bitmaps 1-bit 4x6
CHR_0:
dcb $02,$55,$52
CHR_1:
dcb $02,$62,$27
CHR_2:
dcb $06,$13,$47
CHR_3:
dcb $06,$12,$16
CHR_4:
dcb $05,$57,$11
CHR_5:
dcb $07,$47,$16
CHR_6:
dcb $03,$47,$57
CHR_7:
dcb $07,$12,$44
CHR_8:
dcb $07,$57,$57
CHR_9:
dcb $07,$57,$16
Speaking of which, I proved that I know very well 6502 assembly language, but I still don't know assembler directives (like doing macros, naming memory location, etc). Is directives unique to each assemblers?
What are they? Maybe just put some links to read about. Thanks and thank for reading...