sms: generate TMR SEGA signature in Collapse OS itself

Having the signature generation code in /tools prevents self-hosting
on the SMS.
This commit is contained in:
Virgil Dupras 2020-11-25 21:42:07 -05:00
parent 631e7f1008
commit b4f3fde062
9 changed files with 71 additions and 69 deletions

View File

@ -1,9 +1,8 @@
# See /doc/hw/z80/sms.txt
TARGET = os.bin
TARGET = os.sms
BASE = ../../..
STAGE = $(BASE)/cvm/stage
BLKPACK = $(BASE)/tools/blkpack
SMSROM = $(BASE)/tools/smsrom
EMUL = $(BASE)/emul/z80/sms
.PHONY: all
@ -11,7 +10,6 @@ all: $(TARGET)
$(TARGET): xcomp.fs $(STAGE) blkfs
cat xcomp.fs | $(STAGE) blkfs > $@
$(SMSROM):
$(BLKPACK):
$(MAKE) -C ../tools
@ -21,9 +19,6 @@ blkfs: $(BLKPACK) $(BASE)/blk.fs blk.fs
$(STAGE):
$(MAKE) -C $(BASE)/cvm stage
os.sms: $(TARGET) $(STAGE) $(SMSROM)
$(SMSROM) $(TARGET) > $@
$(EMUL):
$(MAKE) -C ${@:%/sms=%}

View File

@ -16,6 +16,7 @@ SYSVARS 0x74 + CONSTANT PAD_MEM
: ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp )
524 LOAD ( font compiler )
165 LOAD ( Sega ROM signer )
282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides )
@ -37,5 +38,6 @@ CREATE ~FNT CPFNT7x7
( Update LATEST )
PC ORG @ 8 + !
," VDP$ GRID$ PAD$ (im1) " EOT,
ORG @ 0x100 - 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!
ORG @ 0x100 - DUP 256 /MOD 2 PC! 2 PC!
DUP 1 ( 16K ) segasig
0x4000 + 256 /MOD 2 PC! 2 PC!

View File

@ -17,6 +17,7 @@ SYSVARS 0x74 + CONSTANT PS2_MEM
: ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp )
524 LOAD ( font compiler )
165 LOAD ( Sega ROM signer )
282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides )
@ -38,5 +39,6 @@ CREATE ~FNT CPFNT7x7
( Update LATEST )
PC ORG @ 8 + !
," VDP$ GRID$ PS2$ (im1) " EOT,
ORG @ 0x100 - 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!
ORG @ 0x100 - DUP 256 /MOD 2 PC! 2 PC!
DUP 1 ( 16K ) segasig
0x4000 + 256 /MOD 2 PC! 2 PC!

View File

@ -18,6 +18,7 @@ SYSVARS 0x74 + CONSTANT PS2_MEM
: ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp )
524 LOAD ( font compiler )
165 LOAD ( Sega ROM signer )
282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides )
@ -41,5 +42,6 @@ CREATE ~FNT CPFNT7x7
( Update LATEST )
PC ORG @ 8 + !
," VDP$ GRID$ PS2$ BLK$ (im1) " EOT,
ORG @ 0x100 - 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!
ORG @ 0x100 - DUP 256 /MOD 2 PC! 2 PC!
DUP 1 ( 16K ) segasig
0x4000 + 256 /MOD 2 PC! 2 PC!

View File

@ -18,6 +18,7 @@ SYSVARS 0x74 + CONSTANT PS2_MEM
: ZFILL, ( u ) 0 DO 0 A, LOOP ;
262 LOAD ( xcomp )
523 LOAD ( font compiler )
165 LOAD ( Sega ROM signer )
282 LOAD ( boot.z80.decl )
270 LOAD ( xcomp overrides )
@ -40,5 +41,6 @@ CREATE ~FNT CPFNT5x7
( Update LATEST )
PC ORG @ 8 + !
," TMS$ GRID$ PS2$ BLK$ ' SDC@ BLK@* ! (im1) " EOT,
ORG @ 0x100 - 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!
ORG @ 0x100 - DUP 256 /MOD 2 PC! 2 PC!
DUP 1 ( 16K ) segasig
0x4000 + 256 /MOD 2 PC! 2 PC!

14
blk.fs
View File

