• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Removing startup artifacts of "improved" ROM SE/30!!!

zuiko21

Well-known member
Thanks to the amazing efforts of dougg3 and others on this group, I'm on the way of putting a "decent" display during the startup of a SE/30 with alternative ROM...



As specified on flickr's caption, that SE/30 has no disk drive at all -- floppy, HD or CD. Only the Jolly Roger ROM SIMM, which in turn has no trace of any original Apple ROM: just that (very sinister) picture of me, a sampled sound and the (tiny) code to show them. I wrote the display part, and the sound playing code came from Doug's custom startup sound ROM.

Still there are things to smooth out, though. Despite the code being well tried and tested, the sound is heavily distorted :?: ; something doesn't match well my own code, or it just need some other initialisation -- this ROM does nothing else!

But it's a start. It can be done. :cool:

 

Trash80toHP_Mini

NIGHT STALKER
VERY :cool: there, z! For the next rev, swap the spectacles for an eye-patch and substitute a famous pirate movie parrot's cackling rendition of an appropriate line! [;)] ]'>

I can cheer you buccaneers on from the sidelines, but I'm clueless when it comes to your level of hacking. [:I] ]'>

 

dougg3

Well-known member
Awesome!! BTW, zuiko21 is the first one to test out my Mac ROM SIMM programmer board, and it seems to be working for him!

I'm not sure why the sound is distorted. Maybe the Apple ROM does some other initialization of the sound chip somewhere...

 

zuiko21

Well-known member
So far, the contains the following:

1) The Reset Vector: the first four bytes (where the checksum usually goes) are meant to be the initial value for the stack pointer; but since RAM is disabled so far (ROM overlay mode) it would be meaningless anyway. Then goes the code's starting address, I pointed it to 0x4000008 -- right after the vector. Despite being read from what would become RAM, it jumps to the usual ROM address range. I don't bother switching off the ROM overlay, though.

2) My code for displaying the picture; it was assembled by hand and wrote into the ROM with a hex editor (Hex Fiend). After some tweaking, I ended up using something crude like this:

Code:
PutPic: LEA Picture, A0         ;the picture stored in ROM
       LEA 0xFE008000, A1      ;address of the frame buffer
       MOVE.W #0x1560, D0      ;number of long words on a screen
Loop:   MOVE.L (A0)+, D1        ;loads a long word from the picture
       MOVE.L D1, (0x8000, A1) ;writes on the alternate buffer
       MOVE.L D1, (A1)+        ;writes on the main buffer, and avances to next long word
       SUBQ.W #1, D0           ;one long word less to go
       BNE.S Loop              ;repeat until it's finished
Not sure which is the main screen buffer and which is the alternate buffer, so I wrote the picture data in both :b&w: In fact, the 16-bit offset in MOVE.L D1, (0x8000, A1) seems to be signed and working backwards from intended, thus I placed that 0x8000 offset into the base address (see 2nd opcode), otherwise it didn't work -- I don't know which buffer is shown at startup time, either :I

3) dougg3's code for sampled startup sound, but supressing the final return instruction because this wasn't called from anywhere ;)

