main menu.s68
   1	dc.l $0, start
   2	dc.l empty_handler
   3	dc.l empty_handler
   4	;$10
   5	dc.l empty_handler
   6	dc.l empty_handler
   7	dc.l empty_handler
   8	dc.l empty_handler
   9	;$20
  10	dc.l empty_handler
  11	dc.l empty_handler
  12	dc.l empty_handler
  13	dc.l empty_handler
  14	;$30
  15	dc.l empty_handler
  16	dc.l empty_handler
  17	dc.l empty_handler
  18	dc.l empty_handler
  19	;$40
  20	dc.l empty_handler
  21	dc.l empty_handler
  22	dc.l empty_handler
  23	dc.l empty_handler
  24	;$50
  25	dc.l empty_handler
  26	dc.l empty_handler
  27	dc.l empty_handler
  28	dc.l empty_handler
  29	;$60
  30	dc.l empty_handler
  31	dc.l empty_handler
  32	dc.l empty_handler
  33	dc.l empty_handler
  34	;$70
  35	dc.l int_4
  36	dc.l empty_handler
  37	dc.l int_6
  38	dc.l empty_handler
  39	;$80
  40	dc.l empty_handler
  41	dc.l empty_handler
  42	dc.l empty_handler
  43	dc.l empty_handler
  44	;$90
  45	dc.l empty_handler
  46	dc.l empty_handler
  47	dc.l empty_handler
  48	dc.l empty_handler
  49	;$A0
  50	dc.l empty_handler
  51	dc.l empty_handler
  52	dc.l empty_handler
  53	dc.l empty_handler
  54	;$B0
  55	dc.l empty_handler
  56	dc.l empty_handler
  57	dc.l empty_handler
  58	dc.l empty_handler
  59	;$C0
  60	dc.l empty_handler
  61	dc.l empty_handler
  62	dc.l empty_handler
  63	dc.l empty_handler
  64	;$D0
  65	dc.l empty_handler
  66	dc.l empty_handler
  67	dc.l empty_handler
  68	dc.l empty_handler
  69	;$E0
  70	dc.l empty_handler
  71	dc.l empty_handler
  72	dc.l empty_handler
  73	dc.l empty_handler
  74	;$F0
  75	dc.l empty_handler
  76	dc.l empty_handler
  77	dc.l empty_handler
  78	dc.l empty_handler
  79	dc.b "SEGA GENESIS    "
  80	dc.b "(c) 2015.JULY   "
  81	dc.b "Menu            "
  82	dc.b "                "
  83	dc.b "                "
  84	dc.b "Menu            "
  85	dc.b "                "
  86	dc.b "                "
  87	dc.b "MP BlstMenu-00", 0, 0
  88	dc.b "                "
  89	dc.l $0, rom_end-1, $FF0000, $FFFFFF
  90	dc.b "                "
  91	dc.b "                "
  92	dc.b "                "
  93	dc.b "                "
  94	dc.b "JU  "
  95
  96;register addresses
  97VDP_DATA  equ $C00000
  98VDP_CTRL  equ $C00004
  99VDP_HV    equ $C00008
 100Z80_RAM   equ $A00000
 101IO_AREA   equ $A10000
 102PAD1_DATA equ (IO_AREA + 3)
 103PAD2_DATA equ (IO_AREA + 5)
 104EXT_DATA  equ (IO_AREA + 7)
 105PAD1_CTRL equ (IO_AREA + 9)
 106PAD2_CTRL equ (IO_AREA + 11)
 107EXT_CTRL  equ (IO_AREA + 13)
 108
 109MODE_1   equ 0
 110MODE_2   equ 1
 111SCROLL_A equ 2
 112WINDOW   equ 3
 113SCROLL_B equ 4
 114SAT      equ 5
 115BG_COLOR equ 7
 116HINT     equ $A
 117MODE_3   equ $B
 118MODE_4   equ $C
 119HSCROLL  equ $D
 120AUTOINC  equ $F
 121SCROLL   EQU $10
 122WINDOW_H equ $11
 123WINDOW_V equ $12
 124DMALEN_L equ $13
 125DMALEN_H equ $14
 126DMASRC_L equ $15
 127DMASRC_M equ $16
 128DMASRC_H equ $17
 129
 130VDP_VRAM_WRITE equ $40000000
 131VDP_CRAM_WRITE equ $C0000000
 132VDP_VSRAM_WRITE equ $40000010
 133VDP_DMA_FLAG equ $80
 134
 135vdpregset macro
 136	move.w #(((\1) << 8) | $8000 | (\2)), (a1)
 137	endm
 138
 139vdpreg macro
 140	dc.w (((\1) << 8) | $8000 | (\2))
 141	endm
 142
 143;Writes a normal VDP command to the control port
 144;\1 - VDP address
 145;\2 - Access type
 146vdpaccess macro
 147	ifeq NARG-2
 148	move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), (a1)
 149	else
 150	move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), \3
 151	endif
 152	endm
 153
 154;Writes a DMA command to the control port
 155;\1 - Destination address
 156;\2 - Destination type
 157startdma macro
 158	move.l #(\2 | VDP_DMA_FLAG | (\1 << 16) & $3FFF0000 | (\1 >> 14) & 3), (a1)
 159	endm
 160
 161DMA_SRC_68K  equ 0
 162DMA_SRC_VRAM equ $C0
 163DMA_SRC_FILL equ $80
 164
 165dmasrc macro
 166	move.l #($95009600 + (\1) << 15 & $FF0000 + (\1) >> 9 & $FF), (a1)
 167	move.w #($9700 + (\1) >> 17 & $7F | (\2)), (a1)
 168	endm
 169
 170dir_buffer equ $100000
 171menu_port  equ $180000
 172load_rom_port equ (menu_port+2*4)
 173lock_on_port equ (menu_port+8*4)
 174
 175MAX_DISPLAY equ 24
 176
 177	rsset $FFFF8000
 178x_pos           rs.w 1
 179base_cmd        rs.l 1
 180sprite_list     rs.l 160
 181page_index      rs.l MAX_DISPLAY+1
 182page_stack      rs.l 1
 183page_pointers   rs.l 1024
 184mouse_sprite    rs.l 1
 185menu_functions  rs.l 1
 186cursor_show_fun rs.l 1
 187special_click   rs.l 1
 188rom_load_addr   rs.l 1
 189mouse_x         rs.w 1
 190selection_top   rs.w 1
 191selection_bot   rs.w 1
 192selection_mask  rs.w 1
 193num_sprites     rs.b 1
 194last_pad1       rs.b 1
 195last_pad2       rs.b 1
 196selected        rs.b 1
 197more_pages      rs.b 1
 198mouse_buf       rs.b 3
 199mouse_shown     rs.b 1
 200last_mbuttons   rs.b 1
 201num_menu        rs.b 1
 202num_slots       rs.b 1
 203port_off        rs.b 1
 204
 205
 206int_6:
 207	dmasrc sprite_list, DMA_SRC_68K
 208	;set DMA length
 209	move.l #$94009300, d0
 210	moveq #0, d1
 211	move.b num_sprites.w, d1
 212	add.w d1, d1
 213	add.w d1, d1
 214	move.b d1, d0
 215	swap d0
 216	lsr.w #8, d1
 217	move.b d1, d0
 218	move.l d0, (a1)
 219	startdma $C000, VDP_VRAM_WRITE
 220	
 221	move.w (menu_port+4*7), d0
 222	btst #0, d0
 223	bne show_pause_menu
 224
 225	;read gamepad/mouse in port 1
 226	lea PAD1_DATA, a2
 227
 228	bsr io_read
 229
 230	cmp.b #3, d2
 231	beq .mouse
 232
 233	move.b last_pad1.w, d1
 234	eor.b d0, d1
 235	and.b d0, d1
 236	move.b d0, last_pad1.w
 237
 238	bsr handle_pad_buttons
 239
 240	bra pad2
 241.mouse
 242	bsr handle_mouse
 243
 244pad2:
 245	;read gamepad/mouse in port 2
 246	lea PAD2_DATA, a2
 247
 248	bsr io_read
 249
 250	cmp.b #3, d2
 251	beq .mouse
 252
 253	move.b last_pad2.w, d1
 254	eor.b d0, d1
 255	and.b d0, d1
 256	move.b d0, last_pad2.w
 257
 258	bsr handle_pad_buttons
 259	rte
 260.mouse
 261	bsr handle_mouse
 262	rte
 263
 264
 265;d0 = SACBRLUD
 266;d1 = newly pressed buttons
 267handle_pad_buttons:
 268	tst.b num_menu.w
 269	bne handle_buttons_menu
 270	tst.b num_slots.w
 271	bne handle_buttons_save
 272	moveq #16, d2
 273
 274
 275	btst #3, d1
 276	bne right
 277	btst #2, d1
 278	bne left
 279buttons_no_leftright
 280	btst #1, d1
 281	bne down
 282	btst #0, d1
 283	bne up
 284	btst #7, d1
 285	bne select_entry
 286	btst #5, d1
 287	bne select_entry
 288handle_done:
 289	rts
 290handle_buttons_menu
 291	moveq #48, d2
 292	bra buttons_no_leftright
 293handle_buttons_save
 294	moveq #32, d2
 295	bra buttons_no_leftright
 296
 297down:
 298	
 299	;check if we are already at the bottom of the page
 300	moveq #1, d0
 301	add.b (selected).w, d0
 302	tst.b num_menu.w
 303	bne .menu
 304	tst.b num_slots.w
 305	bne .slots
 306	move.w d0, d1
 307	add.w d1, d1
 308	add.w d1, d1
 309	lea page_index.w, a2
 310	tst.l (0, a2, d1.w)
 311	beq handle_done
 312.do_move
 313	move.b d0, (selected).w
 314
 315	add.w d2, (sprite_list).w
 316	add.w d2, (sprite_list+8).w
 317	rts
 318.menu:
 319	cmp.b num_menu.w, d0
 320	beq handle_done
 321	bra .do_move
 322.slots:
 323	cmp.b num_slots.w, d0
 324	beq handle_done
 325	bra .do_move
 326	
 327up:
 328	;check if we are already at the top of the page
 329	move.b (selected).w, d0
 330	beq handle_done
 331	subq #1, d0
 332	move.b d0, (selected).w
 333
 334	sub.w d2, (sprite_list).w
 335	sub.w d2, (sprite_list+8).w
 336	rts
 337
 338right:
 339	;check that we have another page to go to
 340	tst.b more_pages.w
 341	beq handle_done
 342	;switch to the next page
 343	move.l page_stack.w, a6
 344	move.l (-4, a6), a6
 345
 346	addq #6, a7
 347	bra render_page
 348
 349left:
 350	move.l page_stack.w, a5
 351	;check if we're already on the first page
 352	cmp.l #(page_pointers+8), a5
 353	beq handle_done
 354	;switch to previous page
 355	lea (-12, a5), a5
 356	move.l (a5)+, a6
 357	move.l a5, page_stack.w
 358
 359	addq #6, a7
 360	bra render_page
 361
 362select_entry:
 363	moveq #0, d0
 364	move.b (selected).w, d0
 365	add.w d0, d0
 366	add.w d0, d0
 367	tst.b num_menu.w
 368	bne .select_menu_button
 369	tst.b num_slots.w
 370	bne .select_save_slot
 371	lea page_index.w, a2
 372	move.l (0, a2, d0.w), a2
 373	tst.b (-1, a2)
 374	bne enter_dir
 375	;regular file
 376	move.l rom_load_addr.w, a3
 377	move.l a2, (a3)
 378	
 379	addq #6, a7
 380	bra show_pause_menu
 381.select_menu_button:
 382	movea.l menu_functions.w, a2
 383	move.l (0, a2, d0.w), a2
 384	addq #6, a7
 385	jmp (a2)
 386.select_save_slot:
 387	lea menu_port, a3
 388	moveq #0, d0
 389	move.b port_off.w, d0
 390	add.w d0, a3
 391	move.b selected.w, d0
 392	move.l d0, (a3)
 393	addq #6, a7
 394	jmp show_pause_menu
 395	
 396enter_dir:
 397	lea menu_port+4, a3
 398	move.l a2, (a3)
 399.wait_complete
 400	tst.w (a3)
 401	bne .wait_complete
 402	addq #6, a7
 403	bra menu_start
 404
 405handle_mouse:
 406	move.b last_mbuttons.w, d4
 407	eor.b d3, d4
 408	and.b d3, d4
 409	move.b d3, last_mbuttons.w
 410
 411	move.b d0, d2
 412	or.b d1, d2
 413	beq .no_mouse_move
 414
 415
 416	tst.b mouse_shown.w
 417	bne .skip_show_check
 418
 419	moveq #0, d2
 420	move.b num_sprites.w, d2
 421	move.w d2, d4
 422	lsl.w #3, d4
 423	lea sprite_list.w, a2
 424	move.b d2, (-5, a2, d4.w)
 425	lea (0, a2, d4.w), a2
 426	move.l a2, mouse_sprite.w
 427	move.l #$00EA0500, (a2)+
 428	move.w #$8083, (a2)
 429	move.w #$100, mouse_x.w
 430	addq #1, d2
 431	move.b d2, num_sprites.w
 432
 433	move.b #1, mouse_shown.w
 434	
 435	move.l cursor_show_fun.w, d2
 436	beq .skip_show_check
 437	move.l d2, a2
 438	jsr (a2)
 439	
 440
 441.skip_show_check
 442	neg.w d1
 443	move.l mouse_sprite.w, a2
 444	add.w d1, (a2)
 445	add.w d0, mouse_x.w
 446	move.w mouse_x.w, d0
 447	asr.w #1, d0
 448	move.w d0, (6, a2)
 449	move.w (a2), d1
 450	cmp.w selection_top.w, d1
 451	blo .done
 452	cmp.w selection_bot.w, d1
 453	bhi .special_click
 454	tst.b num_menu.w
 455	bne .handle_menu
 456	tst.b num_slots.w
 457	bne .handle_slots
 458	and.w #$FFF0, d1
 459	subq #8, d1
 460	move.w d1, (sprite_list).w
 461	move.w d1, (sprite_list+8).w
 462
 463	sub.w #264, d1
 464	lsr.w #4, d1
 465	move.b d1, selected.w
 466	bra .normal_click
 467.handle_menu
 468	;TODO: FIXME
 469	and.w #$FFF0, d1
 470	moveq #0, d0
 471	move.w d1, d0
 472	sub.w selection_top.w, d0
 473	divu.w #48, d0
 474	swap d0
 475	tst.w d0
 476	beq .no_adjust
 477	
 478	cmp.w #16, d0
 479	bne .round_up
 480	swap d0
 481	sub.w #16, d1
 482	bra .set_cursor_pos
 483	
 484.round_up
 485	swap d0
 486	addq #1, d0
 487	add.w #16, d1
 488	bra .set_cursor_pos
 489	
 490.no_adjust
 491	swap d0
 492.set_cursor_pos
 493	move.w d1, (sprite_list).w
 494	move.w d1, (sprite_list+8).w
 495
 496	move.b d0, selected.w
 497	
 498	bra .normal_click
 499.handle_slots
 500	and.w #$FFE0, d1
 501	subq #8, d1
 502	move.w d1, (sprite_list).w
 503	move.w d1, (sprite_list+8).w
 504
 505	sub.w #264, d1
 506	lsr.w #5, d1
 507	move.b d1, selected.w
 508.normal_click
 509	btst #0, d4
 510	bne select_entry
 511.done
 512	rts
 513.no_mouse_move
 514	tst.b mouse_shown
 515	bne .skip_show_check
 516	rts
 517.special_click:
 518	btst #0, d4
 519	beq .done
 520	move.l special_click.w, d2
 521	beq .done
 522	move.l d2, a2
 523	jmp (a2)
 524int_4:
 525empty_handler:
 526	rte
 527
 528id_lookup:
 529	dc.b $0, $1, $4, $5
 530	dc.b $2, $3, $6, $7
 531	dc.b $8, $9, $C, $D
 532	dc.b $A, $B, $E, $F
 533
 534io_read:
 535	;read TH=1
 536	move.b (a2), d0
 537	;read TH=0
 538	move.b #0, (a2)
 539	nop
 540	nop
 541	move.b (a2), d1
 542	;reset TH to 1
 543	move.b #$40, (a2)
 544
 545	moveq #0, d2   ;4
 546
 547	;calculate Mega Drive peripheral ID
 548	move.b d1, d2  ;4
 549	lsr.b #1, d2   ;8, 12
 550	or.b d1, d2    ;4, 16
 551	and.b #5, d2   ;8, 24
 552
 553	move.b d0, d3  ;4
 554	add.b d3, d3   ;4, 8
 555	or.b d0, d3    ;4, 12
 556	and.b #$A, d3  ;8, 20
 557
 558	or.b d3, d2    ;4
 559	move.b (id_lookup, pc, d2.w), d2 ;14
 560
 561
 562	cmp.b #$3, d2
 563	beq .mouse
 564
 565	cmp.b #$D, d2
 566	bne .not_pad
 567
 568	and.b #$3F, d0
 569	and.b #$30, d1
 570	add.b d1, d1
 571	add.b d1, d1
 572	or.b d1, d0
 573	not.b d0
 574	rts
 575.not_pad:
 576	moveq #0, d0
 577	rts
 578
 579.mouse:
 580
 581	move.b #$60, (a2)
 582	move.b #$60, (PAD1_CTRL-PAD1_DATA, a2)
 583	move.b #$60, (a2)
 584
 585	moveq #$f, d4
 586wait_hi_init:
 587	btst #4, (a2)
 588	beq wait_hi_init
 589	nop
 590	nop
 591	move.b #$20, (a2)
 592	nop
 593	nop
 594	moveq #$f, d4
 595	move.b #0, (a2)
 596.wait_lo
 597	btst #4, (a2)
 598	bne .wait_lo
 599	moveq #$f, d4
 600	move.b #$20, (a2)
 601.wait_hi
 602	btst #4, (a2)
 603	beq .wait_hi
 604
 605	lea mouse_buf.w, a3
 606	move.l a3, a4
 607	moveq #2, d3
 608	moveq #0, d0
 609loop:
 610	moveq #$f, d4
 611	move.b #0, (a2)
 612.wait_lo
 613	btst #4, (a2)
 614	bne .wait_lo
 615	move.b (a2), d0
 616	lsl.b #4, d0
 617	moveq #$f, d4
 618	move.b #$20, (a2)
 619.wait_hi
 620	btst #4, (a2)
 621	beq .wait_hi
 622	move.b (a2), d1
 623	and.b #$f, d1
 624	or.b d1, d0
 625	move.b d0, (a3)+
 626
 627	dbra d3, loop
 628
 629	;end request
 630	move.b #$60, (a2)
 631
 632
 633	;massage data
 634	moveq #0, d1
 635	move.b d0, d1
 636	move.b (a4)+, d3
 637	move.b (a4), d0
 638
 639	btst #4, d3
 640	beq xpos
 641	or.w #$FF00, d0
 642xpos
 643	btst #5, d3
 644	beq ypos
 645	or.w #$FF00, d1
 646ypos
 647	;set port config back to normal controller mode
 648	move.b #$40, (PAD1_CTRL-PAD1_DATA, a2)
 649	rts
 650
 651topcorner equ (button-font)/64 + 32
 652topmiddle equ topcorner+1
 653botcorner equ topmiddle+1
 654botmiddle equ botcorner+1
 655horiz_flip equ $800
 656vert_flip equ $1000
 657
 658; draws a button
 659; d0.w - x in cells
 660; d1.w - y in cells
 661; d2.w - width in cells
 662;
 663; clobbers a6
 664draw_button:
 665	;multiply x by 2
 666	add.w d0, d0
 667	;multiply y by 128
 668	lsl.w #7, d1
 669	add.w d1, d0
 670	add.w #$A000, d0
 671	move.w d0, d1
 672	and.w #$3FFF, d0
 673	rol.w #2, d1
 674	and.w #3, d1
 675	ori.w #(VDP_VRAM_WRITE >> 16), d0
 676	swap d0
 677	move.w d1, d0
 678	move.l d0, (a1)
 679	move.w d2, d1
 680	;top left corner
 681	move.w #topcorner, (a0)
 682	subq #3, d1
 683	bmi .notopmiddle
 684.toploop:
 685	;top middle
 686	move.w #topmiddle, (a0)
 687	dbra d1, .toploop
 688.notopmiddle
 689	;top right corner
 690	move.w #(topcorner | horiz_flip), (a0)
 691	;go to next row in name table
 692	add.l #((2*64) << 16), d0
 693	move.l d0, (a1)
 694	;bottom left corner
 695	move.w #botcorner, (a0)
 696	subq #3, d2
 697	bmi .nomiddlebot
 698.botloop:
 699	;bottom middle
 700	move.w #botmiddle, (a0)
 701	dbra d2, .botloop
 702.nomiddlebot
 703	;bottom right corner
 704	move.w #(botcorner | horiz_flip), (a0)
 705	rts
 706
 707;a5 - menu pointer
 708;d6 - initial Y position of menu
 709draw_menu:
 710	moveq #0, d7
 711	moveq #0, d5
 712	;clear out save slot state
 713	move.b d5, num_slots.w
 714	;clear out event handlers
 715	move.l d5, cursor_show_fun.w
 716	move.l d5, special_click.w
 717	;select first item
 718	move.b d7, selected.w
 719	;save menu pointer for second pass
 720	movea.l a5, a4
 721	;adjust arrow mask
 722	move.w #$FFE0, selection_mask.w
 723.lenloop	
 724	tst.b (a5)
 725	beq .lendone
 726	addq #1, d5
 727	movea.l a5, a6
 728	bsr strlen
 729	cmp.w d7, d0
 730	blo .nochange
 731	move.w d0, d7
 732.nochange
 733	lea (1, a5, d0.w), a5
 734	bra .lenloop
 735.lendone
 736	
 737	addq #2, d7
 738	move.b d5, num_menu.w
 739	
 740	;calculate X position
 741	move.w d7, d4
 742	lsr.w #1, d4
 743	moveq #20, d5
 744	sub.w d4, d5
 745	;calculate left arrow X
 746	move.w d5, d4
 747	lsl.w #3, d4
 748	add.w #(128-24), d4
 749	move.w d4, (sprite_list+6).w
 750	;calculate right arrow x
 751	move.w d7, d3
 752	lsl.w #3, d3
 753	add.w d3, d4
 754	add.w #32, d4
 755	move.w d4, (sprite_list+6+8).w
 756	;update left arrow Y
 757	move.w d6, d4
 758	lsl.w #4, d4
 759	add.w #256, d4
 760	move.w d4, (sprite_list).w
 761	move.w d4, (sprite_list+8).w
 762	;update mouse top limit
 763	move.w d4, selection_top.w
 764	;restore menu pointer
 765	movea.l a4, a5
 766.drawloop
 767	tst.b (a5)
 768	beq .done
 769	;x pos
 770	move.w d5, d0
 771	;y pos
 772	move.w d6, d1
 773	;width
 774	move.w d7, d2
 775	bsr draw_button
 776	
 777	movea.l a5, a6
 778	bsr strlen
 779	movea.l a5, a6
 780	lea (1, a5, d0.w), a5
 781	;x pos
 782	move.w d7, d1
 783	lsr.w #1, d1
 784	add.w d5, d1
 785	lsr.w #1, d0
 786	sub.w d0, d1
 787	;y pos
 788	move.w d6, d2
 789	;base attribute
 790	move.w #$206B, d0
 791	bsr print_string_fixed
 792	
 793	addq #3, d6
 794	bra .drawloop
 795.done
 796	;update mouse bottom limit
 797	lsl.w #4, d6
 798	add.w #224, d6
 799	move.w d6, selection_bot.w
 800	rts
 801	
 802clear_screen:
 803	;clear name tables
 804	vdpaccess $8000, VDP_VRAM_WRITE
 805	moveq #32, d0
 806	swap d0
 807	move.b #32, d0
 808	move.w #(64*64-1), d1
 809ploop:
 810	move.l d0, (a0)
 811	dbra d1, ploop
 812	rts
 813
 814initial_regs:
 815	vdpreg MODE_2, $4    ;Mode 5, everything turned off
 816	vdpreg MODE_1, $4
 817	vdpreg SCROLL_A, $20 ;Scroll a table $8000
 818	vdpreg SCROLL_B, $05 ;Scroll b table $A000
 819	vdpreg SAT, $60      ;SAT table $C000
 820	vdpreg BG_COLOR, 0
 821	vdpreg HINT, $FF
 822	vdpreg MODE_3, 0     ;full screen scroll
 823	vdpreg MODE_4, $87   ;40 cell mode, double-res interlace
 824	vdpreg HSCROLL, 0
 825	vdpreg AUTOINC, 2
 826	vdpreg SCROLL, 1     ;64x32 scroll size
 827end_initial_regs
 828
 829start:
 830	lea $FF0000, a0
 831	moveq #0, d0
 832	move.w #($10000/8 - 1), d1
 833.clearloop:
 834	move.l d0, (a0)+
 835	move.l d0, (a0)+
 836	dbra d1, .clearloop
 837
 838	lea $C00000, a0
 839	lea $C00004, a1
 840
 841	moveq #(end_initial_regs-initial_regs-1), d0
 842	lea initial_regs.w, a2
 843.regloop
 844	move.w (a2)+, (a1)
 845	dbra d0, .regloop
 846
 847	vdpaccess $0, VDP_CRAM_WRITE
 848	move.w #$400, (a0)
 849	move.w #$EEE, (a0)
 850	move.w #$222, (a0)
 851
 852	;init scroll table
 853	vdpaccess $0, VDP_VRAM_WRITE
 854	move.w #0, (a0)
 855	move.w #0, (a0)
 856	
 857	
 858	;load tiles
 859	vdpaccess $800, VDP_VRAM_WRITE
 860	lea font(pc), a2
 861	move.w #((buttonend-font)/4 - 1), d0
 862tloop:
 863	move.l (a2)+, (a0)
 864	dbra d0, tloop
 865	move.w #((fontfixedend-fontfixed)/4 - 1), d0
 866dtloop:
 867	move.l (a2)+, d1
 868	move.l d1, (a0)
 869	move.l d1, (a0)
 870	dbra d0, dtloop
 871
 872
 873	;setup SAT
 874	;;vdpaccess $C000, VDP_VRAM_WRITE
 875
 876	lea sprite_list.w, a2
 877	;left arrow
 878	move.l #$01080501, (a2)+
 879	move.l #$807F0086, (a2)+
 880
 881	;right arrow
 882	move.l #$01080500, (a2)+
 883	move.l #$887F01AA, (a2)+
 884	move.b #2, num_sprites.w
 885	
 886show_main_menu:
 887	bsr clear_screen
 888	;init vertical scroll RAM
 889	vdpaccess $0, VDP_VSRAM_WRITE
 890	move.w #-4, (a0)
 891	move.w #0, (a0)
 892	
 893	moveq #8, d6
 894	move.l #main_menu_func, menu_functions.w
 895	lea main_menu(pc), a5
 896	bsr draw_menu
 897	bra gamepad_setup
 898	
 899show_pause_menu:
 900	bsr clear_screen
 901	;init vertical scroll RAM
 902	vdpaccess $0, VDP_VSRAM_WRITE
 903	move.w #-4, (a0)
 904	move.w #0, (a0)
 905	moveq #8, d6
 906	move.l #pause_menu_func, menu_functions.w
 907	lea pause_menu(pc), a5
 908	bsr draw_menu
 909	bra gamepad_setup
 910	
 911lock_on:
 912	move.l #lock_on_port, rom_load_addr.w
 913	bra menu_common
 914menu_start:
 915	move.l #load_rom_port, rom_load_addr.w
 916menu_common:
 917	moveq #0, d0
 918	;init vertical scroll RAM
 919	vdpaccess $0, VDP_VSRAM_WRITE
 920	move.w d0, (a0)
 921	move.w d0, (a0)
 922	
 923	;reset arrow position
 924	move.w #$0108, sprite_list.w
 925	move.w #$0108, (sprite_list + 8).w
 926	move.w #$0086, (sprite_list + 6).w
 927	move.w #$01AA, (sprite_list + 6 + 8).w
 928	
 929	;reset selection
 930	move.b d0, selected.w
 931	
 932	;reset special click handler
 933	move.l d0, special_click.w
 934
 935	
 936	lea page_pointers.w, a5
 937	lea dir_buffer, a6
 938	move.l a6, (a5)+
 939	move.l a5, page_stack.w
 940	lea menu_port, a2
 941	move.l a6, (a2)
 942
 943wait_complete:
 944	tst.w (a2)
 945	bne wait_complete
 946
 947render_page:
 948	bsr clear_screen
 949	
 950	;clear menu state
 951	move.b #0, num_menu.w
 952	move.w #272, selection_top.w
 953	move.w #655, selection_bot.w
 954	move.w #$FFF0, selection_mask.w
 955
 956	;init scroll table
 957	vdpaccess $0, VDP_VRAM_WRITE
 958	move.w #0, (a0)
 959	move.w #4, (a0)
 960	
 961	move.l #$40860002, d3
 962	move.l d3, (a1)
 963	move.l d3, base_cmd.w
 964	
 965	move.b #0, more_pages.w
 966	lea page_index.w, a3
 967	moveq #MAX_DISPLAY-1, d7
 968file_loop:
 969	tst.b (a6)+
 970	beq done_files
 971	addq #1, a6 ;TODO: Do something with directory flag
 972
 973	;skip over entries starting with a dot except ..
 974	cmp.b #$2E, (a6)
 975	bne normal
 976	cmp.b #$2E, (1, a6)
 977	beq normal
 978	addq #1, a6
 979.skip_loop:
 980	tst.b (a6)+
 981	bne .skip_loop
 982	addq #1, d7
 983	move.l a6, d6
 984	bra skip
 985normal:
 986	;save entry pointer to page index
 987	move.l a6, (a3)+
 988	;print name on screen
 989	moveq #0, d0
 990	bsr print_string
 991	move.l a6, d6
 992
 993	lea Newline(pc), a6
 994	bsr print_string
 995
 996skip:
 997	;word align pointer
 998	addq #1, d6
 999	and.w #$FFFE, d6
