GenDev SpritesMind Website SpritesMind.Net
Sega Megadrive/Genesis development
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Smallest 'Useful' MD ROM
Goto page 1, 2  Next
 
Post new topic   Reply to topic    SpritesMind.Net Forum Index -> Demos
View previous topic :: View next topic  
Author Message
snkenjoi
Newbie


Joined: 06 Aug 2009
Posts: 6

PostPosted: Thu Aug 06, 2009 8:08 pm    Post subject: Smallest 'Useful' MD ROM Reply with quote

First, a little intro.

Some of you will recognise me from Sonic Retro, where I make hacks of the various sonic games. I recently made this 'demo' with stef's devkit that got me interested in spritesmind.

Anyway, I hope you find this an interesting read, it documents my journey to attempt to create the smallest Megadrive ROM that actually does something.

So, first I need some code that does something basic - this is to check that the code actually worked, and that it's relativly small.

The best thing I could think of for this task was to make the screen go green :) The code is a carbon copy from the checksum error routine from 'most' ROMs.

So here is the first revision, with the checksum code pasted after the header I ripped from Sonic 1.

Code:
Vectors:   dc.l $FFFE00, CodeStart, CodeStart, CodeStart; 0
      dc.l CodeStart, CodeStart, CodeStart, CodeStart; 4
      dc.l CodeStart, CodeStart,   CodeStart, CodeStart; 8
      dc.l CodeStart, CodeStart, CodeStart, CodeStart; 12
      dc.l CodeStart, CodeStart, CodeStart, CodeStart; 16
      dc.l CodeStart, CodeStart, CodeStart, CodeStart; 20
      dc.l CodeStart, CodeStart,   CodeStart, CodeStart; 24
      dc.l CodeStart, CodeStart, CodeStart, CodeStart; 28
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 32
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 36
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 40
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 44
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 48
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 52
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 56
      dc.l CodeStart,   CodeStart, CodeStart, CodeStart; 60
Header:      dc.b 'SEGA MEGA DRIVE ' ; Console name
asc_110:   dc.b '(C)SEGA 1991.APR' ; Copyright/Date
DomesticName:   dc.b 'SONIC THE               HEDGEHOG                ' ; Domestic Name
asc_150:   dc.b 'SONIC THE               HEDGEHOG                ' ; International Name
      dc.b 'GM 00001009-00'   ; Version
Checksum:   dc.w $264A      ; DATA XREF: ROM:00000332o
               ; Checksum
asc_190:   dc.b 'J               ' ; I/O Support
RomStartLoc:   dc.l 0         ; ROM Start
RomEndLoc:   dc.l $7FFFF      ; DATA XREF: ROM:00000322o
               ; ROM End
RamStartLoc:   dc.l $FF0000      ; RAM Start
RamEndLoc:   dc.l $FFFFFF      ; RAM End
asc_1B0:   dc.b '                                                          ' ; Notes
      dc.b '      '
      dc.b 'JUE             ' ; Country
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

CodeStart:
   move.l   #$C0000000,($C00004).l
   move.w   #$F0,($C00000).l
   bra.s CodeStart


Which comes out to 532 bytes. Which I feel is somewhat bloated. ;)

Now, there is a lot of spare space in the header. How about we try storing the code in there? Then we just have to branch into it and we'll save loads of space.

So, we change CodeStart to this;

Code:
CodeStart:
   bra.s asc_1B0


To insert the code into the header, the machine code is simply assembled and pasted in the corresponding place.

Code:
   move.l   #$C0000000,($C00004).l
   move.w   #$F0,($C00000).l
   jmp $1B0


becomes

Code:
23FCC000000000C0000433FC00F000C000004EF9000001B0


paste this onto the header at $1B0 and we get;

Code:
00000000 00FF FE00 0000 0200 0000 0200 0000 0200 ................
00000010 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000020 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000030 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000040 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000050 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000060 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000070 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000080 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000090 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000A0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000B0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000C0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000D0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000E0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000F0 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000100 5345 4741 204D 4547 4120 4452 4956 4520 SEGA MEGA DRIVE
00000110 2843 2953 4547 4120 3139 3931 2E41 5052 (C)SEGA 1991.APR
00000120 534F 4E49 4320 5448 4520 2020 2020 2020 SONIC THE       
00000130 2020 2020 2020 2020 4845 4447 4548 4F47         HEDGEHOG
00000140 2020 2020 2020 2020 2020 2020 2020 2020                 
00000150 534F 4E49 4320 5448 4520 2020 2020 2020 SONIC THE       
00000160 2020 2020 2020 2020 4845 4447 4548 4F47         HEDGEHOG
00000170 2020 2020 2020 2020 2020 2020 2020 2020                 
00000180 474D 2030 3030 3031 3030 392D 3030 264A GM 00001009-00&J
00000190 4A20 2020 2020 2020 2020 2020 2020 2020 J               
000001A0 0000 0000 0007 FFFF 00FF 0000 00FF FFFF ................
000001B0 23FC C000 0000 00C0 0004 33FC 00F0 00C0 #.........3.....
000001C0 0000 4EF9 0000 01B0 2020 2020 2020 2020 ..N.....       
000001D0 2020 2020 2020 2020 2020 2020 2020 2020                 
000001E0 2020 2020 2020 2020 2020 2020 2020 2020                 
000001F0 4A55 4520 2020 2020 2020 2020 2020 2020 JUE             
00000200 60AE                                    `.             


514 bytes! Not bad, but if we want to go further than this, we have to learn about the header format.

If you take these bytes from the first line;

00000000 00FF FE00 0000 0200 0000 0200 0000 0200 ................

These point to the location in the ROM where the code starts, we can change this to define a new start location for our code.

So if we change it to say, 0001B0, it'll point to the code in the header and we can remove the trailing branch from the end of the code.

Code:
00000000 00FF FE00 0000 01B0 0000 0200 0000 0200 ................
00000010 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000020 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000030 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000040 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000050 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000060 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000070 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000080 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000090 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000A0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000B0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000C0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000D0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000E0 0000 0200 0000 0200 0000 0200 0000 0200 ................
000000F0 0000 0200 0000 0200 0000 0200 0000 0200 ................
00000100 5345 4741 204D 4547 4120 4452 4956 4520 SEGA MEGA DRIVE
00000110 2843 2953 4547 4120 3139 3931 2E41 5052 (C)SEGA 1991.APR
00000120 534F 4E49 4320 5448 4520 2020 2020 2020 SONIC THE       
00000130 2020 2020 2020 2020 4845 4447 4548 4F47         HEDGEHOG
00000140 2020 2020 2020 2020 2020 2020 2020 2020                 
00000150 534F 4E49 4320 5448 4520 2020 2020 2020 SONIC THE       
00000160 2020 2020 2020 2020 4845 4447 4548 4F47         HEDGEHOG
00000170 2020 2020 2020 2020 2020 2020 2020 2020                 
00000180 474D 2030 3030 3031 3030 392D 3030 264A GM 00001009-00&J
00000190 4A20 2020 2020 2020 2020 2020 2020 2020 J               
000001A0 0000 0000 0007 FFFF 00FF 0000 00FF FFFF ................
000001B0 23FC C000 0000 00C0 0004 33FC 00F0 00C0 #.........3.....
000001C0 0000 4EF9 0000 01B0 2020 2020 2020 2020 ..N.....       
000001D0 2020 2020 2020 2020 2020 2020 2020 2020                 
000001E0 2020 2020 2020 2020 2020 2020 2020 2020                 
000001F0 4A55 4520 2020 2020 2020 2020 2020 2020 JUE             


512 bytes! We have a ROM that actually does something that is the size of a full MD header. It's worth noting that the only emulator that will run the ROMs from this point is Regen. Surely we can't go smaller than this. Or can we...?

Turns out, a lot of the header isn't required. In fact, most of it - the only *requirement* is the first 8 bytes. So if we set the start of the code to $8... we can just paste our code straight afterwards removing almost the entire header.

Code:
00000000 00FF FE00 0000 0008 23FC C000 0000 00C0 ........#.......
00000010 0004 33FC 00F0 00C0 0000 4EF9 0000 0008 ..3.......N.....


32 bytes! Brilliant! That's much smaller, and it still runs in regen.

Of course, we can remove the last three words to bring it down to 24 bytes, too. I'm told this will break eventually, but it works in regen, so I'm keeping it.

We can't get any smaller than this. It's just not possible.

That's what I thought, until I came up with this dirty trick;

Code:
00000000 4E71 23FC C000 0000 00C0 0004 33FC 00F0 Nq#.........3...
00000010 00C0                                    ..             


18 bytes! Can you see what I did?

Part of the code is used to set the start of the code. A nop (4E71) is added to align it to the correct place and then the code sets the start to $0. This then runs through the code again, ignores the nop, and executes the rest as normal - so the bytes used to set the address of the code are reused as part of the code.

I don't know how well I explained that or if you will understand it. Please ask if you don't get it.

===

From this point I'd pretty much called it a day, there wasn't much more i could do to optimise this any further. I sent the ROMs off to TmEE to find out which ones will run on hardware. Unfortunatly none :(. Well, at least they were running on Regen!

Anyway, after this he sent me the smallest ROM he could think of that runs on hardware. 38 bytes! Apparently, the MD required some VDP initilisation that I overlooked. Here is his code;

Code:
; Smallest possible MD program to run on most hardware

 DC.L   $00FFFE00       ; Default A7, Padding
 DC.L   CodeStart       ; Default PC
CodeStart:
 LEA    $C00004, A0     ; Makes things a little bit more tighter ;)

 MOVE.L #$80148700, (A0) ; Initialize VDP into enough nice state
 MOVE.W #$8134, (A0)
 MOVE.L #$C0000000, (A0)
 MOVE.W #$0FF0, -4(A0)
 BRA.B  CodeStart


Note; this will work on non-TMSS hardware only, TMSS based ROMs have a lower bound and trying to make them small is fairly trivial and uninteresting.

Anyhoo, as you can see the code is pretty compact leaving little room for optimisation. That doesn't mean I didn't try anyway ;)

Here is my final piece of code. With use of the trick I demonstrated before, and a little shifting around of the code, I managed to get it down to 32 bytes. Just trace the execution of this thing, it's beautiful.

Code:
Start:
 bra.s CodeStart
 dc.w   $20BC           ; this and instruction below are executed as;
 dc.l   $C0000000       ; move.l #$C0000000, (a0)
CodeStart:
 move.w #$F0,-4(a0)  ; does nothing the first run through ;)
 lea    $C00004,a0
 move.l #$80148700,(a0)
 move.w #$8134,(a0)
 bra.s Start+2


Code:
00000000 6006 20BC C000 0000 317C 00F0 FFFC 41F9 `. .....1|....A.
00000010 00C0 0004 20BC 8014 8700 30BC 8134 60E2 .... .....0..4`.


download

On a side note, qiuu suggested that the smallest valid ROM (that doesn't do anything) would be 2 bytes long (assuming padding is 00s). bra.s -2 / '60FE'. This actually works in Regen :D

And that's about all I have to say for my first post. Hopefully next time I post a demo, it'll do a more than just this ;)
Back to top
View user's profile Send private message
Shiru
Very interested


Joined: 07 Apr 2007
Posts: 786
Location: Russia, Moscow

PostPosted: Thu Aug 06, 2009 10:57 pm    Post subject: Reply with quote

This is surely interesting information for 256/512b intro or minigame (1K/2K/4K) creators.

I think, relying for padding zeroes is somewhat wrong, because in the real world if you have, say, 256 byte ROM chip, it will not have zeroes above 256 byte. Instead, it will be repeated throughout whole address space.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Chilly Willy
Very interested


Joined: 17 Aug 2007
Posts: 2360

PostPosted: Thu Aug 06, 2009 11:02 pm    Post subject: Reply with quote

Most of the exception vectors will never get called, so you could easily use most of that space for code. The rom header should probably be left alone, but you could also stick code or data in the strings of the header.
Back to top
View user's profile Send private message
HardWareMan
Very interested


Joined: 15 Dec 2007
Posts: 584
Location: Kazakhstan, Pavlodar

PostPosted: Fri Aug 07, 2009 7:05 am    Post subject: Reply with quote

Chinese programmers don't fill required header (except vectors table) and they games run only on chinese MD clones (without TMSS). So, to run your code on MD with TMSS you will need to fill only used vectors and string at $100..$103 (wich contains "SEGA" word, that presence checked by TMSS). All other places can be filled your own data/code.
Back to top
View user's profile Send private message
TascoDLX
Very interested


Joined: 06 Feb 2007
Posts: 246

PostPosted: Fri Aug 07, 2009 7:07 am    Post subject: Re: Smallest 'Useful' MD ROM Reply with quote

snkenjoi wrote:
Here is my final piece of code. With use of the trick I demonstrated before, and a little shifting around of the code, I managed to get it down to 32 bytes. Just trace the execution of this thing, it's beautiful.

Nice, but it could be shorter. You get a free register load because of the stack pointer, and you're moving 2 words that you can fit into 1 longword.

Here is 28 bytes:
Code:
Stack:
dc.l   $00C00004         ; a7 = 00C00004
Data:
dc.l   $C0000008         ; pc = Start
Start:
move.l #$87008004,(a7)   ; vdp reg set = 8700, vdp reg set = 8004
move.l Data,(a7)         ; vdp addr set = C0000008 (bit 3 ignored by vdp)
move.l #$0E8E8104,-2(a7) ; vdp data write = 0E8E (pink!), vdp reg set = 8104
Done:
bra.s  Done

Code:
000000 : 00C0 0004 C000 0008 2EBC 8700 8004 2EBA
000010 : FFF4 2F7C 0E8E 8104 FFFE 60FE

Download here

I don't think it can get any shorter.

snkenjoi wrote:
It's worth noting that the only emulator that will run the ROMs from this point is Regen.

Fusion works fine (unless you've set it up to use the TMSS BIOS).
Back to top
View user's profile Send private message Send e-mail
TmEE co.(TM)
Very interested


Joined: 05 Dec 2006
Posts: 2167
Location: Estonia, Rapla City

PostPosted: Fri Aug 07, 2009 11:30 am    Post subject: Reply with quote

and TascoDLX pwns everyone Razz
_________________
Mida sa loed ? Nagunii aru ei saa Wink
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Chilly Willy
Very interested


Joined: 17 Aug 2007
Posts: 2360

PostPosted: Fri Aug 07, 2009 3:40 pm    Post subject: Reply with quote

That won't work on all Genesis models, so it doesn't count. Razz

As stated in another post by HardWareMan, you at least need the "SEGA" in the header or TMSS systems won't accept it.
Back to top
View user's profile Send private message
TmEE co.(TM)
Very interested


Joined: 05 Dec 2006
Posts: 2167
Location: Estonia, Rapla City

PostPosted: Fri Aug 07, 2009 3:43 pm    Post subject: Reply with quote

so you have a 230 byte ROM with lot of nothingness in it Razz
_________________
Mida sa loed ? Nagunii aru ei saa Wink
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Chilly Willy
Very interested


Joined: 17 Aug 2007
Posts: 2360

PostPosted: Fri Aug 07, 2009 5:09 pm    Post subject: Reply with quote

260 Razz
Laughing
Back to top
View user's profile Send private message
TmEE co.(TM)
Very interested


Joined: 05 Dec 2006
Posts: 2167
Location: Estonia, Rapla City

PostPosted: Fri Aug 07, 2009 5:55 pm    Post subject: Reply with quote

craaap.... I somehow got 226 in my mind..... my brain needs sleep which it has not got for a while Razz
_________________
Mida sa loed ? Nagunii aru ei saa Wink
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
snkenjoi
Newbie


Joined: 06 Aug 2009
Posts: 6

PostPosted: Sat Aug 08, 2009 5:14 pm    Post subject: Re: Smallest 'Useful' MD ROM Reply with quote

Chilly Willy; You didn't read this >:|

snkenjoi wrote:
Note; this will work on non-TMSS hardware only, TMSS based ROMs have a lower bound and trying to make them small is fairly trivial and uninteresting.


I know about the TMSS, guys.

TascoDLX wrote:
snkenjoi wrote:
It's worth noting that the only emulator that will run the ROMs from this point is Regen.

Fusion works fine (unless you've set it up to use the TMSS BIOS).


I meant for all the non-hardware ROMs, I shoulda clarified.

TascoDLX wrote:
Code:
000000 : 00C0 0004 C000 0008 2EBC 8700 8004 2EBA
000010 : FFF4 2F7C 0E8E 8104 FFFE 60FE


This is brilliant. I really admire your use of the stack pointer.

You might argue the validity of what I'm going to say next, but I believe it counts.

I believe 26 bytes is possible by simply truncating your example to 26. This will cause the game to crash eventually. However, this will not change the graphics on the screen - resulting in the same behaviour as the infinite loop anyway. This leads me to think you can just drop it. Ugly, but it works. (I think?)

Code:
00C00004C00000082EBC870080042EBAFFF42F7C0E8E8104FFFE
Back to top
View user's profile Send private message
Chilly Willy
Very interested


Joined: 17 Aug 2007
Posts: 2360

PostPosted: Sat Aug 08, 2009 6:12 pm    Post subject: Re: Smallest 'Useful' MD ROM Reply with quote

snkenjoi wrote:
Chilly Willy; You didn't read this >Neutral

snkenjoi wrote:
Note; this will work on non-TMSS hardware only, TMSS based ROMs have a lower bound and trying to make them small is fairly trivial and uninteresting.



Sure I did. That doesn't change my position that unless it works on all (official) models, it doesn't count. It's not so much that the minimum size is 260 bytes as much as what you do with it. Who gives a rat's ass if you can do a "loop: bra loop" demo - I want a tiny demo that really does something (and works on any model). Cool

Without TMSS, the smallest rom possible is always going to be 10 bytes: the reset SSP, the reset PC, and one bra.b opcode. There's nothing special about that. That won't earn anything more than "Noob...". Rolling Eyes

You want praise? Make pong in 260 bytes (or something similar).
Back to top
View user's profile Send private message
snkenjoi
Newbie


Joined: 06 Aug 2009
Posts: 6

PostPosted: Sat Aug 08, 2009 8:03 pm    Post subject: Reply with quote

Maybe it doesn't count in your eyes. That's fine.

But you're still missing the point. Thankfully you don't govern what I can and can't try to do :)

(Besides, it does do something... it detects if you have TMSS or not ;)

I'm not looking for praise, I'm saying "Hi guys, I joined the forum. Here's something cool I did recently that you may find interesting."

You don't have to be such an arse about it :(.
Back to top
View user's profile Send private message
Chilly Willy
Very interested


Joined: 17 Aug 2007
Posts: 2360

PostPosted: Sat Aug 08, 2009 8:21 pm    Post subject: Reply with quote

Sorry, but "loop: bra loop" demos are LAME, not interesting. You'd have a be a complete noob to think otherwise. Just telling it like it is. Twisted Evil

And to tell the truth, when someone comes along gushing about how fantastic such things are, yes, I DO have to be an arse about it. Wink

Feel free to share your "exciting" potty training stories, but don't get mad at me when I laugh and point. Laughing
Back to top
View user's profile Send private message
Shiru
Very interested


Joined: 07 Apr 2007
Posts: 786
Location: Russia, Moscow

PostPosted: Sat Aug 08, 2009 8:26 pm    Post subject: Reply with quote

If you have real 256 byte ROM, word 'SEGA' probably could be placed at $000, but if it is possible to make the code start somehow after that? I don't know 68K opcodes, what 'SEGA' would be as code?
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    SpritesMind.Net Forum Index -> Demos All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group