4) A STOP instruction -- supposedly halts the CPU and keeps it waiting for an interrupt... which would be catastrophic anyway, without any RAM/stack available xx(

5) The bitmap of my picture (512x342, 1-bit). I made it in CS5 after resizing/converting/dithering the original almost-as-sinister photo ;) Saved it, inverted (the Mac's screen is substractive: "1" means black pixel) as Wireless Portable Bitmap which contains the raw data after a small header, easily edited off with Hex Fiend

6) The sound sample (this address hardwired into Doug's code) after the preceptive 4-byte header indicating the sample's length. Again took it from the original 8-bit 22kHz AIFF after stripping the header.

And that's all! The code is actually playing the sample (not just static) and for the proper length; but the distortion could be caused by the lack of further initialization, as said -- I presume Doug's code originally executed after a great deal of Apple's ROM code.

A weird thing, however, is that after 45 seconds or so it does play again the sample! And keeps doing so every after... :?:

 

Gorgonops

Moderator
Staff member
A weird thing, however, is that after 45 seconds or so it does play again the sample! And keeps doing so every after... :?:
Some uninitialized part of the hardware is acting as a "watchdog timer" and triggering a reset after roughly 45 seconds? (So you're basically just rebooting over and over again, but since the picture-drawing loop is just stuffing the same data into the video buffer over and over again you're not seeing any visual indication?)

 

Charlieman

Well-known member
Does behaviour change if you modify RAM size, SCSI bus, ADB, external floppy drive presence, serial port impedance?

 

dougg3

Well-known member
Interesting...aside from the other suggestions, one other idea. After doing the STOP instruction, maybe the CPU wakes back up due to an interrupt of some kind, going past the STOP instruction and executing garbage instructions (whatever 0xFFFF... represents in machine code) until it falls through to the sound code. Have you put the STOP instruction inside an infinite loop? If not, it might be worth a try...

 

zuiko21

Well-known member
Some new info: multiplying the (approximately timed) 45 seconds by 22254 samples/sec gives a figure close to a suspiciously round 1 MiB -- add the fact that the second and subsequent times the sample gets played, it's preceeded by a buzzing sound for a moment, not heard just after reset... :-/

So I did another experiment: right after the code and data previously flashed, I wrote several repetitions of a number sequence (0x05-0A-0F-15-1A-1F-25-2A-2F... you get the idea) which, if played by the sound hardware, would make a sawtooth waveform of about 440 Hz -- an easily spotted sound! I filled up to 256 kiB of ROM this way, reflashed and... it plays the sawtooth, right after the (distorted) sample 8-o Sounds more like 880 Hz, though. Some kinds of distortion could double the frequency of a single wave, indeed; but it's definitely playing fast: after discounting the picture data, the 256 kiB should play for roughly 10 seconds at 22 kHz, but it's doing like 5 s... It wouldn't surprise me if this unexpected speed comes from the lack of a proper initialization of the sound chip -- Yamaha's YM2149 sound chip had a clock speed doubling feature, maybe Apple's has something similar (and it's reset somewhere in the original ROM's code)?

But what really amazes me is the fact that Doug's known good code isn't stopping at the end of the sample... I've double checked that the four-byte header with the sample's length in big-endian format is properly formed in front of the sample, and its address correctly stated in the related LEA of the playing code -- unless Hex Fiend is cheating on me, of course :?: And no matter how hard I try scrutinizing doug's code, I can see no way it could fail doing the right amount of samples...

The only chance would be a mysterious change of D0/D1 values... I could only think of an interrupt, but I'm under the impression that, in the current state (ROM overlay mode, no available RAM, no stack and no propely loaded Interrupt Vectors!) such event would totally crash the computer xx( However, just in case, as soon as I get back home I'll add an interrupt-disable instruction to the code...

BTW: the tests were done with 20 MiB RAM, although in ROM overlay mode that should be irrelevant -- tried last night with NO installed RAM, exactly same results. No ADB devices were connected, nothing on the serial ports, no floppy drive (internal or external). This particular machine has a SCSI failure -- the chip itself (and its connections to the CPU) is fine, but DB2 line is not connected to the SCSI bus (internal or external).

 

dougg3

Well-known member
Weird!

I would have to agree -- the sound loop seems to be running past its bounds, which could only happen if D0 or D1 were being externally modified while the loop was running--for example, by an interrupt. But since you don't have any interrupt vectors yet, it would probably crash (like you said) or do something incredibly goofy. Did the behavior still happen after you disabled interrupts?

In case anyone's wondering, here's how I disabled interrupts when I was experimenting with sampled startup chimes:

Code:
ori #$0700, sr ; Disable interrupts (interrupt priority level = 7)
 

zuiko21

Well-known member
Weird, certainly... Yesterday was a hard day at work, and in a few minutes I'll hop into the car and stay out of town all day -- not much time to tinker with the ROM, I'm afraid :'(

On the interrupt suspicion, my only evidence so far is that pressing the NMI/programmers button stops whatever my ROM is doing -- as expected. I expect to get back into the hacking scene by Friday evening or Saturday, I'll check out then. Thanks for the reminder on disabling the 680x0 interrupts!

If nothing improves, I can try loading manually the sample's length into your code -- that is, not reading it from the header, just in case I got the numbers wrong (even if I double checked it...)

Another thing to do, once this is sorted out, would be checking the actual machine model -- I don't think it's a good idea to draw the picture from this ROM on a Mac II, assuming it has the video hardware of the SE/30 xx(

Patience... |)

 

zuiko21

Well-known member
Got it!

After tidying up the ROM contents, things were more or less like before, but now playing at the right speed: ≈11 seconds for 256 kiB ROM, repeating the whole cycle after about one-and-a-half minute -- twice the previous values. Disabling interrupts, changing the sample's length and/or its address made absolutely no difference :?:

I eventually discovered where the problem was -- a matter of assembler syntax! Yes, assembler and not assembly...

Both my source code and yours use a LEA address, A0 instruction at the beginning... but with different addresing modes! While yours (opcode 0x41FA) uses a 16-bit relative offset (which makes a lot of sense since in your version the sample was right after the code), I was using a 32-bit absolute address (opcode 0x41F9 for increased flexibility). When I inserted your code besides mine, I dumbly assumed that your LEA was like mine, and filled the following 32 bits with the absolute address -- actually "eating out" some of the initialization code! :I

Now, the sample is played at the proper position and length (like your original ROM did, of course) and your code finishes properly -- I added an infinite loop after that, working as a 32-bit counter on the screen itself, and I can see the pixels changing quickly as expected.

However, there's still the problem of distorted playback -- something else has to be intialized, it was done somewhere in the original ROM...

 

dougg3

Well-known member
Ah, nice detective work! What are you using as an assembler? I've been using GNU as, which does have some annoying syntax, like the % before register names. The various addressing modes that GNU tools expect look weird, too (it's called AT&T syntax, I think). That's probably where the confusion comes from. If I had something that used the more common syntax, I'd use it instead.

