Point of order! Your thread title says "What makes a CP/M program a CP/M program (and not just, say, a z80 program)?"... shouldn't have you said "
CP/M-80 program"? CP/M-86 and CP/M-68000 exist, you know.
Anyway... I find it a bit odd that your list of criteria doesn't actually include "uses documented CP/M API calls and accesses them via the standard: "LD DE,parameter; LD C,function; CALL 5"" calling routine? Is that what you meant by "recognizes the BDOS and stays clear?", because it's not actually clear to me what "stays clear" means there? Because, well, it seems to me like that's the basic definition of a CP/M program, that is uses the CP/M API verses, I dunno,
TRS-DOS's roughly equivilant set of functionality that was called via completely different conventions?
The question is contentious because there is no correct answer. It's another one of those things to discuss in circles until the end of time.
Totally. This is "is the glass half empty, or half full?" on steroids. A "soft" glass-half-empty answer is probably going to be that the program:
a: uses *only* the documented CP/M API for everything it does; no directly poking hardware addresses or calling proprietary firmware extensions
b: loads at 100h and access the CP/M API via the "Call 5" address
While a *strict* "half-empty" is going to add:
c: only uses 8080 instructions for universal compatibility
Bullet point A: seems pretty reasonable, although you have to add an asterisk specifying which *version* of the CP/M API the program is targeting. (IE, you can't disqualify a program meant for MP/M or CP/M Plus because it doesn't run on CP/M 1.4.) And bullet point B: is also pretty reasonable; yes, there were those oddball versions of CP/M to run on TRS-80s and Zenith machines, but they're not directly binary compatible with "standard" CP/M-80 programs. You could trivially run programs for those oddball systems (usually ORG'ed to start at 4200H) on a generic CP/M system by using a special loader, I suppose, but the reverse is not true, so, yeah, I'd say they're disqualified. Bullet point C:... well, yes, it's "reasonable" in the sense that while Z80 machines vastly outnumber 8080 boxes CP/M itself is 8080-only, and, well, there *were* still companies churning out 8085 computers well into the 1980's; the point of the "half empty" position is you're defining a "CP/M Program" as compatible with "any machine that runs standard CP/M-80". Z80 programs fail that test.
On the flip side, the expansive answer is simply "the program runs on a computer that boots CP/M and uses it to load the binary". Almost *any* program designed for a computer that has anything remotely like graphics capability breaks rule "A" for the strict criteria; even standard fare like Wordstar, which *can* abide by rule A, usually doesn't when it's configured for computers that have memory mapped video because doing fancy terminal handling is such a massive PITA when all you have to work with is a serial punch API call.
But yeah, who cares. If you want to start calling video games shipped on floppy disks for MSX computers "CP/M programs" go with your heart, they do probably make at least a few CP/M compatible calls before going straight off into ColecoVision-ville with the direct register pounding. Just don't expect that designation to help anyone trying to run them on their Osborne.