;
; HELLO WORLD — Neo Geo homebrew example
;
; Displays "HELLO WORLD" centred on the fix layer and plays three SSG
; beeps. Assembles with wla-68000, links with wlalink into a 1 MiB
; P-ROM. Paired with soundz80.s (M1) and the S1 generated by
; make_s1.py.
;

.INCDIR "../../../include/neogeo"

.INCLUDE "../../../memorymaps/neogeo68k.i"
.INCLUDE "macros.inc"
.INCLUDE "68k.inc"
.INCLUDE "bios.inc"

.ROMBANKMAP
  BANKSTOTAL 1
  BANKSIZE $100000
  BANKS 1
.ENDRO

.EMPTYFILL $00

.NGHEADER
  NGH $0042
  PROMSIZE AUTO
  BACKUPRAMPTR $00100000
  BACKUPRAMSIZE 2
  EYECATCHER GAME
  LOGOBANK 0
  USERENTRY _ng_userentry
  PLAYERSTART _ng_playerstart
  DEMOEND _ng_demoend
  COINSOUND _ng_coinsound
.ENDNG

.BANK 0 SLOT 0
.ORGA $0000

.INCLUDE "crt0.s"

; -------------------------------------------------------------------
; main — entered from crt0 after hardware init and Z80 RESET.
; -------------------------------------------------------------------
main:
  ; Give the Z80 a moment to finish its own reset sequence.
  bsr.w  delay_250ms

  ; Latch the cartridge fixed font source before printing.
  move.b #1, REG_CRTFIX

  ; ---------------------------------------------------------------
  ; Write "HELLO WORLD" centred on the fix layer.
  ;
  ; Fix layer VRAM is column-major: addr(col,row) = $7000 + col*32 + row
  ; Screen: 40 cols x 32 rows (rows 2-29 are visible on NTSC AES).
  ;   "HELLO WORLD" = 11 chars  ->  start col = (40-11)/2 = 14
  ;   Vertical centre of visible area = row 16
  ;   Start VRAM addr = $7000 + 14*32 + 16 = $71D0
  ; VRAMMOD $20 (=32) advances one column after each VRAMRW write.
  ; Tile word: (palette<<12) | ascii_code.
  ;   Palette 15, colour 1 = white (set by crt0).  $F000 | char.
  ; ---------------------------------------------------------------
  NG_VRAM_ADDR $71D0
  NG_VRAM_MOD  $20
  lea    txt_hello, a0
print_next:
  moveq  #0, d0
  move.b (a0)+, d0
  beq.b  print_end
  ori.w  #$F000, d0
  move.w d0, REG_VRAMRW
  bra.b  print_next
print_end:
  NG_VRAM_MOD 1              ; restore default modulo

  ; Play three beeps after the text is visible: low ($10), mid ($11), high ($12).
  ; Commands $01-$03 are BIOS-reserved; homebrew uses $10+.
  bsr.w  delay_250ms
  moveq  #$10, d0
  bsr.w  send_cmd
  bsr.w  delay_250ms
  moveq  #$11, d0
  bsr.w  send_cmd
  bsr.w  delay_250ms
  moveq  #$12, d0
  bsr.w  send_cmd
  bsr.w  delay_250ms

  ; Idle forever — kick the watchdog so the board does not reset.
idle:
  NG_KICK_WATCHDOG
  bra.b  idle

; -------------------------------------------------------------------
; delay_250ms — busy-wait ~250 ms at 12 MHz.
; -------------------------------------------------------------------
delay_250ms:
  move.l #$00040000, d1
delay_loop:
  subq.l #1, d1
  bne.b  delay_loop
  rts

; -------------------------------------------------------------------
; send_cmd — send command byte in d0.b to Z80, then poll REG_SOUND
; until the Z80 echoes it back (with bit 7 set), with a timeout.
; -------------------------------------------------------------------
send_cmd:
  move.b d0, REG_SOUND
  move.l #$00020000, d1
send_cmd_poll:
  move.b REG_SOUND, d2
  cmp.b  d0, d2
  beq.b  send_cmd_done
  ori.b  #$80, d0
  cmp.b  d0, d2
  beq.b  send_cmd_done
  subq.l #1, d1
  bne.b  send_cmd_poll
send_cmd_done:
  rts

txt_hello:
  .db "HELLO WORLD", $00