As for the sound distortion, hmm. I noticed my sound code doesn't touch the ASC register at $802, which the MAME/MESS source code says is a control register. Maybe messing with the contents of that register would help...

 

zuiko21

Well-known member
Back again...

Assembler? :lol: So far I've been assembling by hand...

Anyway, while I get a reasonable tool somewhere, I experimented with the register at $0802 -- just putting your code inside a loop that will try every single value for that register, stored in otherwise unused D3. For debugging purposes, I "placed" that byte on the screen so I can see what's going on. Here's what I flashed lastly on the Jolly Roger SIMM:

Code:
40000000    0000000040800008  ;SP-PC Reset

;disable interrupts... just in case

40000008    007C0700          ;MOVE #0x0700, SR

;put image at 0x40001000 on screen

4000000C    41F940001000      ;LEA Picture, A0
40000012    43F9FE008000      ;LEA VideoBuffer, A1
40000018    303C1560          ;MOVE.W #0x1560, D0
4000001C*1  2218              ;MOVE.L (A0)+, D1
4000001E    23418000          ;MOVE.L D1, (0x8000, A1)
40000022    22C1              ;MOVE.L D1, (A1)+
40000024    5340              ;SUBQ.W #1, D0
40000026    66F4              ;BNE.S *1

;loop for trying every 0x802 value!

           7600              ;MOVEQ #0, D3  ;init value
*8          13C3FE001877      ;MOVE.B D3, BYTE  ;show on screen
           13C3FE009877      ;MOVE.B D3, BYTE2
           17430802          ;MOVE.B D3, (0x802, A3)  ;set reg

