Topic: NeXT V66 ROM - Force Serial Console

zigzagjoe
May 27, 2025, 11:50:12 AM

https://www.nextcomputers.org/forums/index.php?topic=5982.msg33996


As folks probably know the Serial monitor console is only available if you've specifically set the PRAM setting to enable it first. This is a catch-22 if you haven't a working monitor and keyboard/mouse for your system.

Attached is a modified version of the commonly available V66 ROM (non-turbo) which will always enable the serial console if no monitor is attached.

This was a nice and simple modification as the ROM binary still mostly lines up with the ROM source floating around.
Code Select
km.c:

/* switch console to SCC if monitor is not responding */
if ((km_send (MON_KM_USRREQ, KM_SET_ADRS(0)) & MON_NO_RESP) &&
    mg->mg_nvram.ni_alt_cons) {
    mg->mg_console_i = CONS_I_SCC_A;
    mg->mg_console_o = CONS_O_SCC_A;
    return (0);
}

Disassembly:

(prior to this is the call to km_send and checking of the monitor no response bit)
ROM:000082BE                 btst    #3,$16(a2) ; check bit 3 (ni_alt_cons) of struct nvram_info in struct mon_global
ROM:000082C4                 beq.s   loc_82D6 ; do not enter if block when not set

Offset 82C4 needs to become 4E 71 (NOP) so we don't ever skip the if block.

After this is performed the checksum at offset 26 (decimal) must be updated. Attached is the original NeXT CRC algorithm as a Retro68 function. It was easiest to just run this on a 68k machine, so I did just that with a Macintosh SE/30.

Below is some quick code to use the CRC function where ROMTOCHECK is a byte array of the ROM file.

Code Select Expand
#pragma parameter __D0 calculateCRC(__A1,__D3)
uint32_t calculateCRC(uint8_t *addr, uint32_t count);
// offsets into the ROM header
#define MONCRC 26
#define ENETCRC 22
#define ROMLEN 0x20000

void verify() {
    uint8_t* start;
    uint32_t len, result, expect;

    expect = *((uint32_t*)(&ROMTOCHECK[MONCRC]));
    labelhexl("MonCRC expect",expect);   

    start = &ROMTOCHECK[MONCRC + 4]; // skip monitor CRC
    len = ROMLEN - MONCRC - 4;
    result = calculateCRC(start,len);

    labelhexl("MonCRC",result);   
    puts(result == expect ? "CRC is OK\n" :"Bad CRC\n");

    expect = *((uint32_t*)(&ROMTOCHECK[ENETCRC]));
    labelhexl("ENETCRC expect",expect);   

    start = &ROMTOCHECK[0]; // from start of rom to enet crc
    len = ENETCRC;
    result = calculateCRC(start,len);

    labelhexl("ENETCRC",result);   
    puts(result == expect ? "CRC is OK\n" :"Bad CRC\n");
}

Write it to an AT27C010 or similar DIP-32 ROM to use. Hopefully this helps someone.