Macintosh ROM Hacking II (startup sound change)


 2016.04.24.(日)

EPROM을 재프로그래밍 할 수 있다고 하지만 UV로 지우는데 생각보다 어려운 일이었다.
그래서 EEPROM을 재주문했다. 하지만 판매자 신뢰가 낮아 도착까지 오래 기다려야 할 듯 하다.

ROM 주문과 별개로 롬파일을 가지고 사운드 변경에 도전해 보았다.

시동음을 변경시키는 것은 아이콘변경과 비교하여 매우 어렵다.
특히 음악에 문외한인 나에게는 더욱 어려웠다.

우선 기계음(?) 과 녹음음(sampled)으로 정리를 해보았다.

- 기계음 : PWM으로 가청주파수(20Hz~20,000Hz) 를 만들어 내고 음계에 맞는 주파수를 정의해 소리를 낸다.
- 녹음음 : 소리를 녹음해 그 정도값을 2진수화 해서 합성기에서 소리를 낸다.

27c400 27e257

flash rom : 2M SST 39SF040(512K x 8) x 4개
              1M AT29C020(256 x 8) x 4개
              8M Micron M29F160FB5AN6E2 x 4개

IIci
Apple sound chip address
0x50014000
0x50016000 : IIsi sound chip address
0x50054000
0x50094000
~
0x50F14000
0x50FD4000

스타트업 사운드를 재생시키려면 0x408435BC 주소로 간다 !  $435D0

$435D0   41F9 FFFC 3A82  LEA.L   ($-3C57E), A0   ; FFFC 3A82 반전 3C57D+1(2의 보수) = 3C57E
     
            435D0-3C57E = $7052 ; BootBeep6 으로 가라는 코드 있음

            51D70~5A820 (반복코드로 여기에 커스텀 사운드 코드 삽입)

$435D0   41F9 0000 E7A0  LEA.L ($-F185F), A0 ;  $51D70으로 가라는 소스

IIsi

$45C12   41F9 FFFC 1440  LEA.L   ($-3EBC0), A0   ; FFFC 1440 반전 3EBBF+1(2의 보수) = 3EBC0

            45C12-3EBC0 = $7052 ; BootBeep6 으로 가라는 코드 있음

            4BF28~51D40 (반복코드로 여기에 커스텀 사운드 코드 삽입)

SE/30

$4122A  41F9 FFFC 5E28

$4122A  41F9 0001 0846

ClassicII      $45C68 (?)

$45C12   41F9 FFFC 1440  LEA.L   ($-3EBC0), A0   ; FFFC 1440 반전 3EBBF+1(2의 보수) = 3EBC0

            45C12-3EBC0 = $7052 ; BootBeep6 으로 가라는 코드 있음

            4D228~51220 (반복코드로 여기에 커스텀 사운드 코드 삽입)

$45C12   41F9 0000 7616 LEA.L ($-F89EA), A0 ;  $4D228로 가라는 소스

빈공간도 발견했으니 그 빈공간에 음악을 써 넣어주면 된다.

1) 녹음음
    - 녹음음(샘플된 음)을 먼저 만들어 주어야 한다.
      특별한 장비가 없기에 개러지 밴드에서 그랜드피아노로
      '솔~솔솔~도~' 음을 만들어 디스크로 보내기(MP3 압축, 224kbps) 해서 녹음음을 만들었다.
      이 음을 Apple Sound chip 이 연주할 수 있게 변형해 주어야 한다.
      변형은 무료 Audacity 프로그램을 이용한다.

      Audacity 에서 MP3 파일을 열면 스테레오 음이 열린다. 음악데이터를 모노, 16비트 PCM, 샘플레이트
      22250Hz 로 바꾸어준다. 스테레오에서 분리된 나머지는 삭제한다.
      파일메뉴의 export audio 를 선택하고 파일형식을 기타 비압축 파일, 옵션으로 헤더를 RAW(header less)
      인코딩을 unsigned 8 bit PCM 으로 바꿔서 저장한다.
      단 파일크기가 빈공간(약 32K)보다 크면 당연히 안된다.
     
      내가 만든 음(?)은 큰 의미가 없고 페르시아왕자에서 처음 칼을 잡았을 때의 음을 흉내낸 것이다.
      그런데 이렇게 간단하게 녹음된 음도 크기가 너무 커서 결국 '솔~도-' 하는 이상한 음으로 변형됐다.

     헥스에디터에서 녹음음의 크기를 확인하고, Brown Doug 가 연구해 낸 연주코드를 빈공간 시작부위에
     삽입한다. 샘플된 사운드를 연주하기 위해 LC3 롬파일을 참조해 Browm Doug 가 만들어 냈다고 한다.
     140 바이트의 짧은 코드다. 그리고 녹음음의 크기를 4 바이트 빅 엔디언 정수로 써 넣는다.
     (빅 엔디언 정수라 복잡한 줄 알았는데 그냥 음악데이터 크기를 4바이트 헥스값으로 적어주면 된다)
     그리고 헥스에디터에서 읽은 녹음음을 복사해 붙여 넣어주면 완성이다.

     여기까진 오히려 쉬웠다. IIci 에서 시동음으로 '솔~도-' 하는 기괴한 음이 나오는 걸 금방 확인할 수 있다.

     doug 에게서 8M rom Simm을 2년 전에 구입했기에 사실 빈 공간을 찾을 필요없이 나머지 공간에
     녹음음을 마음껏 삽입하고 연주하면 되지만 그건 뒤로 미루기로 했다.