;dougg3's sampled sound code (at absolute address 0x40007000)

           47F950F14000      ;LEA 0x50F14000, A3
           41F940007000      ;LEA Sample, A0  [41FA-"rel16"]
           177C00010801      ;MOVE.B #0x01, (0x801, A3)
           422B0807          ;CLR.B (0x807, A3)
           177C00400806      ;MOVE.B #0x40, (0x806, A3)
           277CFE00FE000830  ;MOVE.L #0xFE00FE00, (0x830, A3)
           277CFE00FE000834  ;MOVE.L #0xFE00FE00, (0x834, A3)
           177C00800803      ;MOVE.B #0x80, (0x803, A3)
           422B0803          ;CLR.B (0x803, A3)
           4A2B0804          ;TST.B (0x804, A3)
           2018              ;MOVE.L (A0)+, D0
           2200              ;MOVE.L D0, D1
           4841              ;SWAP D1
           6014              ;BRA.S *5
*2          082B00010804		;BTST #1, (0x804, A3)  ;PSIC
           6708              ;BEQ.S *4
*3          082B00000804		;BTST #0, (0x804, A3) ;WHE
           67F8              ;BEQ.S *3
*4          1418              ;MOVE.B (A0)+, D2  ;DS
           1682              ;MOVE.B D2, (A3)
*5          51C8FFEA          ;DBF D0, *2  ;NS
           51C9FFE6          ;DBF D1, *2
*6          177C00010801      ;MOVE.B #0x01, (0x801, A3)
           422B0807          ;CLR.B (0x807, A3)
           177C00400806      ;MOVE.B #0x40, (0x806, A3)
           277CFE00FE000830  ;MOVE.L #0xFE00FE00, (0x830, A3)
           277CFE00FE000834  ;MOVE.L #0xFE00FE00, (0x834, A3)
           177C00800803      ;MOVE.B #0x80, (0x803, A3)
           422B0803          ;CLR.B (0x803, A3)
           4A2B0804          ;TST.B (0x804, A3)

;loop's end

           5203              ;ADDQ.B #1, D3  ;next value
           6600FF60          ;BNE *8

;put a counter on the screen saying we're finished

*7          53B9FE001844      ;SUBQ.L #1, SITIO
           53B9FE009844      ;SUBQ.L #1, SITIO2
           60F2              ;BRA.S *7
Now, the bad news :( None of the values played the sample cleanly, although the effect of some bits of this register became evident:

D0: disables sound (if set to "1")

D1: makes sound weaker (volume control?)

D3: makes sound even weaker (can be combined with D1 for further attenuation)

Not sure if any other bits had effect on the sound, but at least we know something more about the ASC :b&w:

There has to be some other obscure initialization pending...

 

tt

Well-known member
Cool stuff zuiko21! I am thinking your code would be a good basis for making some kind of slide-show or animation that would be totally self-contained within a ROM if there's enough room. Could be some kind of art project or display without worrying about floppy disks and hard drives.

 

tt

Well-known member
Zuiko21, the code you posted, is that the entire code to get from boot to image display? I'm not too familiar with assembly...I was wondering how you did this, and maybe try it out on my own machine. Maybe like have a ROM base for booting up showing an image, then concatenate any image in the proper format at the end of that file. Maybe the base could have a byte for changing how many total images are appended and another for dwell time for each image and then concatenate the images in the sequence desired.

 

zuiko21

Well-known member
tt, your idea is quite feasible and interesting!

The actual code for displaying a picture is about a 25% of the whole listing, just anything above the line:

Code:
;loop for trying every 0x802 value!
and could be somewhat simpler with a bit of optimization -- this was a quick-and-dirty approach :b&w:

I'm currently on holidays so I don't have the developer resources at hand ;) but I think the simplest way would be concatenating the 22 KB blocks for each picture after the code, then adding an empty loop for the desired delay between pics, and then jumping back to the code without resetting the image pointer, thus the following addresses are read. As you propose, this final loop should be done only for the specified number of pictures.

 

onlyonemac

Well-known member
Are you sure that turning the volume down (registers D1/D2) wouldn't take the distortion off? (i.e. It's simply playing too loud, like a guitar amp on max.)

 
Top