setting a bit on a ram variable

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Post Reply
Scorpion Illuminati
Interested
Posts: 28
Joined: Fri Oct 02, 2015 4:58 pm

setting a bit on a ram variable

Post by Scorpion Illuminati » Wed Nov 11, 2015 3:30 am

Lets say i have a int variable called flags. As you know an integer has 8 bits.

Code: Select all

7-6-5-4-3-2-1-0
How would I set bit X where x is 0 to 7? For example:

Code: Select all

flags       equ (audio_clock+SizeWord)

FLAG_FRET_GREEN       equ 0x1
FLAG_FRET_RED           equ 0x2
FLAG_FRET_YELLOW    equ 0x4

// now set it
?????
I want to set a bit without effecting the other ones. Any assistance in this matter would be greatly appreciated.

Sincerely,

Scorpion Illuminati
Scorpion Illuminati - An open source rhythm game for the Sega Genesis
http://www.scorpionilluminati.tk

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Re: setting a bit on a ram variable

Post by TmEE co.(TM) » Wed Nov 11, 2015 5:33 am

In assembly you use the BSET instruction.

in C I think there's no choice but to use logic functions.
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

mikejmoffitt
Very interested
Posts: 86
Joined: Fri Sep 25, 2015 4:16 pm

Re: setting a bit on a ram variable

Post by mikejmoffitt » Wed Nov 11, 2015 5:43 am

In C, you can do it a few ways. Here is one

Code: Select all


// To set a bit
var = var | (1 << bit);

// To clear a bit
var = var & (~(1 << bit));

If you are more comfortable, you can make a macro:

Code: Select all


#define BITSET(x, y) x = x | ( 1 << y)
#define BITCLR(x, y) x = x & (~(1 << y))

// You can now do this:
BITSET(var, 2); // Set bit 2
BITCLR(var, 0); // Clear bit 0

If the compiler is even half decent, it should see what you're doing and optimize it to a BSET. GCC is smart enough to see that 1 << (any immediate value) can be determined at compile time, and should also see that you are ORing with a constant that has only one bit set.

BigEvilCorporation
Very interested
Posts: 209
Joined: Sat Sep 08, 2012 10:41 am
Contact:

Re: setting a bit on a ram variable

Post by BigEvilCorporation » Wed Nov 11, 2015 10:44 am

Yep, BSET is the tool for the job, note that it takes a bit number (0, 1, 2, 3, etc) instead of the bit value itself (1, 2, 4, 8, etc).

You can also abuse SNASM68K's "rs" family of keywords to make an enum of sorts:

Code: Select all

   rsset 0
FLAG_FRET_GREEN       rs.b 1
FLAG_FRET_RED           rs.b 1
FLAG_FRET_YELLOW     rs.b 1
I use the same for declaring structures, and the memory map too, which cleans up that "(audio_clock+SizeWord)" mess I wrote when I started coding.
A blog of my Megadrive programming adventures: http://www.bigevilcorporation.co.uk

Scorpion Illuminati
Interested
Posts: 28
Joined: Fri Oct 02, 2015 4:58 pm

Re: setting a bit on a ram variable

Post by Scorpion Illuminati » Thu Nov 12, 2015 11:09 pm

Thanks for the info. Am having a bit of trouble figuring out how to use it effectively. Here's the proposed code:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
The problem is no matter what the clear bit instruction executes regardless if the button is on or off. Any assistance in this matter would be greatly appreciated.

Sincerely,

Scorpion Illuminati
Scorpion Illuminati - An open source rhythm game for the Sega Genesis
http://www.scorpionilluminati.tk

Mask of Destiny
Very interested
Posts: 616
Joined: Thu Nov 30, 2006 6:30 am

Re: setting a bit on a ram variable

Post by Mask of Destiny » Thu Nov 12, 2015 11:46 pm

You don't have a branch instruction after the bset, so after it sets the flag, the bclr instruction runs and clears it. Instead you want something like this:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
      bra @GotA
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
@GotA:

Scorpion Illuminati
Interested
Posts: 28
Joined: Fri Oct 02, 2015 4:58 pm

Re: setting a bit on a ram variable

Post by Scorpion Illuminati » Fri Nov 13, 2015 2:03 am

Mask of Destiny wrote:You don't have a branch instruction after the bset, so after it sets the flag, the bclr instruction runs and clears it. Instead you want something like this:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
      bra @GotA
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
@GotA:
Any way to shorten it to not use the bra instruction?

Sincerely,

Scorpion Illuminati
Scorpion Illuminati - An open source rhythm game for the Sega Genesis
http://www.scorpionilluminati.tk

Mask of Destiny
Very interested
Posts: 616
Joined: Thu Nov 30, 2006 6:30 am

Re: setting a bit on a ram variable

Post by Mask of Destiny » Fri Nov 13, 2015 5:47 am

There are other ways to achieve similar goals. Which one would be best depend on what you're optimizing for (cycle count, size, RAM usage). For instance, if you want to optimize for cycle count or code size by sacrificing memory usage, you could use scc to set a byte to either $FF or 0 depending on a condition code. Another option might be to just save the pad state somewhere and test it directly rather than trying to translate it into another bitfield.

Another option might be to rethink the code a bit. Presumably you're going to check a bunch of buttons and then update all the corresponding flags. Rather than clearing and setting each bit individually you could clear the entire fret_flags variable and only do a bset for the flags that need it. While you're at it, you could move fret_flags into a register temporarily to burn a lot fewer cycles on memory access.

So something like

Code: Select all

	moveq #0, d1
	btst #pad_button_a, d0
	bne @NoA
	bset #FLAG_FRET_GREEN, d1
@NoA:
        ;handle other buttons here
        move.b d1, fret_flags

Natsumi
Very interested
Posts: 82
Joined: Mon Oct 05, 2015 3:00 pm
Location: 0x0
Contact:

Re: setting a bit on a ram variable

Post by Natsumi » Fri Nov 13, 2015 11:07 am

Code: Select all

      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit first
      btst #pad_button_a, d0                                           ; Check A button
      bne @NoA                                                         ; if button is off, skip setting the bit
      bset #FLAG_FRET_GREEN, (fret_flags)                              ; set the green fret bit

@NoA:
This is the easiest solution; of course there are ways to optimize cycle counts using lookuptables for example, but for 99% of the cases you'd use code like this, its completely impractical.

Post Reply