2) 기계음(?)
   - 사실 기계음이 진정한 도전이었다. 음질은 확실히 녹음음에 비해 떨어지지만 데이터 크기가 작아
     긴 음악을 연수 할 수 있기 때문이다.
     기계음을 연주하기 위해 배경지식이 필요하고 고정소수점 연산이라는 방법도 알아야만 했다.
     결국 고정소수점값을 Hz로 변경하는 것은 알수 없어서 Doug에서 다시 한번 메일을 보내야만 했다.

     배경지식

     ASC(Apple Sound Chip)은 데이터를 처리할 때 고정소수점 9.15 형식을 사용한다.
     $000143EF 는 24비트 2진수로 0000 0001 0100 0011 1110 1111 이다.
     정수부는 상위 9 비트, 소수부는 하위 15비트 이다.
     정수는 1*2^1+0*2^1 = 2
     소수는 1*2^(-1)+1*2^(-6)+1*2^(-7)+1*2^(-8)+1*2^(-9)+1*2^(-10)+1*2^(-12)+1*2^(-13)+1*2^(-14)+1*2^(-     15) = 0.530731201171875

     즉 $000143EF 는 10진수로 2.530731201171875 라는 의미다.
     그럼 2.5307312... 는 몇 Hz 인가?

     공식은 decimal value * ASC fr / 2^9 = fr (Hz)

     여기까지 간신히 왔지만 이건 단순한 음악데이터의 일부분일 뿐이다.
     롬의 빈공간에 넣어보았자 1단위(동시에 연주되는 4화음)의 음만 연주하고 끝낼것이다.
     1단위를 여러개 연결해서 하나의 음악을 연주하도록 해야 한다.
     그래서 다음과  같이 시도해 보았다.
    
  IIci 에서 기계음 연주

  51D70 주소에 다음 코드를 삽입하면 bootbeep 후 에러 아르페지오 연주를 하고 시동단계로 나아간다.
 
  49 FA 00 EC 42 2B 08 01 42 2B 08 07 30 1C E5 48 4A 2B 08 00 66 02 EA 48 17 40 08 06 70 01 4A 2B 08
  00 66 02 70 00 17 40 08 02 41 EB 08 10 70 1F 42 18 51 C8 FF FC 70 FE 10 C0 10 C0 10 C0 10 C0 10 C0
  10 C0 10 C0 10 C0 17 7C 00 02 08 01 42 2B 08 03 20 3C C0 01 FF 40 4A 2B 08 00 66 06 20 3C 30 01 3F
  10 20 4B 72 1F 74 3F 10 C0 51 CA FF FC E0 98 51 C9 FF F4 4C DC 00 07 36 1C 7A 00 4B ED 1C 00 43 EB
  08 14 20 4B 47 EB 02 00 60 24 18 18 B7 C8 62 04 41 E8 FE 00 D8 10 E2 14 11 44 06 00 11 44 04 00 11
  44 02 00 10 84 38 00 4A 15 51 CC FF FC 51 CD 00 14 4A 43 67 0E 3A 01 12 DC 12 DC 12 DC 12 DC 58
  49 53 43 51 CA FF C4 47 EB FE 00 4B ED E4 00 41 EB 08 14 74 03 42 18 42 18 42 18 42 18 58 48 51 CA
  FF F4 42 2B 08 01 60 20 02 04 00 00 00 0D 00 00 01 2C 00 00 75 30 00 04 00 01 80 00 00 02 00 00 00
  01 81 79 00 03 00 00 49 FA 00 EC 42 2B 08 01 42 2B 08 07 30 1C E5 48 4A 2B 08 00 66 02 EA 48 17 40
  08 06 70 01 4A 2B 08 00 66 02 70 00 17 40 08 02 41 EB 08 10 70 1F 42 18 51 C8 FF FC 70 FE 10 C0 10
  C0 10 C0 10 C0 10 C0 10 C0 10 C0 10 C0 17 7C 00 02 08 01 42 2B 08 03 20 3C C0 01 FF 40 4A 2B 08 00
  66 06 20 3C 30 01 3F 10 20 4B 72 1F 74 3F 10 C0 51 CA FF FC E0 98 51 C9 FF F4 4C DC 00 07 36 1C 7A
  00 4B ED 1C 00 43 EB 08 14 20 4B 47 EB 02 00 60 24 18 18 B7 C8 62 04 41 E8 FE 00 D8 10 E2 14 11 44
  06 00 11 44 04 00 11 44 02 00 10 84 38 00 4A 15 51 CC FF FC 51 CD 00 14 4A 43 67 0E 3A 01 12 DC 12
  DC 12 DC 12 DC 58 49 53 43 51 CA FF C4 47 EB FE 00 4B ED E4 00 41 EB 08 14 74 03 42 18 42 18 42 18
  42 18 58 48 51 CA FF F4 42 2B 08 01 4E D6 06 07 00 00 00 2B 00 00 0B B8 00 00 61 A8 00 04 00 01 43
  EF 00 01 94 EB 00 01 E5 E7 00 02 89 57 00 00 00 00

  맨마지막 00 00 00 00 은 그냥 넣어준 코드임

  어셈블러로 번역하면 다음과 같다

  49 FA 00 EC    ; Lea.L BootBeep6Data, A4  ; 49 FA 이후 236 바이트 어드레스(EC offset) 주소를 불러온다
  42 2B 08 01    ; Clr.B $801(A3) ; ASC mode = 0 (off?)   modified PlaySynth 시작 ~
       ~
  42 2B 08 01    ; Clr.B $801(A3) ; ASC mode = 0 (off?)   deinitLoopDone
  60 20            ; Bra  연주 후 32 바이트 뒤로 점프
  02 04 ~         ; BootBeep6Data  32 바이트 크기
  49 FA 00 EC    ; Lea.L OrigErrorBeep4Data, A4  49 FA 이후 236 바이트 어드레스(EC offset) 주소를 불러온다
  42 2B 08 01    ; Clr.B $801(A3) ; ASC mode = 0 (off?)   modified PlaySynth 시작 ~
       ~
  42 2B 08 01    ; Clr.B $801(A3) ; ASC mode = 0 (off?)   deinitLoopDone
  4E D6            ; Jmp A6  연주 후 원래 호출 주소로 돌아간다.
  06 07 ~         ; OrigErrorBeep4Data  32 바이트 크기

  원래 롬은 BootBeep6 만 연주하도록 되어 있어서 에러 아르페지오 도 연속적으로 연주가 가능한지 반신반의
  하면서 코드를 만들었는데 예상외로 한번에 성공하였다.
 
  이제 음악코드만 준비하면 된다.

  옥타브   음계명       주파수(Hz) 
     2        라(A)        110.000
               A#          116.541
               시(B)        123.471
     3        도(C)        130.813
               C#          138.591
               레(D)       146.832
               D#          155.563
               미(E)        164.814
               파(F)        174.614
               F#           184.997
               솔(G)        195.998
              






  * EEPROM 이 아직도 배송중이어서 부득이 IIci 에서 진행할 수 밖에 없었다. 도착하면 Classic II 롬에 적용
    해 볼 생각이다.

  * EEPROM 이 배송되어 Classic II에서 테스트해 보았다. 확실히 EPROM 보다 편하다. 자외선 살균기에 안넣어도
    되기 때문이다. 하지만 Classic II는 시동음 코드를 변경해도 시동음에 변화가 없었다...

  * 디벨로퍼노트에 ASC를 Egret 칩에서 흉내내지만 wavetable sound output을 지원하지 않는다고 한다.
    이때문에 시동음 코드를 변경해도 변화가 없는지 모르겠다. 아마도 기계음(?)이 아닌 녹음음(?)이 나오는
    것일 수도 있다. 그렇다면 LC3 ROM을 조사해 봐야 한다.

  * Bsr.s 와 Bsr.w 가 주소를 나타내는 방식은 약간 다르다. 2016.5.27. 우연한 발견
    6104 와 61000006 이 가리키는 주소가 같다.

  * 음악코드가 끝나면 맨뒤에 00을 붙여줘야 한다. 그렇지 않으면 에러가 발생한다. 똑같은 19음인데 어떤건
    연주되고 어떤건 에러가 발생했다. 비교해 보니 뒤가 00 으로 끝나 있는건 연주가 되었다. 원래는 음악코드가
    길어지면 그리되는 줄 알고 음의코드 길이만 변경하면서 시간을 낭비하고 있었다. 이것도 우연한 발견이었다.

 
             
             
<- Prev