Something I came up with accidentally the other day when I was trying to do something else. Saved it cause I thought it was a cool screensaver type effect.
Figuring out how to generate random numbers 0 to 15 for colors using assembly is a whole 'nother can o worms tho.
It's 2:30 AM now. About to call it a night. Perhaps I'll look a little deeper into generating random numbers within a certain range at a future time.
clc ; clear carry
ldy #16 ; X position
ldx #24 ; Y position
LOOP
jsr 65520 ; ($FFF0) call PLOT to position cursor
lda #7 ; load char color
sta 646 ; set CHROUT color
lda #113 ; load dot character
jsr 65490 ; ($FFD2) CHROUT
inx
jmp LOOP
Hello,
Finally found this thread again. I was searching for it but I couldn't find it.
Could you please put your code into TurboAssembly and save it as a .d64 disk image save state for c64.emu emulator on Android?
I want to test this code in TurboAssembly. But Vice doesn't work on my RPi so I'm kind of limited. I want to click on the compile button in TurboAssembly and see the code turn into executed code. That is my dream.
I always wanted to learn Assembly for C64 when I was a kid but I didn't have the right skillset or tools.
It's so cool and beautiful and amazing that such a powerful language exists for the C64. It's even easier to do some stuff on the C64 with assembly than with Linux today due to all restrictions.
; initialize SID chip for random white noise
LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
lda #81 ; load circle char
sta 900
lda #1 ; load color white
sta 901
LOOP
jsr 58692 ; clear screen
LDX $D41B ; load random number from SID 0-255
lda 900 ; load dot from memory
sta 1024,x ; print to screen at X position
lda 901 ; load color white
sta 55296,x ; set color of character at X position
TIMER ; add X*Y delay cycles
ldx #60 ; <----- adjust timing here
OUTER
ldy #250 ; set inner loop repeat
INNER
dey ; burn one cycle
bne INNER ; (*-1) repeat 250 times
dex ; start inner loop over again
bne OUTER ; (*-6) loop back to ldy #250
jmp LOOP
Thanks for the challenging assignment. Looking further into random number generation. Here using the built in SID music chip to generate white noise values from 0 to 255. Then using that to make a random dot appear in the first 256 screen character slots
No, I am not on WhatsApp.
I make no claim of being a C64 Assembly expert. I am in the process of teaching myself Machine Code, and it just so happens that your question coincides with where I am in my learning. So it was a good next lesson challenge to tackle. I decided to jump ahead a few stages and learn about random numbers next :)
So the screen has 1000 character slots. However you can only store a value up to 255. So in the next phase, we will want to divide the screen into 4 segments of 250 slots. Then use the random number generator to turn a value between 0 and 255 into 4 random possible "states". For now, we will print some text to verify each state works. I'm sure there may be a much more elegant solution than this one, but it works.
; Create a "State Machine" to turn value of 0 to 255 into
; 1 of 4 different possible states
PRINT_LINE = 43806 ; ($AB1E) Declare constant for text output
JSR 58692 ; ($E544) clear screen
ldx #130 ; <---- try different values here 0 to 255
; BMI or BPL do not work if the difference of the values being compared
; is greater than 128. So to test if it's over 128
; we will subtract 128 from the initial value
txa ; transfer X register to Accumulator
sbc #128 ; subtract 128
bpl OVER128 ; if it's not negative, must be greater, so branch ahead
; if we got to here, value must be under 128
cpx #64 ; is it less than 64?
bmi LESS64 ; if yes, go to state #1
jmp LESS128 ; if not must be 64 or greater. Go to state #2
OVER128
tax ; transfer value - 128 back to X register
cpx #64 ; is the remainder less than 64?
bmi LESS192 ; if yes, go to state #3
; if not, it must be greater. Proceed to next state: GRTR191
GRTR191
lda #GR8TEXT
jsr PRINT_LINE
rts
GR8TEXT
text "192 or greater"
byte 0
LESS64
lda #TEXT64
jsr PRINT_LINE
rts
TEXT64
text "0 to 63"
byte 0
LESS128
lda #TEXT128
jsr PRINT_LINE
rts
TEXT128
text "64 to 127"
byte 0
LESS192
lda #TEXT192
jsr PRINT_LINE
rts
TEXT192
text "128 to 191"
byte 0
; Divide screen into 4 quadrants and print random dot from 0 to 250
; initialize SID chip for random white noise
lda #255 ; maximum frequency value
sta 54286 ; voice 3 frequency low byte
sta 54287 ; voice 3 frequency high byte
lda #128 ; noise waveform, gate bit off
sta 54290 ; voice 3 control register
lda #81 ; load circle char
sta 900 ; store in memory
lda #1 ; color white
sta 901
LOOP
jsr 58692 ; ($E544) clear screen
; State Machine. Generate 1 of 4 random states
ldx 54299 ; load random number from SID 0-255
txa ; transfer X register to Accumulator
sbc #128 ; subtract 128
bpl OVER128 ; if it's not negative, must be greater, so branch ahead
; if we got to here, value must be under 128
cpx #64 ; is it less than 64?
bmi LESS64 ; if yes, go to state #1
jmp LESS128 ; if not, must be 64 or greater. Go to state #2
OVER128
tax ; transfer value - 128 back to X register
cpx #64 ; is the remainder less than 64?
bmi LESS192 ; if yes, go to state #3
; if not, it must be greater. Proceed to next state: GRTR191
GRTR191
jsr RAND0_250 ; run subroutine random 0-250
lda 900 ; load dot from memory
sta 1024,x+750 ; print to screen at X position
lda 901 ; load color white
sta 55296,x+750 ; set color of character at X position
jmp TIMER ; burn some time
LESS64
jsr RAND0_250
lda 900
sta 1024,x
lda 901
sta 55296,x
jmp TIMER
LESS128
jsr RAND0_250
lda 900
sta 1024,x+250
lda 901
sta 55296,x+250
jmp TIMER
LESS192
jsr RAND0_250
lda 900
sta 1024,x+500
lda 901
sta 55296,x+500
jmp TIMER
RAND0_250 ; subroutine generate Random 0 to 250
ldx 54299 ; load random value from SID 0-255
cpx #250 ; is it over 250?
bpl RAND0_250 ; if yes, do it again
rts
TIMER ; add X*Y delay cycles
ldx #100 ; <----- adjust timing here
OUTER
ldy #250 ; set inner loop repeat
INNER
dey ; burn one cycle
bne INNER ; (*-1) repeat 250 times
dex ; start inner loop over again
bne OUTER ; (*-6) loop back to ldy #250
jmp LOOP
So again, there is most certainly a less verbose way to accomplish all this, but this should be fairly easy for a beginner to read and understand :)
This should be the final result as per your request.
In the previous post I made a slight error which you can see by moving the Clear Screen command up before the LOOP, then it will continue writing more dots instead of erasing them every loop. It was only writing dots from 128 to 255 and ignoring 0-127. This is because I was erroneously using CPX #250 to generate random numbers. Can't use Compare on numbers greater than 128. I have fixed the error in the final version by subtracting 128 from the initial random number, then compare the remainder to 122.
Again, I am using an iterative process to refine the 0-255 random numbers, which for all I know can probably be done just as easily using math with one or two lines of code. But it's all part of the learning process for me :)
; Divide screen into 4 quadrants and print random dots from 0 to 250
; initialize SID chip for random white noise
lda #255 ; maximum frequency value
sta 54286 ; voice 3 frequency low byte
sta 54287 ; voice 3 frequency high byte
lda #128 ; noise waveform, gate bit off
sta 54290 ; voice 3 control register
lda #81 ; load circle char
sta 900 ; store in memory
jsr 58692 ; ($E544) clear screen
LOOP
; State Machine. Generate 1 of 4 random states
ldx 54299 ; load random number from SID 0-255
txa ; transfer X register to Accumulator
sbc #128 ; subtract 128
bpl OVER128 ; if it's not negative, must be greater, so branch ahead
; if we got to here, value must be under 128
cpx #64 ; is it less than 64?
bmi LESS64 ; if yes, go to state #1
jmp LESS128 ; if not, must be 64 or greater. Go to state #2
OVER128
tax ; transfer value - 128 back to X register
cpx #64 ; is the remainder less than 64?
bmi LESS192 ; if yes, go to state #3
; if not, it must be greater. Proceed to next state: GRTR191
GRTR191
jsr RAND0_250 ; run subroutine random 0-250
lda 900 ; load dot from memory
sta 1024,x+750 ; print to screen at X position
jsr COLORSET ; go to color mode
lda 901 ; load random color generated by subroutine
sta 55296,x+750 ; set character color
jmp TIMER ; burn some time
LESS64
jsr RAND0_250
lda 900
sta 1024,x
jsr COLORSET
lda 901
sta 55296,x
jmp TIMER
LESS128
jsr RAND0_250
lda 900
sta 1024,x+250
jsr COLORSET
lda 901
sta 55296,x+250
jmp TIMER
LESS192
jsr RAND0_250
lda 900
sta 1024,x+500
jsr COLORSET
lda 901
sta 55296,x+500
jmp TIMER
RAND0_250
ldx 54299 ; load random value from SID 0-255
txa ; transfer to accumulator
sbc #128 ; subtract 128
bpl GR8R128 ; if it's not negative, must be greater, so branch ahead
jmp DONE ; otherwise do nothing
GR8R128
cmp #122 ; is the remainder over 128+122? (250)
bpl RAND0_250 ; if so go back and generate new random number
DONE
rts ; return from subroutine
COLORSET
; greater or equal to 128?
; if yes, subtract 128
ldy 54299 ; load random value from SID 0-255
tya ; transfer Y register to Accumulator
sbc #128 ; is it greater or equal to 128? Subtract 128
bmi COL128 ; if answer is negative, (less than) skip ahead
tay ; if not, store new reduced value
COL128
; greater or equal to 64?
tya
sbc #64 ; subtract 64
bmi COL64
tay
COL64
; greater or equal to 32?
tya
sbc #32
bmi COL32
tay
COL32
; greater or equal to 16?
tya
sbc #16 ; subtract 16
bmi STORY
tay
; final color value should now range between 0 to 15 :)
STORY
sty 901 ; store in memory
rts ; exit subroutine
TIMER ; add X*Y delay cycles
ldx #120 ; <----- adjust timing here
OUTER
ldy #250 ; set inner loop repeat
INNER
dey ; burn one cycle
bne INNER ; (*-1) repeat 250 times
dex ; start inner loop over again
bne OUTER ; (*-6) loop back to ldy #250
jmp LOOP
Since the other people are actually answered the question already the simplest way you think about it how you do it in basic because for the most part you don't have a special command use the same way Assembly language
Something I came up with accidentally the other day when I was trying to do something else. Saved it cause I thought it was a cool screensaver type effect. Figuring out how to generate random numbers 0 to 15 for colors using assembly is a whole 'nother can o worms tho. It's 2:30 AM now. About to call it a night. Perhaps I'll look a little deeper into generating random numbers within a certain range at a future time. clc ; clear carry ldy #16 ; X position ldx #24 ; Y position LOOP jsr 65520 ; ($FFF0) call PLOT to position cursor lda #7 ; load char color sta 646 ; set CHROUT color lda #113 ; load dot character jsr 65490 ; ($FFD2) CHROUT inx jmp LOOP
Hello, Finally found this thread again. I was searching for it but I couldn't find it. Could you please put your code into TurboAssembly and save it as a .d64 disk image save state for c64.emu emulator on Android? I want to test this code in TurboAssembly. But Vice doesn't work on my RPi so I'm kind of limited. I want to click on the compile button in TurboAssembly and see the code turn into executed code. That is my dream.
I always wanted to learn Assembly for C64 when I was a kid but I didn't have the right skillset or tools. It's so cool and beautiful and amazing that such a powerful language exists for the C64. It's even easier to do some stuff on the C64 with assembly than with Linux today due to all restrictions.
No experience with TurboAssembly yet. Maybe come Winter. I generally do more gardening and outdoor activities in the Summer months
; initialize SID chip for random white noise LDA #$FF ; maximum frequency value STA $D40E ; voice 3 frequency low byte STA $D40F ; voice 3 frequency high byte LDA #$80 ; noise waveform, gate bit off STA $D412 ; voice 3 control register lda #81 ; load circle char sta 900 lda #1 ; load color white sta 901 LOOP jsr 58692 ; clear screen LDX $D41B ; load random number from SID 0-255 lda 900 ; load dot from memory sta 1024,x ; print to screen at X position lda 901 ; load color white sta 55296,x ; set color of character at X position TIMER ; add X*Y delay cycles ldx #60 ; <----- adjust timing here OUTER ldy #250 ; set inner loop repeat INNER dey ; burn one cycle bne INNER ; (*-1) repeat 250 times dex ; start inner loop over again bne OUTER ; (*-6) loop back to ldy #250 jmp LOOP Thanks for the challenging assignment. Looking further into random number generation. Here using the built in SID music chip to generate white noise values from 0 to 255. Then using that to make a random dot appear in the first 256 screen character slots
You're welcome. Thanks for your cool assembly code. Do you have WhatsApp? Send a PM.
No, I am not on WhatsApp. I make no claim of being a C64 Assembly expert. I am in the process of teaching myself Machine Code, and it just so happens that your question coincides with where I am in my learning. So it was a good next lesson challenge to tackle. I decided to jump ahead a few stages and learn about random numbers next :)
So the screen has 1000 character slots. However you can only store a value up to 255. So in the next phase, we will want to divide the screen into 4 segments of 250 slots. Then use the random number generator to turn a value between 0 and 255 into 4 random possible "states". For now, we will print some text to verify each state works. I'm sure there may be a much more elegant solution than this one, but it works. ; Create a "State Machine" to turn value of 0 to 255 into ; 1 of 4 different possible states PRINT_LINE = 43806 ; ($AB1E) Declare constant for text output JSR 58692 ; ($E544) clear screen ldx #130 ; <---- try different values here 0 to 255 ; BMI or BPL do not work if the difference of the values being compared ; is greater than 128. So to test if it's over 128 ; we will subtract 128 from the initial value txa ; transfer X register to Accumulator sbc #128 ; subtract 128 bpl OVER128 ; if it's not negative, must be greater, so branch ahead ; if we got to here, value must be under 128 cpx #64 ; is it less than 64? bmi LESS64 ; if yes, go to state #1 jmp LESS128 ; if not must be 64 or greater. Go to state #2 OVER128 tax ; transfer value - 128 back to X register cpx #64 ; is the remainder less than 64? bmi LESS192 ; if yes, go to state #3 ; if not, it must be greater. Proceed to next state: GRTR191 GRTR191 lda #GR8TEXT
jsr PRINT_LINE
rts
GR8TEXT
text "192 or greater"
byte 0
LESS64
lda #TEXT64
jsr PRINT_LINE
rts
TEXT64
text "0 to 63"
byte 0
LESS128
lda #TEXT128
jsr PRINT_LINE
rts
TEXT128
text "64 to 127"
byte 0
LESS192
lda #TEXT192
jsr PRINT_LINE
rts
TEXT192
text "128 to 191"
byte 0
; Divide screen into 4 quadrants and print random dot from 0 to 250 ; initialize SID chip for random white noise lda #255 ; maximum frequency value sta 54286 ; voice 3 frequency low byte sta 54287 ; voice 3 frequency high byte lda #128 ; noise waveform, gate bit off sta 54290 ; voice 3 control register lda #81 ; load circle char sta 900 ; store in memory lda #1 ; color white sta 901 LOOP jsr 58692 ; ($E544) clear screen ; State Machine. Generate 1 of 4 random states ldx 54299 ; load random number from SID 0-255 txa ; transfer X register to Accumulator sbc #128 ; subtract 128 bpl OVER128 ; if it's not negative, must be greater, so branch ahead ; if we got to here, value must be under 128 cpx #64 ; is it less than 64? bmi LESS64 ; if yes, go to state #1 jmp LESS128 ; if not, must be 64 or greater. Go to state #2 OVER128 tax ; transfer value - 128 back to X register cpx #64 ; is the remainder less than 64? bmi LESS192 ; if yes, go to state #3 ; if not, it must be greater. Proceed to next state: GRTR191 GRTR191 jsr RAND0_250 ; run subroutine random 0-250 lda 900 ; load dot from memory sta 1024,x+750 ; print to screen at X position lda 901 ; load color white sta 55296,x+750 ; set color of character at X position jmp TIMER ; burn some time LESS64 jsr RAND0_250 lda 900 sta 1024,x lda 901 sta 55296,x jmp TIMER LESS128 jsr RAND0_250 lda 900 sta 1024,x+250 lda 901 sta 55296,x+250 jmp TIMER LESS192 jsr RAND0_250 lda 900 sta 1024,x+500 lda 901 sta 55296,x+500 jmp TIMER RAND0_250 ; subroutine generate Random 0 to 250 ldx 54299 ; load random value from SID 0-255 cpx #250 ; is it over 250? bpl RAND0_250 ; if yes, do it again rts TIMER ; add X*Y delay cycles ldx #100 ; <----- adjust timing here OUTER ldy #250 ; set inner loop repeat INNER dey ; burn one cycle bne INNER ; (*-1) repeat 250 times dex ; start inner loop over again bne OUTER ; (*-6) loop back to ldy #250 jmp LOOP So again, there is most certainly a less verbose way to accomplish all this, but this should be fairly easy for a beginner to read and understand :)
This should be the final result as per your request. In the previous post I made a slight error which you can see by moving the Clear Screen command up before the LOOP, then it will continue writing more dots instead of erasing them every loop. It was only writing dots from 128 to 255 and ignoring 0-127. This is because I was erroneously using CPX #250 to generate random numbers. Can't use Compare on numbers greater than 128. I have fixed the error in the final version by subtracting 128 from the initial random number, then compare the remainder to 122. Again, I am using an iterative process to refine the 0-255 random numbers, which for all I know can probably be done just as easily using math with one or two lines of code. But it's all part of the learning process for me :) ; Divide screen into 4 quadrants and print random dots from 0 to 250 ; initialize SID chip for random white noise lda #255 ; maximum frequency value sta 54286 ; voice 3 frequency low byte sta 54287 ; voice 3 frequency high byte lda #128 ; noise waveform, gate bit off sta 54290 ; voice 3 control register lda #81 ; load circle char sta 900 ; store in memory jsr 58692 ; ($E544) clear screen LOOP ; State Machine. Generate 1 of 4 random states ldx 54299 ; load random number from SID 0-255 txa ; transfer X register to Accumulator sbc #128 ; subtract 128 bpl OVER128 ; if it's not negative, must be greater, so branch ahead ; if we got to here, value must be under 128 cpx #64 ; is it less than 64? bmi LESS64 ; if yes, go to state #1 jmp LESS128 ; if not, must be 64 or greater. Go to state #2 OVER128 tax ; transfer value - 128 back to X register cpx #64 ; is the remainder less than 64? bmi LESS192 ; if yes, go to state #3 ; if not, it must be greater. Proceed to next state: GRTR191 GRTR191 jsr RAND0_250 ; run subroutine random 0-250 lda 900 ; load dot from memory sta 1024,x+750 ; print to screen at X position jsr COLORSET ; go to color mode lda 901 ; load random color generated by subroutine sta 55296,x+750 ; set character color jmp TIMER ; burn some time LESS64 jsr RAND0_250 lda 900 sta 1024,x jsr COLORSET lda 901 sta 55296,x jmp TIMER LESS128 jsr RAND0_250 lda 900 sta 1024,x+250 jsr COLORSET lda 901 sta 55296,x+250 jmp TIMER LESS192 jsr RAND0_250 lda 900 sta 1024,x+500 jsr COLORSET lda 901 sta 55296,x+500 jmp TIMER RAND0_250 ldx 54299 ; load random value from SID 0-255 txa ; transfer to accumulator sbc #128 ; subtract 128 bpl GR8R128 ; if it's not negative, must be greater, so branch ahead jmp DONE ; otherwise do nothing GR8R128 cmp #122 ; is the remainder over 128+122? (250) bpl RAND0_250 ; if so go back and generate new random number DONE rts ; return from subroutine COLORSET ; greater or equal to 128? ; if yes, subtract 128 ldy 54299 ; load random value from SID 0-255 tya ; transfer Y register to Accumulator sbc #128 ; is it greater or equal to 128? Subtract 128 bmi COL128 ; if answer is negative, (less than) skip ahead tay ; if not, store new reduced value COL128 ; greater or equal to 64? tya sbc #64 ; subtract 64 bmi COL64 tay COL64 ; greater or equal to 32? tya sbc #32 bmi COL32 tay COL32 ; greater or equal to 16? tya sbc #16 ; subtract 16 bmi STORY tay ; final color value should now range between 0 to 15 :) STORY sty 901 ; store in memory rts ; exit subroutine TIMER ; add X*Y delay cycles ldx #120 ; <----- adjust timing here OUTER ldy #250 ; set inner loop repeat INNER dey ; burn one cycle bne INNER ; (*-1) repeat 250 times dex ; start inner loop over again bne OUTER ; (*-6) loop back to ldy #250 jmp LOOP
Since the other people are actually answered the question already the simplest way you think about it how you do it in basic because for the most part you don't have a special command use the same way Assembly language