1000	move.l d6, a6
1001
1002	dbra d7, file_loop
1003	tst.b (a6)
1004	beq done_files
1005	move.b #1, more_pages.w
1006done_files:
1007	move.l page_stack.w, a5
1008	move.l a6, (a5)+
1009	move.l a5, page_stack.w
1010
1011	;null terminate page_index
1012	moveq #0, d0
1013	move.l d0, (a3)
1014	
1015	tst.b mouse_shown
1016	beq .no_mouse
1017	
1018	tst.b more_pages.w
1019	beq .no_next_page
1020	
1021	;draw Next button
1022	moveq #30, d0
1023	moveq #26, d1
1024	moveq #6, d2
1025	bsr draw_button
1026	
1027	;base attribute
1028	move.w #$206B, d0
1029	;x pos
1030	moveq #32, d1
1031	;y pos
1032	moveq #26, d2
1033	lea next_str(pc), a6
1034	bsr print_string_fixed
1035	
1036.no_next_page
1037
1038	cmp.l #(page_pointers+8), a5
1039	beq .no_prev_page
1040	
1041	;draw Prev button
1042	moveq #3, d0
1043	moveq #26, d1
1044	moveq #6, d2
1045	bsr draw_button
1046	
1047	;base attribute
1048	move.w #$206B, d0
1049	;x pos
1050	moveq #5, d1
1051	;y pos
1052	moveq #26, d2
1053	lea prev_str(pc), a6
1054	bsr print_string_fixed
1055	
1056.no_prev_page
1057
1058	move.l #0, cursor_show_fun.w
1059	
1060	bra .done_page_buttons
1061.no_mouse
1062	move.l #show_prev_next_buttons, cursor_show_fun.w
1063.done_page_buttons
1064	move.l #handle_prev_next_click, special_click.w
1065
1066gamepad_setup:
1067	;setup gamepads
1068	move.b #$40, PAD1_CTRL
1069	move.b #$40, PAD2_CTRL
1070
1071	move.w #$8174, (a1) ;enable display, vertical interrupts, DMA
1072
1073
1074wait_forever
1075	stop #2500
1076	bra wait_forever
1077	
1078handle_prev_next_click:
1079	;make sure we're actually low enough
1080	cmp.w #663, d1
1081	bls .no_prev_page
1082
1083
1084	tst.b more_pages.w
1085	beq .no_next_page
1086	
1087	cmp.w #373, d0
1088	blo .no_next_page
1089	
1090	cmp.w #419, d0
1091	bhi .no_next_page
1092	
1093	;switch to the next page
1094	move.l page_stack.w, a6
1095	move.l (-4, a6), a6
1096
1097	add.w #10, a7
1098	bra render_page
1099	
1100.no_next_page
1101	cmp.l #(page_pointers+8), a5
1102	beq .no_prev_page
1103	
1104	cmp.w #157, d0
1105	blo .no_prev_page
1106	
1107	cmp.w #203, d0
1108	bhi .no_prev_page
1109	
1110	;switch to previous page
1111	lea (-12, a5), a5
1112	move.l (a5)+, a6
1113	move.l a5, page_stack.w
1114
1115	add.w #10, a7
1116	bra render_page
1117	
1118.no_prev_page
1119	rts
1120	
1121show_prev_next_buttons:
1122	movem.l d0-d2/a6, -(a7)
1123	tst.b more_pages.w
1124	beq .no_next_page
1125	
1126	;draw Next button
1127	moveq #30, d0
1128	moveq #26, d1
1129	moveq #6, d2
1130	bsr draw_button
1131	
1132	;base attribute
1133	move.w #$206B, d0
1134	;x pos
1135	moveq #32, d1
1136	;y pos
1137	moveq #26, d2
1138	lea next_str(pc), a6
1139	bsr print_string_fixed
1140	
1141.no_next_page
1142
1143	cmp.l #(page_pointers+8), a5
1144	beq .no_prev_page
1145	
1146	;draw Prev button
1147	moveq #3, d0
1148	moveq #26, d1
1149	moveq #6, d2
1150	bsr draw_button
1151	
1152	;base attribute
1153	move.w #$206B, d0
1154	;x pos
1155	moveq #5, d1
1156	;y pos
1157	moveq #26, d2
1158	lea prev_str(pc), a6
1159	bsr print_string_fixed
1160	
1161.no_prev_page
1162	move.l #0, cursor_show_fun.w
1163	movem.l (a7)+, d0-d2/a6
1164	rts
1165	
1166show_about:
1167	bsr clear_screen
1168	moveq #1, d7
1169	lea about_text(pc), a6
1170	;base attribute
1171	move.w #$006B, d0
1172.loop
1173	tst.b (a6)
1174	beq .done
1175	;x pos
1176	moveq #1, d1
1177	;y pos
1178	move.w d7, d2
1179	bsr print_string_fixed
1180	addq #1, d7
1181	bra .loop
1182.done
1183	moveq #8, d6
1184	move.l #about_menu_func, menu_functions.w
1185	lea about_menu(pc), a5
1186	bsr draw_menu
1187.wait
1188	stop #$2500
1189	bra .wait
1190	
1191exit:
1192	move.l #1, menu_port+12
1193	bra exit
1194	
1195resume:
1196	move.l #2, menu_port+12
1197	bra show_pause_menu
1198	
1199show_save_slots:
1200	move.w #(256+26), sprite_list.w
1201	move.w #(256+26), (sprite_list+8).w
1202	move.w #(128+8), (sprite_list+6).w
1203	move.w #(128+320-24), (sprite_list+6+8).w
1204	move.w #(256+32), selection_top.w
1205	move.b #0, selected.w
1206	move.b #0, num_menu.w
1207	lea dir_buffer, a6
1208	lea menu_port+16, a3
1209	move.l a6, (a3)
1210.waitdone:
1211	tst.w (a3)
1212	bne .waitdone
1213	bsr clear_screen
1214	moveq #0, d0
1215	
1216	moveq #0, d6
1217	moveq #2, d7
1218.slotloop
1219	tst.b (a6)
1220	beq .done
1221	addq #1, d6
1222	moveq #4, d1
1223	move.w d7, d2
1224	bsr print_string_fixed
1225	addq #2, d7
1226	bra .slotloop
1227.done
1228	lsl.w #4, d7
1229	add.w #248, d7
1230	move.w d7, selection_bot.w
1231	move.b d6, num_slots.w
1232	rts
1233	
1234save_state:
1235	move.b #(5*4), port_off.w
1236	bsr show_save_slots
1237.wait
1238	stop #$2500
1239	bra .wait
1240	
1241load_state:
1242	move.b #(6*4), port_off.w
1243	bsr show_save_slots
1244.wait
1245	stop #$2500
1246	bra .wait
1247	
1248next_str:
1249	dc.b "Next", 0
1250prev_str:
1251	dc.b "Prev", 0
1252	
1253about_text:
1254	dc.b "BlastEm v0.6.2", 0
1255	dc.b "Copyright 2011-2019 Michael Pavone", 0
1256	dc.b " ", 0
1257	dc.b "BlastEm is a high performance, open", 0
1258	dc.b "source (GPLv3) Genesis/Megadrive", 0
1259	dc.b "emulator.",0
1260	dc.b " ", 0
1261	dc.b " ", 0
1262	dc.b " ", 0
1263	dc.b " ", 0
1264	dc.b "       --- Special Thanks ---", 0
1265	dc.b " ", 0
1266	dc.b "Nemesis: Documentatino and test ROMs", 0
1267	dc.b "Charles MacDonald: Documentation", 0
1268	dc.b "Eke-Eke: Documentation", 0
1269	dc.b "Bart Trzynadlowski: Documentation", 0
1270	dc.b "KanedaFR: Hosting the best Sega forum", 0
1271	dc.b "Titan: Awesome demos and documentation", 0
1272	dc.b "flamewing: BCD info and test ROM", 0
1273	dc.b "r57shell: Opcode size test ROM", 0
1274	dc.b "micky: Testing", 0
1275	dc.b "Sasha: Testing", 0
1276	dc.b "lol-frank: Testing", 0
1277	dc.b "Sik: Testing", 0
1278	dc.b "Tim Lawrence : Testing", 0
1279	dc.b "ComradeOj: Testing", 0
1280	dc.b "Vladikcomper: Testing", 0
1281	dc.b 0
1282	
1283
1284Newline:
1285	dc.b $A, 0
1286
1287	align 1
1288
1289;Prints a null terminated string
1290;a6 - pointer to string
1291;a0 - VDP data port
1292;d0 - base tile attribute
1293;
1294;Clobbers: d1.w, d2.w, d3.l
1295print_string:
1296	lea widths(pc), a5
1297	move.w x_pos.w, d2
1298	move.l base_cmd.w, d3
1299.loop
1300	moveq #0, d1
1301	move.b (a6)+, d1
1302	beq .end
1303	cmp.b #$A, d1
1304	beq .newline
1305	tst.b (-32, a5, d1.w)
1306	beq .narrow
1307	add.w d0, d1
1308	move.w d1, (a0)
1309	addq #2, d2
1310	bra .loop
1311.narrow
1312	add.w d0, d1
1313	move.w d1, (a0)
1314	addq #1, d2
1315	move.l d2, d1
1316	;switch to other plane
1317	and.w #$FFFE, d1
1318	swap d1
1319	eor.l #$20000000, d3
1320	add.l d3, d1
1321	move.l d1, (a1)
1322	bra .loop
1323.newline
1324	moveq #0, d2
1325	;switch back to plane A
1326	and.l #$DFFFFFFF, d3
1327	;skip to next row
1328	add.l #$00800000, d3
1329	move.l d3, (a1)
1330	bra .loop
1331.end
1332	move.w d2, x_pos.w
1333	move.l d3, base_cmd.w
1334	rts
1335	
1336;Prints a null-terminated string with a fixed width font
1337;a6 - pointer to string
1338;a0 - VDP data port
1339;d0 - base tile attribute
1340;d1 - x col
1341;d2 - y col
1342;
1343print_string_fixed:
1344	;multiply x by 2
1345	add.w d1, d1
1346	;multiply y by 128
1347	lsl.w #7, d2
1348	add.w d2, d1
1349	add.w #$8000, d1
1350	move.w d1, d2
1351	and.w #$3FFF, d1
1352	rol.w #2, d2
1353	and.w #3, d2
1354	ori.w #(VDP_VRAM_WRITE >> 16), d1
1355	swap d1
1356	move.w d2, d1
1357	move.l d1, (a1)
1358.loop
1359	moveq #0, d1
1360	move.b (a6)+, d1
1361	beq .end
1362	add.w d0, d1
1363	move.w d1, (a0)
1364	bra .loop
1365.end
1366	rts
1367	
1368;Returns string length in d0
1369;a6 - pointer to string
1370strlen:
1371	moveq #-1, d0
1372.loop
1373	addq #1, d0
1374	tst.b (a6)+
1375	bne .loop
1376	rts
1377
1378	align 1
1379font:
1380	incbin font_interlace_variable.tiles
1381fontend
1382arrow:
1383	incbin arrow.tiles
1384arrowend:
1385cursor:
1386	incbin cursor.tiles
1387cursorend:
1388button:
1389	incbin button.tiles
1390buttonend:
1391fontfixed:
1392	incbin font.tiles
1393fontfixedend:
1394
1395widths:
1396	dc.b 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1
1397	dc.b 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0
1398	dc.b 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1
1399	dc.b 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1400	dc.b 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1
1401	
1402main_menu:
1403	dc.b "Load ROM", 0
1404	dc.b "About", 0
1405	dc.b "Exit", 0
1406	dc.b 0
1407	
1408	align 1
1409main_menu_func:
1410	dc.l menu_start
1411	dc.l show_about
1412	dc.l exit
1413	
1414about_menu:
1415	dc.b "Return", 0
1416	dc.b 0
1417	
1418	align 1
1419about_menu_func:
1420	dc.l show_main_menu
1421	
1422pause_menu:
1423	dc.b "Resume", 0
1424	dc.b "Load ROM", 0
1425	dc.b "Lock On", 0
1426	dc.b "Save State", 0
1427	dc.b "Load State", 0
1428	dc.b "Exit", 0
1429	dc.b 0
1430	
1431	align 1
1432pause_menu_func
1433	dc.l resume
1434	dc.l menu_start
1435	dc.l lock_on
1436	dc.l save_state
1437	dc.l load_state
1438	dc.l exit
1439
1440rom_end: