; What the controllers are doing, as they do it. ; ; Prints a line whenever any pad changes: which pad, and the byte it is now reporting. That is ; the whole of the diagnostic, and it is enough to tell apart the three things that look ; identical from inside a game which is not responding. ; ; Nothing printed at all, and nought pads present: the front end never saw a controller. ; A pad present but no lines: it is seen, and the buttons are mapped to nothing. ; Lines that do not match the buttons pressed: the mapping is wrong rather than missing. ; ; ---- Why a program rather than a print in the front end ---- ; ; Because the question is what the MACHINE can see. A front end that printed what it thought ; it was sending would answer a different question, and the gap between those two is exactly ; where a controller that was detected, mapped and reported still did nothing: the port that ; says which pads exist counted only recorded ones, so a game asked whether there was a ; controller and was told no while the buttons underneath worked perfectly. ; ; Written by Anachronaut #Include services.asm #Program #Base 0x5000 start: SETD.0 Intro SWI osPrintString ; How many are there, before anybody presses anything. One bit a pad. SETD.0 PresentText SWI osPrintString INA 0x64 CALL sayByte INIA 0x0A OUTA 0x00 INIA 0x01 OUTA 0x02 ; Key mode, so q arrives without a Return. everyFrame: INA 0x30 INIB 0x01 AND BRQ everyFrame ; A frame, which is when a pad's recording steps. RSTA SETD.2 Which STA.2 eachPad: CALL onePad SETD.2 Which LDA.2 INCA STA.2 INIB 0d4 CCF SUB BNQ eachPad ; q gives the machine back. Anything else typed is ignored, because a pad test that ; stopped on a stray keypress would be a poor thing to lean on. INA 0x01 INIB 0x01 AND BRQ everyFrame INA 0x00 INIB 0x71 ; q CCF SUB BNQ everyFrame RSTA OUTA 0x02 SWI osExit ; ---- One pad, printed only when it changes ---- ; ; A line a frame for four pads would be two hundred and forty lines a second and unreadable. ; What is worth seeing is the moment something goes down or comes up. onePad: ; The port is 0x60 plus the pad number, and a port is an immediate byte inside the ; instruction that names it - so it cannot be computed, and the four are written out. SETD.2 Which LDA.2 BRA padZero DECA BRA padOne DECA BRA padTwo INA 0x63 BRI padGot padZero: INA 0x60 BRI padGot padOne: INA 0x61 BRI padGot padTwo: INA 0x62 padGot: ; Against what it was last time. Last is four bytes, one a pad, so DP1 walks to this one. SETD.1 Last PSHA SETD.2 Which LDA.2 DPUA.1 POPA LDB.1 CCF SUB BRQ padSame ; The same as last frame, so there is nothing to say. STA.1 ; Remembered, so the next frame has something to compare with. PSHA LDA.2 ; DP2 is still Which, from working out where in Last to look. INIB 0x30 ; '0' CCF ADD OUTQ 0x00 INIA 0x3A ; ':' OUTA 0x00 INIA 0x20 OUTA 0x00 POPA CALL sayByte INIA 0x0A OUTA 0x00 padSame: RET ; ---- One byte, as a number ---- ; ; osPrintNumber takes A and B TOGETHER, A being the high half - which is the same way round as ; the shift register and every other pair on this machine, and is not what a byte in A wants. ; Passed as it stood, every value came out two hundred and fifty six times too big. sayByte: RSTB CCF ADD MVQB ; The byte, in the low half where it belongs. RSTA ; And nothing in the high one. SWI osPrintNumber RET #Data #Base 0x3000 Intro: "Press buttons on a controller. q quits. " PresentText: "Pads present, as a bit each: " ; One byte a pad, holding what it said last frame. Last: 0x00 0x00 0x00 0x00 Which: 0x00