bogax
-
Content Count
902 -
Joined
-
Last visited
Posts posted by bogax
-
-
Ok, (yup he's losing it) I made some additions
first, I rigged it so it just stashes playfieldpos in aux1 then put it back when it's time to draw the screen
so you don't need to modify the defintion of playfieldpos
I fixed it so you can choose between the 8 bit rand and the 16 bit rand
I added a (not very good) LCG and a scatter table
you choose amongst the options with joy0 left-right
the two digits on the left tell you where you are
bit 0 of the right digit selects between rand8 and rand 16
bit 1 of the right digit turns on the LCG
bit 2 of the right digit applies the scatter table
if bit 3 is set you get just the LCG
bit 0 of the left digit turns reseeding on or off 0 for off 1 for on
even numbers except 8 or 18 are 8 bit rand odd numbers are 16 bit rand
if the left digit is 0 then it uses the same seed if it's 1 it reseeds
if the LCG is selected it is XORed with the rand result unless the number is 8 or 18 in which case you just get the LCG
so 2,12, 3, 13 are rand XORed with just the LCG
if the LCG is on and the scatter table is enabled then it takes the result of rand ^ LCG and looks up a number in the table and returns that
if the LCG is off it XORs rand with the current seed and returns that and then uses it to look up a new seed
so 4, 14, 5, 15 are rand ^ scattertable
6, 16, 7, 17 are rand ^ LCG then lookup value in scattertable
8, 18 are just the LCG
if reseeding is not selected the seed is restored to whatever it was (so you can run different combinations with the same seed)
then it does a run of 255 and displays it
if reseeding is selected it reseeds rand and the LCG from the current seed and the scatter table (so even thought there's three bytes
there's only 256 possibilities)
the scatter table was lifted from the wikipedia entry on Pearson hashing
-
I think that shows the distribution pretty well
here I've added a 6th one that uses 5 components
they avoid the edges but fill the middle fairly well
edit: interesting to compare rand with rand16 ie comment out rand16
and see what happens
-
1
-
-
So when you run that .bin file, you see numbers in the score? I'm using Stella 4.6. Do I need a newer version to see the numbers in the score?
the score should show the number of the routine selected ie something in the range 0..19
I'm using Stella 4.5
I wonder if anyone else is having problems
-
started a new thread so we can stop walking all over Captain Spazer's topic
-
if you haven't been following along I come from here
this let's you choose among 20 possible (random number) routines and graphs the
result as a sort of bar graph
the routines are r0..r19
they should return a number in temp1
the numbers are modded to 0..31
the number of times a number comes up is a bar at
that position of the playfield. the height is limited to 20
the numbers are left to right 0..31
the routine is called each drawscreen untill results for
255 numbers have been graphed
it then waits for you to press fire at which point rand is reseeded from
a counter and it runs through another 255 numbers
while it's waiting for you to press fire you can step through
the routines to select one of r0..r19 using joy0up-down
the number of the routine should be displayed in the score
(but RT didn't seem to be able to see it)
in order to get a contiguous 32 bytes of RAM to keep track of how often a number comes up
I moved playfieldpos to aux1 ($F0) in 2600basic.h
r0 is just rand
r1 is RT's scheme for numbers 0..26
r2 starts with 5 bit random numbers (rand & 31) and scales that to 0..26
r3 starts with 7 bit random numbers (rand / 2) and scales that to 0..26
r4 starts with 8 bit random numbers and scales them to 0..26
r5 starts with 8 bit random numbers and scales them to 0..26 but uses 16 bit math
r6 starts with 16 bit random numbers (it calls rand twice to get 16 bits) and scales to 0..26 using 16 bit math
r7 starts with 5 bit numbers from the upper 5 bits of rand (rand & &F8) and scales them to 0..26 using 16 bit math
r8 takes rand & 31 mod 27 carrying the residue along to eliminate/distribute the bias that modding causes and so needs a variable
r9 is rand & 26
r10 is rand & 15
r11 is rand & 240 shifted to 0..15 same as r10 but using the upper 4 bits instead of the lower 4 bits
r12 if you scale 5 numbers down to 4 then one of the four will get the spare ie three of the four will come up once and one twice
if you scale 0..255 to 0..204 then every fourth number should come up twice as often but any four contiguous values should
come up as often as any other contigouous four
if you divide the numbers by 4 then each bar should subsume four contigous values and have equal distribution
thats what r12 and 13 do, r12 scales 7 bit random numbers to 0..204 and keeps only results that are 40..71
r13 is the same as r12 but divides by 4 and so hides the biases, it keeps 10..41
r14 and 15 are the same as r12 and 13 but uses asm and 8 bit random numbers
r16 is meant to be a worst case of RT's scheme for numbers 0..57 and shows the left side 0..31
r17 is the same but shows the middle 13..44
r18 is the same but shows the right edge 26..57
r19 rand & 30 ie even numbers 0..30
-
1
-
-
bah
I forgot to save 2600basic.h
so DASM does complain
I guess you have to go in to 2600basic.h and change playfieldpos to $F0 (or something else out of the way)
-
Clever that you added the previous rand to the current rand&31, to remove the seam that using mod usually produces. When looking for ranges less than 128, IMO this should be preferred to the "grab another rand" solution commonly used. (except if memory is tight) It's simple, has a better worst-case iteration count, and the probability distribution should be completely even for each value.
When I compile you .bas, the number of scanlines is huge.
I think the reason is the playfieldpos variable is getting stepped on. Your basic code seems to treat the memory between var0 and the alphabet vars as continuous and all available, but bB puts playfieldpos smack between them, at $D5. Did you by chance reorder playfieldpos in your 2600basic.h, at some point?
yeah, somewhere up there I mentioned that I moved playfieldpos to aux1 ($F0)
it appears that dimming it in bB (re)dims it and DASM doesn't complain so I've added it to the bB
0005 is otherwise the same as 0004
edit: DASM does complain (I forgot to save 2600basic.h)
so 0005 is the same as 0004 (in needing a modified 2600basic.h)
for numbers greater than 128
sincerand - mod < 256 - modandrnd < modthenrnd + 256 - mod < 256andrnd + rand - mod < 256( I hope that makes sense)
so you could do this
temp1 = rand if temp1 >= mod then temp1 = temp1 - mod rnd = rnd + temp1 if rnd >= mod then rnd = rnd - mod temp1 = rnd return
-
1
-
-
Yeah, the extra bits of randomness are certainly required.
Nice on the 16 bit solutions, though there's a half-way solution too. If you take your original r3 version and use 8 bits of random until the final divide, the values with lower probability only differ from the rest by ~10%. Worth it for just a few more more cycles.
and as you mentioned those extra 10% are well distributed (if those are the right terms
)if one in three consecutive numbers comes up 10% more often, it'll basically be that way for any
range of three consecutive numbers you choose.
having said that
it's been a while since this topic was discussed but my recollection is that RTs method
produces a sort of trapezoidal distribution, at either extreme the probabilities fall off but
in the middle it's probably as good as or better than any other method
so if you want a range of 20..150 maybe you don't care that 20..30 and 140..150
don't come up as often
it's having to call rand so many times that I think is not so good the time it takes being one,
but not the only, reason
I jimmied it so there's room for 20 routines
r8 uses mod it requires a variable but works well I think
edit: for some reason the forum seems to eat the ends of my posts
I added a version number to the name
RT mentioned not being able to see the routine number in the score
I wonder if that's a difference in bB or kernel versions or something
rnd = (rand & 31) + rnd mod27 if rnd > 26 then rnd = rnd - 27 : goto mod27 temp1 = rnd return
-
I'm not sure it's the precision, so much as something inherent with the method - I just wrote a C test with floats, and it has the similar weakness with 0, 5, 10, 16, and 21 being twice as likely as the other numbers.
I think each addition of the rand and the shifted version of itself spreads out the range, and creates spots of lower probability.
Your suggested idea for DPC+ is good, but we're pretty much done for adding functionality to it. I jumped through all sorts of hoops to squeeze bB DPC+ down (uglifying the source in the process) to add what functionality I could. IIRC we're just a few bytes away from stuffing the DPC+ bank.
Maybe the next go around with a bus stuffing kernel, batari will implement user-defined ARM assembly subroutines in other banks.
I don't think extra precision in the math will help much if you don't have extra random bits
here I've added three
r5 is 16 bit math with 8 bits of random
r6 is 16 bit (plus the carry) math with 16 random bits (rand called twice)
r7 is 16 bit math with only 5 random bits
-
1
-
-
Nice rand app, bogax!
Your r2 solution appears to be 0-22, instead of 0-26. It's alway worth noting some values are twice as likely to come up as others, though these are distributed fairly evenly through the range. So good for a screen position solution that OP wants, but not as good where even distribution is required, like a dice/card simulation.
oh, heck
yep I goofed it
should be
temp1 = rand & 31 : temp1 = (((temp1 / 2 + temp1) / 4 + temp1) / 2 + temp1) / 2
I think the distribution is fairly well illustratedthe problem is (I think) the limited precisionhere I've added the asm versionso r2..r4 are progressively better precisionif the ARM has hardware multiply you should knock together a routine todo it as a function (in 32 bits
) for the DPC+ kernel-
1
-
-
Can you make a DPC+ version of that?
Since the score doesn't change in your posted example, it's hard to know which r# I'm looking at and I don't understand most of the explanations in your post. Are you saying that there is a better way to have a limited range of random numbers so they'll be spread out more evenly? If so, is there a simple way to do it that doesn't involve techniques that are over the heads of most casual bB users?
I also have this on the bB page above the chart:
Warning: Using only division or only AND seems to create visible patterns. Mixing up division with AND seems to get rid of the patterns.
Since the DPC+ kernel has better random numbers, I hoped that it might automatically spread them out more evenly.
I forgot to mention that I moved playfieldposition to aux1 in order yo get a contiuous 32 bytes
I'm not very familiar with the DPC+ kernel but I seem to recall that space is even tighter with it
I don't think the quality of the random numbers matters the way you do it
its just that there's more ways to get the middle numbers
which is not to say the DPC+ prng wouldn't help
if you were using that method with the bB prng (which has a cycle length of 255) and
you needed 5 components you reduce the nunber of possibilities to 51 (255 / 5)
what I don't like about it is you have to call rand multiple times
there's javascript here
save it with an html extension then open it in your browser
hmm somethings bugged
the URL is http://pastebin.com/6PZ2kLtU
-
this lets you choose between one of eight
random number shemes r0..r7 and bar graphs the
result
each bars height is how often its number came up
r0..r7 should return a number in temp1
the result is modded to 0..31
routine is called 255 times graphing the result
then waits for you to press fire
it then reseeds the rand from a counter and
graphs another 255
while it's waiting you can select among routines
using joy0 up - down
r0 is just rand
r1 is RTs scheme for numbers 0..26
r2 is a range of 0..31 scaled to 0..26 the 0..31 are produced with rand & 31
r3 is rand scaled to 0..26
r4 is rand scaled to 0..31
r5 is rand & 31
r6..r7 are rand & 30 which procduces even numbers 0..30
notice the RT's scheme has the numbers bunching in the middle
-
Papa,
Thanks for the tips. I have been looking at what you post and they well above what I can accomplish. I'm still not there yet. I just started Bb last Oct 2015 while I was in Afghanistan. I have came a long ways but still have more to learn. As for the BASIC style you are correct. I learned how to use Basic on the old Apple II by doing CTRL ALT BREAK and some of the old school LOGO. I understand now what everyone is saying about the gosubs I have and I plan to go back and read what RT sent as well.
Not sure if someone could make a "video" on how to make simple title screens and or music. I am more a visual person than reading when it becomes more detailed. I'm still learning that as well which is hinder some progress on the next homage game I am working on.
you don't necessarily have to avoid gosubs but you will want to avoid switching banks if you don't have to
you've got a string of gosubs to bank6
__Return_From_Map gosub draw_room gosub __PacMan_Color bank6 gosub __Red_Ghost_Color bank6 gosub __Pink_Ghost_Color bank6 gosub __Blue_Ghost_Color bank6 gosub __Orange_Ghost_Color bank5 player9y = 250 ; Map PacMan off Screen
don't do that
jump into bank6 do your gosubs (and specify "thisbank" for both gosubs and returns) and then jump bank
bank switches cost
having said that, there's other things you could do to speed up your code
-
first (not really a bug)
1915 f4c9 .L021 ; a{0} = !a{0} 1916 f4c9 1917 f4c9 a5 d6 LDA a 1918 f4cb 29 01 AND #1 1919 f4cd 08 PHP 1920 f4ce a5 d6 LDA a 1921 f4d0 29 fe AND #254 1922 f4d2 28 PLP 1923 f4d3 d0 02 .byte.b $D0, $02 1924 f4d5 09 01 ORA #1 1925 f4d7 85 d6 STA athere's got to be a better way, especially considering that bit indices are constants
second
sometimes when we do something like
if !(a & 1) then skip
we'll get a complaint that skip is an unknown keyword
it doesn't happen all the time
I haven't figured out exactly what will cause it
-
I would add two points to what Spiceware said
you don't actually need asm to do any of that you can do it in bB
if you just can't figure out how to do it in bB it's not necessary to resort to asm
you can certainly do a better job of it with asm than bB would do
so if you just want to learn some asm more power to you
if playerpointers is meant to be a table of pointers into sprite data
the more usual way, the facility built into the processor for that, is to
use an index register
and since the index register is 8 bits (in this case) you'd only have to deal with one byte
even though the addresses are two bytes the upper byte doesn't change
with indexing you supply an address, whatever is in the index register gets added to it and
the result is used as the address
; table of pointers to individual sprites in a table of sprite data
data playerpointers
locationofsprite0, locationofsprite1, locationofsprite2, etc
end
; table of sprite data sprites are 8 bytes
data spritedata
%00111100 ; locationofsprite0 = spritedata, a 16 bit address
%01111110
%11000011
%11000011
%11000011
%11000011
%01111110
%00111000 ; top of sprite 0
%00111100 ; locationofsprite1 = spritedata + 8, a 16 bit address
%00011000
%00011000
%00011000
%00011000
%00011000
%01111000
%00111000 ; top of sprite 1
%11111111 ; locationofsprite1 = spritedata + 16, a 16 bit address
%11000000
%11100000
%00111000
%00001110
%11000011
%01100110
%00111100 ; top of sprite 2
end
; then to set player0 to sprite 1 in bB
player0pointer = spritedata[1]
; if you wanted to set player1pointer to sptite 2 you could do it this way
; player1pointer is the second location after player0pointer (the pointer is a 16 bit address, two bytes)
a = 2
player0pointer[a] = spritedata[2]
here's an excerpt from the asm listing produced
1736 f493 ;
1737 f493
1738 f493 .L013 ; const locationofsprite0 = < spritedata
1739 f493
1740 f493 .L014 ; const locationofsprite1 = < ( spritedata + 8 )
1741 f493
1742 f493 .L015 ; const locationofsprite2 = < ( spritedata + 16 )
1743 f493
1744 f493 .
1745 f493 ;
1746 f493
1747 f493 .
1748 f493 ;
1749 f493
1750 f493 .
1751 f493 ;
1752 f493
1753 f493 .
1754 f493 ;
1755 f493
1756 f493 .L016 ; data playerpointers
1757 f493
1758 f493 4c 9a f4 JMP .skipL016
1759 f496 playerpointers
1760 f496 9d a5 ad 00 .byte.b locationofsprite0, locationofsprite1, locationofsprite2, ;etc
1761 f49a
1762 f49a .skipL016
1763 f49a .
1764 f49a ;
1765 f49a
1766 f49a .
1767 f49a ;
1768 f49a
1769 f49a .
1770 f49a ;
1771 f49a
1772 f49a .L017 ; data spritedata
1773 f49a
1774 f49a 4c b5 f4 JMP .skipL017
1775 f49d spritedata
1776 f49d 3c .byte.b %00111100 ; locationofsprite0 = spritedata, a 16 bit address
1777 f49e
1778 f49e 7e .byte.b %01111110
1779 f49f
1780 f49f c3 .byte.b %11000011
1781 f4a0
1782 f4a0 c3 .byte.b %11000011
1783 f4a1
1784 f4a1 c3 .byte.b %11000011
1785 f4a2
1786 f4a2 c3 .byte.b %11000011
1787 f4a3
1788 f4a3 7e .byte.b %01111110
1789 f4a4
1790 f4a4 38 .byte.b %00111000 ; top of sprite 0
1791 f4a5
1792 f4a5 3c .byte.b %00111100 ; locationofsprite1 = spritedata + 8, a 16 bit address
1793 f4a6
1794 f4a6 18 .byte.b %00011000
1795 f4a7
1796 f4a7 18 .byte.b %00011000
1797 f4a8
1798 f4a8 18 .byte.b %00011000
1799 f4a9
1800 f4a9 18 .byte.b %00011000
1801 f4aa
1802 f4aa 18 .byte.b %00011000
1803 f4ab
1804 f4ab 78 .byte.b %01111000
1805 f4ac
1806 f4ac 38 .byte.b %00111000 ; top of sprite 1
1807 f4ad
1808 f4ad ff .byte.b %11111111 ; locationofsprite1 = spritedata + 16, a 16 bit address
1809 f4ae
1810 f4ae c0 .byte.b %11000000
1811 f4af
1812 f4af e0 .byte.b %11100000
1813 f4b0
1814 f4b0 38 .byte.b %00111000
1815 f4b1
1816 f4b1 0e .byte.b %00001110
1817 f4b2
1818 f4b2 c3 .byte.b %11000011
1819 f4b3
1820 f4b3 66 .byte.b %01100110
1821 f4b4
1822 f4b4 3c .byte.b %00111100 ; top of sprite 2
1823 f4b5
1824 f4b5 .skipL017
1825 f4b5 .
1826 f4b5 ;
1827 f4b5
1828 f4b5 .
1829 f4b5 ;
1830 f4b5
1831 f4b5 .
1832 f4b5 ;
1833 f4b5
1834 f4b5 .L018 ; player0pointer = spritedata[1]
1835 f4b5
1836 f4b5 a2 01 LDX #1
1837 f4b7 bd 9d f4 LDA spritedata,x
1838 f4ba 85 8a STA player0pointer
1839 f4bc .
1840 f4bc ;
1841 f4bc
1842 f4bc .
1843 f4bc ;
1844 f4bc
1845 f4bc .
1846 f4bc ;
1847 f4bc
1848 f4bc .
1849 f4bc ;
1850 f4bc
1851 f4bc .L019 ; a = 2
1852 f4bc
1853 f4bc a9 02 LDA #2
1854 f4be 85 d6 STA a
1855 f4c0 .
1856 f4c0 ;
1857 f4c0
1858 f4c0 .L020 ; player0pointer[a] = spritedata[2]
1859 f4c0
1860 f4c0 a2 02 LDX #2
1861 f4c2 bd 9d f4 LDA spritedata,x
1862 f4c5 a6 d6 LDX a
1863 f4c7 95 8a STA player0pointer,x
1864 f4c9 .
-
you keep saying "WORKS" but you don't say what it works for or what you're trying to do
you don't say what playerpointers is, but assuming you mean either of player0pointer or player1pointer,
if playerpointers is player0pointer that will end up with the address of player1pointer in a
the address of player1pointer is the address of player0pointer + 2
if playerpointers is player1pointer you'll end up with the address of player0height in a
(in the standard kernel)
-
Dunno. Listing are enabled by default in my bB build.
In case you missed it wllaby, you can already use the "player#-#:" command to share DPC+ sprite definitions with multiple spites.
to be fair
I don't remember if I had to turn on listing in the version I'm using now (which is bB.1.1d.reveng37)
and I haven't kept up but I know it was off at one time
-
edit: oops goofed it, hopefully fixed now..
the sprite data needs to be page aligned it can't cross a page boundary (in the standard kernel, I don't know about DPC+)
the sprite data label is the line number of the player statement where it's defined
something like
playerL032_0
if it's line 32
you can get the label from a list file if you can coax bB/DASM to produce a list file*
probably the simplest thing is just to define the player with all the sprite data
then read the lo byte of the pointer into a variable and use that
then bB will put the sprite data at the end and adjust things so that it doesn't
cross a page boundary (but data statements are more flexible in some ways)
if you don't want to spend a variable on that, write the pointer lo byte to a screen variable
read the number off the screen then incorporate it into your code as a constant
(in such a way that it doesn't change the player data location or so that you give it the correct
location if you remove a write to the screen that's four bytes to subtract, maybe)
*it's a switch somewhere in the make mechanics
what dingbat thought it was a good thing to remove that!?
it's the most useful thing bB produces second only to the bin
-
-
you can do that without asm
as far as I know there are only two uses of labels in bB
either as targets for goto's and such or as the name of a table in a data statement
if it's a goto target bB appends a "."
to get access in bB define constants for the labels
data table xx, xx, etc end const tablelo = <table const tablehi = >table ;the label target const targetlo = <.target const targethi = >.target [
I haven't got time to search now
but if you can find some of my previous posts there should be examples (somewhere
)edit: I found some old files and attached them here
because I thought they were probably from the (no longer working) link there
maybe a mistake because they appear to come from here
-
I don't see anything there that needs asm
you can't stx in bB but you don't need to
what is the nature of the label/parameter?
-
This is basic ASM question. What I'm trying to do is use assembly (instead of a macro) to change the player sprites and colors to anything.
change_player_color STA player0color STY player0color+1 LDA #16 STA player0height RETURN
If I call the function this way: temp1 = change_player_color(flash_lo, flash_hi)
This changes the color, but not the right way. It looks like it's just getting random data and all the lines are different colors.
I'd like to simplify this so I only need to pass the label of the data object. Like:
temp1 = change_player_color(flash_color)
Another thing, is how can I manipulate something already in a register? Can I use other registers in an expression? LDA x + y? Can I manipulate the current register on the same line? LDA a + 1?
I have this working with macros, but do macros duplicate your code for every permutation?
macros do duplicate code
they're kinda like inlined functions
"temp =" is bB and there's not much facility built into bB for getting stuff from asm to bB
(you just do it in asm)
a bB function can supply a value for an assignment but it has a bunch of overhead you probably don't need
for one thing it's a subroutine for another it always (in effect) passes at least two parameters whether you
want them or not
if your player data object is in RAM and therefore uses 1 byte addresses then you're asm might be something like this
macro {1} asm lda {1} sta player0color lda #16 sta player0height end endyou'd pass the macro a number which is the address of the color data (a single byte)
in bB that would be either a numeric constant or a variable name
the variable name is an alias for the number which is the address of a location in memory
it gets interpreted as an address in the asm because I didn't tell it otherwise
if you passed "a" as a parameter that would be equivalent to
lda $d6
$d6 is the location of variable a
if the asm were
lda {1}+1
that would be address $d7 dasm would do the math it's a constant expression and that would be variable b (they're in order in memory)
if the asm were
lda #{1}
and you passed (variable name) "a" as a parameter then player0color would get set to $d6
the bB equvalent of that (my) macro would be
macro player0color = {1} playerheight = 16 endI don't think that helps you much though (I don't think any of that is what you want)
could you give a little more information (maybe a little more explicit)
-
The stack memory in question is locked up inside the ARM chip, and it's not normally accessible to the 6502 - except when the 6502 uses DPC+ functions to fetch it and put it back. So with the current DPC+ standard you won't be able
The closest you can get to random access with this memory is exactly what wallaby is doing, and yes, it's cumbersome and cycle-intensive. There's other way DPC+.
There's no reason why a new standard - lets call it DPC++ - couldn't have RAM mapped into 6502 address space like the SARA chip. Just bear in mind you'll lose twice as much ROM as the RAM you get, and someone "just" needs to rewrite the ARM code and go through all of the testing.
how does RAM on the cartridge port(?) know if you're reading or writing?
edit: you mention losing twice as much ROM so are you talking about using an address line for R/W
ie read a location at one address and write that location at another address?
-
I can't really grasp how this works exactly. I'm trying to make it so that the resolution is fullscreen and so that the pfpixels are much thinner but I can't figure out how it works really, I've experimented alot and either things glitch out, nothing happens or I end up with a very narrow screen height.
Using const pfrowheight=3 gets the pfpixels to the size I want but the screen gets squished, how do I combo up to get a fullscreen resolution with this?
const pfres=32 gets the screen to the desired size but the pf gets all jumbled.
I'm not an expert but I believe your problem is you've only got enough memory for 12 rows
if you want to fill the screen and you make some rows shorter you have to make other rows taller to compensate
you need more memory
in addition to the options RT mentioned there's the multisprite kernel which uses ROM for the screen
but it has it's limitations

graphing random numbers
in batari Basic
Posted · Edited by bogax
fixed a couple bugs
removed some cruft
moved some stuff to subroutines
graph_rand0009.bas
graph_rand0009.bas.bin