Those "This is totally stupid but it works" moments?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Those "This is totally stupid but it works" moments?
by on (#206152)
Sometimes I wonder if anyone else feels like that when finding a solution to a certain problem during development (be it NES or otherwise).
Like this instance where I had a bunch of things to comment out, but no "block comments" in ASM6:
Code:
.if 1 = 0
.db 0,3,6,9,12,16,19,22
.db 25,28,31,34,37,40,43,46
.db 49,51,54,57,60,63,65,68
.db 71,73,76,78,81,83,85,88
.db 90,92,94,96,98,100,102,104
.db 106,107,109,111,112,113,115,116
.db 117,118,120,121,122,122,123,124
.db 125,125,126,126,126,127,127,127
.db 127,127,127,126,126,126,125,125
.db 124,123,122,122,121,120,118,117
.db 116,115,113,112,111,109,107,106
.db 104,102,100,98,96,94,92,90
.db 88,85,83,81,78,76,73,71
.db 68,65,63,60,57,54,51,49
.db 46,43,40,37,34,31,28,25
.db 22,19,16,12,9,6,3,0
.endif


So I did this instead. But anyway, this might be a stupid topic because programming in general is one of those interesting flow-experience generating hobbies I do on the side, so you don't stop to think about things in that sort of way if it's your job I assume.
Re: Those "This is totally stupid but it works" moments?
by on (#206161)
Your method is actually a pretty valid way of commenting out code parts in C, C++ and C#. (C# even specifically allows #if false for this purpose.)
Because even if you have multiline comments, what do you do if your source code is cluttered with them, but you still want to temporarily remove whole blocks of code?

(Besides, I assume .if 0 should be sufficient in your example.)


Another pretty hacky thing: If you want to define constant values in the same file that work for Assembly and for C at once.
You cannot have a #define inside a #define. But you can do this:

Code:
#ifdef COMPILE_FOR_ASSEMBLY
#define Constant(name, value) name = value
#else
/* #define Constant(name, value) #define name (value)
   wouldn't work, so we use: */
#define Constant(name, value) enum { name = value };
#endif

Constant(SomeValue, 5)
Constant(SomeOtherValue, SomeValue * 2 - 1)

An enum with only one value.

In case anybody is wondering how the above code works:
For C, you would simply include the file like a regular header file (#include "Constants.h").
For Assembly, you would do this:

cc65 -o Constants.inc -DCOMPILE_FOR_ASSEMBLY -E Constants.h

and then .include "Constants.inc".
Re: Those "This is totally stupid but it works" moments?
by on (#206167)
The method za909 demonstrated has a name: conditional assembly.

DRW's is called polyglot.
Re: Those "This is totally stupid but it works" moments?
by on (#206181)
DRW wrote:
Another pretty hacky thing: If you want to define constant values in the same file that work for Assembly and for C at once.
You cannot have a #define inside a #define. But you can do this:



That's wonderful and clever and horrible all at the same time.

I just had python script called by my makefile that pre-processes a list of constants and creates C and asm files. Not nearly as exciting.
Re: Those "This is totally stupid but it works" moments?
by on (#206182)
Yes, #if 0 is a very commonly used way to disable a block of code.
Re: Those "This is totally stupid but it works" moments?
by on (#206183)
I'm not familiar with ASM6, so I don't know if your .if 1 = 0 and .endif can be put in a macro; but that's what I've done in a couple of other assemblers. You do have to be careful to not start a line in the comment section with something the assembler might interpret to end the comment though, something which is more likely if you're commenting-out a portion of actual code than if you're commenting-out an explanation of what's coming. This is from a project of mine years ago:

Code:
COMMENT: MACRO      ; COMMENT and END_COMMENT here relieve us from having to contend with
         IF 0       ; many semicolons in places where we have many lines of comments together.
         ENDM       ; Since the IF is looking for an ELSE or ENDI (either cap.s or lower case),
 ;------------      ; just be sure none of the lines commented-out start with one of these
END_COMMENT: MACRO  ; words that could cause problems by fooling it.  If there is, that line
         ENDI       ; will still need a semicolon.  Also, if a line starts with a macro name
         ENDM       ; which is followed by illegal parameters for that macro (as in a
 ;------------      ; discussion of it), you will still need the semicolon.

<snip...>

 COMMENT
     The way SETUPACIA and POLLACIA (following) work, the appropriate way to set
     up the COM port on a DOS computer would be:

         C:\DOS\MODE COM2:9600,N,8,1,P

     Then connect to the DOS computer's COM2 port withOUT a nul modem.  This will
     give complete hardware handshaking for data going from the PC to the target
     computer on the workbench.
 END_COMMENT

Re: Those "This is totally stupid but it works" moments?
by on (#206184)
Garth wrote:
I'm not familiar with ASM6, so I don't know if your .if 1 = 0 and .endif can be put in a macro;

I don't know about ASM6, but just yesterday I tried this in ca65 and it yelled at me for not having closed the IF block before ending the macro... Too bad, I was really counting on being able to do this in something I was working on (not for comments though).
Re: Those "This is totally stupid but it works" moments?
by on (#206189)
za909 wrote:
Sometimes I wonder if anyone else feels like that when finding a solution to a certain problem during development (be it NES or otherwise).
Like this instance where I had a bunch of things to comment out, but no "block comments" in ASM6:

If you use Notepad++ you can use the shortcut Ctrl+Q to comment a block of code with a single-line comment per line. This is terribly useful, however it only works for a block where there isn't already comments. Else, I'd also do how you did it - I don't think it's "totally stupid".
Re: Those "This is totally stupid but it works" moments?
by on (#206190)
tokumaru wrote:
I don't know about ASM6, but just yesterday I tried this in ca65 and it yelled at me for not having closed the IF block before ending the macro... Too bad, I was really counting on being able to do this in something I was working on (not for comments though).

But ca65 does support it:
http://www.cc65.org/doc/ca65-11.html#.IF
http://www.cc65.org/doc/ca65-11.html#.ENDIF

Are you sure that you didn't do anything wrong?
Re: Those "This is totally stupid but it works" moments?
by on (#206192)
DRW wrote:

Sure, it supports conditional assembly, but you can't write macros like Garth did, where one macro opens the IF and another macro closes it.

I wanted to use this to parse different parts of the same file at different times, by including the file twice and using IFs hidden in macros to select which part to parse each time. Doesn't work, though.

EDIT: Shit, I just tried it again and it worked...! I must have done something wrong when I tried this before...

EDIT 2: Ohhh, I see what's going on now... Look at these macros:

Code:
.macro Open Arg
   .if Arg = 1
.endmacro

.macro Close
   .endif
.endmacro

If the condition evaluates as true and the block is parsed, there's no problem:

Code:
Open 1
.out "oi"
Close

But if it evaluates as false, the rest of the file is ignored and the macro that closes the IF is never called. If you use an actual ".endif" command instead of the "Close" macro, it works. A .define macro that translates to ".endif" also works. None of that helps if I need to do more work than just close the IF block though...
Re: Those "This is totally stupid but it works" moments?
by on (#206299)
Yes, sometimes I have thought that "This is totally stupid but it works" when writing some programming, although I do not remember the details right now.

However, I have done #if 0 in C to make a shell polyglot (so the source file includes its own compilation instructions, which can be executed by bash)

tokumaru wrote:
....Look at these macros:

Code:
.macro Open Arg
   .if Arg = 1
.endmacro

.macro Close
   .endif
.endmacro

If the condition evaluates as true and the block is parsed, there's no problem:

Code:
Open 1
.out "oi"
Close

But if it evaluates as false, the rest of the file is ignored and the macro that closes the IF is never called....
The same is true in TeX, but then you can use \let to give a token the same meaning as \fi so that it will work; even then, nested conditions don't work, so TeX has another thing; you can use \let to give a token the same meaning as \iftrue of \iffalse then. I don't know if assembler has support any such thing, but it is how Knuth solved that problem, so you may consider somthing similar if possible, I suppose.