@ -21,7 +21,7 @@ MASTER INDEX
005 Z80 assembler 030 8086 assembler
050 AVR assembler 70-99 unused
100 Block editor 120 Visual Editor
160 AVR SPI programmer
160 AVR SPI programmer 165 Sega ROM signer
170-259 unused 260 Cross compilation
280 Z80 boot code 350 Core words
400 AT28 EEPROM driver 401 Grid subsystem
@ -957,6 +957,18 @@ VARIABLE aspprevx
: aspe! ( byte addr --, write to EEPROM )
256 /MOD ( b lsb msb ) SWAP
0xc0 ( b msb lsb 0xc0 ) _cmd DROP asprdy ;
( ----- 165 )
( Sega ROM signer. See doc/sega.txt )
: A!+^ ( a c -- a+1 ) OVER A! 1+ ;
: segasig ( addr size -- )
0x2000 OVER LSHIFT ( a sz bytesz )
ROT TUCK + 0x10 - ( sz a end )
TUCK SWAP 0 ROT> ( sz end sum end a ) DO ( sz end sum )
I A@ + LOOP ( sz end sum ) SWAP ( sz sum end )
'T' A!+^ 'M' A!+^ 'R' A!+^ 0x20 A!+^ 'S' A!+^ 'E' A!+^
'G' A!+^ 'A' A!+^ 0 A!+^ 0 A!+^
( sum's LSB ) OVER A!+^ ( MSB ) SWAP 8 RSHIFT OVER A! 1+
( sz end ) 0 A!+^ 0 A!+^ 0 A!+^ SWAP 0x4a + SWAP A! ;
( ----- 260 )
Cross compilation program

View File

@ -57,7 +57,7 @@ so far. I haven't explored whether this can run on a megadrive).
# Build the ROM
Running "make os.sms" in /arch/z80/sms will produce a "os.sms"
Running "make" in /arch/z80/sms will produce a "os.sms"
ROM that can be put as is on a SD card to the everdrive or
flashed as is on a writable ROM cart. Then, just run the thing!

40
doc/sega.txt Normal file
View File

@ -0,0 +1,40 @@
# Sega Master System ROM signatures
When loading ROM, the SMS' BIOS checks for a special signature
at the end of that ROM. If that signature is incorrect, the ROM
doesn't load.
Collapse OS has a program to generate that signature at B165.
This document describes what it does.
At boot, the BIOS checks 0x10 bytes before the 0x8000, then
0x4000, then 0x2000 mark for a signature. This signature has
the following structure.
0x00-0x07: String constant: "TMR SEGA"
0x08-0x09: null bytes
0x0a-0x0b: checksum
0x0c-0x0e: null bytes
0x0f : "size" flag
The checksum is a simple 16-bit sum of all bytes up to the
beginning of the signature.
The size flag can have 3 values: 0x4a for an 8K ROM, 0x4b for
16K and 0x4c for 32K. It can have other values for other kinds
of sizes, but we don't care about them in the context of
Collapse OS.
## Generating the signature
Before generating the signature, you need to have the contents
of your ROM somewhere in memory. Then, you load B165 and you
call "segasig" which has the signature "addr size". "addr" is
the adress of the beginning of the ROM and "size" is 0, 1 or 2
depending on whether your ROM is 8K, 16K or 32K.
Calling the word will write the 0x10 bytes signature at the
end of the ROM.
Note that all I/O use the "Addressed device" words (see
usage.txt), so I/O indirections will work.

View File

@ -1,53 +0,0 @@
/* ./smsrom fname
Transforms binary at fname into an 8K, 16K or 32K Sega Master System ROM with
a header fit for an Export SMS. The resulting ROM is spit to stdout.
Whether the ROM is 8, 16 or 32K depends on the size of binary at fname.
*/
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: ./smsrom fname\n");
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stderr, "Can't open %s.\n", argv[1]);
return 1;
}
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
uint8_t hdsz = 0x4a; // size flag in header. either 4a, 4b or 4c.
int romsize = 0x2000;
while (romsize-16 < fsize) {
romsize *= 2;
hdsz++;
if (romsize > 0x8000) {
fprintf(stderr, "binary too big\n");
return 1;
}
}
uint16_t chksum = 0;
for (int i=0; i<romsize-16; i++) {
int c = getc(fp);
if (c == EOF) c = 0;
putchar(c);
chksum += c;
}
// and now, the header
printf("TMR SEGA");
putchar(0);
putchar(0);
putchar(chksum & 0xff);
putchar(chksum >> 8);
putchar(0);
putchar(0);
putchar(0);
putchar(hdsz);
return 0;
}