Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 8, 2014 23:28:20 GMT -5
Hey everyone I wrote some math functions to convert decimal to binary and binary to decimal: declare function decimal(strBin$ as string) as integer decimal = 0 binpower = len(strBin$) - 1 for i = 0 to len(strBin$) - 1 bit = val(mid$(strBin$, binpower-i,1)) if bit = 1 then addVal = 2<<(i-1) decimal+=addVal end if next return decimal end function
declare function binary$(dec as integer) as string
while dec <> 0 r = dec % 2 if r = 1 then binary$ = "1" + binary$ else binary$ = "0" + binary$ end if dec = dec>>1 wend return binary$ end function
To use, simply do: print binary$(40550) print decimal(binary$(40550)) I know, I know, what's the use?! Well, if you have some options in your game, you can do something like: if val(mid$(binary$(500),bit%,1)) = 1 then SecretLevel = 1 Or if you want to make it more difficult for rom hackers or try to prevent game genie codes, then you can just reference the bit instead of assigning a variable: if val(mid$(binary$(500),bit%,1)) = 1 then ' do code end if I'm sure there are other uses, such as setting values in SRAM, but that would require a little modification. I also didn't put any checks to ensure that the binary string when converting to decimal that there isn't anything but 1's and 0's. You can add them yourself, or if you're having difficulty, I can add it in (of course, if you're using this, I would hope you understand binary and wouldn't try to force a non 1 or 0 value into the string) Anyway, enjoy! Next up will be the trig functions for sine and cosine and tangent, though I can't see why anyone would want to do calculations on the fly instead of creating a table, but who knows (I actually don't even know if these functions will be possible on the Genesis/Mega Drive, but we'll see!)
|
|
|
Post by Tamkis on May 10, 2014 21:55:44 GMT -5
I still do not exactly understand the use of this, when BEX can handle "argunerics" according to the manual (ie Myvar.1 for extracting the first bit of some variable). Also doing something like "if val(mid$(binary$(500),bit%,1))" probably would be more memory/processor intensive than just using argunerics, and I really doubt anybody would actually try to hack a homebrew video game, lol. Still, it's nice example code. If it is possible, please do, as BEX could really use some external trig functions for finer angle precision rather than a unit circle lookup table. (The board is really becoming dead lately ...)
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 11, 2014 15:37:31 GMT -5
Ya know, I completely forgot about argunerics. It probably does exactly what I wrote the functions for, but I'll still mess around to verify Thanks for reminding me about that! And the reason why I did these functions was because somebody in the chatroom I visit loves to make game genie codes, so he had made a bunch for Fix-It Felix. He had a bit of trouble on how to make you invincible, but he eventually got it and I did this to try to stump him/give him practice haha.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 11, 2014 17:34:45 GMT -5
Since the trig functions require precision, they aren't supported natively on the Genesis/Mega Drive hardware. I *think* I can get them to work with up to 9 points of precision for tangent and 14 points of precision for sine and cosine, though I'm not sure how efficient it will be. I think having that high of a precision is overkill, though, so I'll most likely limit it to 5 points for all the functions. Tangent will be the most difficult as it'll require a custom division function
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 11, 2014 19:15:17 GMT -5
Argunerics are nice to find out if a bit is either a 1 or a 0, and you could use those for your conditional statements, but if you want to change the value of that bit, how would you be able to? Poke will only go down to the byte level, not the bit level, and doing Integer.1 = 0 errors out. I didn't see any string functions to replace a value at a specific point in a string, so I had to write a function (see below) for that There are a few uses for this - a layer of "security", item management, script handling, and really anything. A lot of people will do something like this: has_bombs% = 1 has_bodyarmor% = 1
BEX uses 16 bit integers, so using those 2 variables, you're taking up 4 bytes of memory. Both values in binary are 0000000000000001. Using this method of using binary conversion, you can convert the decimal value of an integer to a binary value, with the function below, you can change the bit from 0 to 1 or 1 to 0, and put it back as a decimal value. Another example, say for an RPG to trigger an event, you might have something like this: intro_passed = 1 quest_1 = 1 quest_2 = 2 boss_1 = 1 quest_3_event = 0
Apply the same thing, and you now have less variables and will save memory. Of course, if your program is small, using this method would most likely use up more memory, but a medium to large program would be able to utilize memory more efficiently. I was able to reduce the memory usage for these 3 functions down to 164 bytes, so if your flag variables are less than 166 bytes, there wouldn't be a need to use these functions (unless you want to combine a few flags together for an added layer of protection), or unless I can figure out a way to get the string variable strBin$ down to 16 bytes, then it would be 52 bytes instead of 164. I've tried declaring the string as * 16 in the function declarations as well as using OPTION STRING SIZE, 16, but neither helped. Maybe it's a glitch in the compiler, or maybe it's required for stability purposes, I'm not sure Anyway, here's a sample program with the updated functions:
OPTION STRING SIZE, 16 print decimal(binary$(65535)) print binary$(65535) if decimal(binary$(65535)).3 = 1 then print binval$(binary$(65535),3) print decimal(binval$(binary$(65535),3)) end if
declare function binval$(strBin$ as string*16, bit as integer) as string * 16 dim strBinNewVal$ as string * 1, adjustedBit as integer adjustedBit = len(strBin$)-(bit+1) strBinNewVal$ = "1" if mid$(strBin$,adjustedBit,1) = "1" then strBinNewVal$ = "0" return left$(strBin$,adjustedBit) + strBinNewVal$ + right$(strBin$,bit)
end function
declare function decimal(strBin$ as string*16) as integer decimal = 0 binpower = len(strBin$) - 1 for i = 0 to len(strBin$) - 1 bit = val(mid$(strBin$, binpower-i,1)) if bit = 1 then if i = 0 then addVal = 1 else addVal = 2<<(i-1) end if decimal+=addVal end if next return decimal end function
declare function binary$(dec as integer) as string * 16 dim binStr$ as string * 16 while dec <> 0 r = dec % 2 if r = 1 then binStr$ = "1" + binStr$ else binStr$ = "0" + binStr$ end if dec = dec>>1 wend return binStr$ end function
Which this will output: 65535 1111111111111111 1111111111110111 65527
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 11, 2014 20:44:35 GMT -5
Please, for the love of genesis .. simply use the BSET opcode Or wrap it in a BEX function if you must, like this .. x = bset(x,8) ' Sets bit 8 print x ' Prints 256 end
declare asm function bset(d0 as long, d1 as long) bset.l d1,d0 end function
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 11, 2014 23:02:03 GMT -5
Ha! Thanks moon!
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 12, 2014 16:38:38 GMT -5
I think the biggest use of binary <-> decimal functions is to properly read/write them to save RAM. Take an 8-bit value from a location in save RAM. Write an 8-bit value to a location in save RAM. Taking to account which of the odd or even bytes save RAM usually uses.
I'd love to make a game in the same vein as Dwarven Fortress that stores as much as the game world state as possible. These routines are a huge stepping store for that kind of thing.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Aug 22, 2014 11:05:27 GMT -5
I think the biggest use of binary <-> decimal functions is to properly read/write them to save RAM. Take an 8-bit value from a location in save RAM. Write an 8-bit value to a location in save RAM. Taking to account which of the odd or even bytes save RAM usually uses. I'd love to make a game in the same vein as Dwarven Fortress that stores as much as the game world state as possible. These routines are a huge stepping store for that kind of thing. So many uses once you get creative with it still working on the trig functions, but I have to make a custom number system to handle precision
|
|
|
Post by sega16 on Aug 22, 2014 14:20:17 GMT -5
Here is how I convert an integer to a string.
WordToNumUnsigned: ;D0 the word you want converted ;A0 the buffer to hold output ;A1 tempory buffer ;Registers used by this function ;D1 lenght minus one ;D2 tempory ;Also stack is used and D0 is clobered ;First get remainder moveq #-1,d1 nextDigit: divu.w #10,d0 move.l d0,d2 clr.w d2 swap d2 addi.b #48,d2 move.b d2,(a1)+ andi.l #$FFFF,d0 addi.w #1,d1 tst d0 bne nextDigit revStr: move.b -(a1),(a0)+ dbra.w d1,revStr move.b #0,(a0) rts
That should be a more direct route instead of first converting to a binary string then doing to a decimal string.
|
|