free some bits in global reg, use r5 for edit
[megadrive.git] / hexed / hexed.s
... / ...
CommitLineData
1##################################################
2# #
3# Assemble with gas #
4# --register-prefix-optional --bitwise-or #
5# #
6##################################################
7
8.text
9.globl main
10.globl VBL
11
12##################################################
13# #
14# Register and bitmask definitions #
15# #
16##################################################
17
18.equ GFXDATA, 0xc00000
19.equ GFXCNTL, 0xc00004
20
21.equ VDP0_E_HBI, 0x10
22.equ VDP0_E_DISPLAY, 0x02
23.equ VDP0_PLTT_FULL, 0x04
24
25.equ VDP1_SMS_MODE, 0x80
26.equ VDP1_E_DISPLAY, 0x40
27.equ VDP1_E_VBI, 0x20
28.equ VDP1_E_DMA, 0x10
29.equ VDP1_NTSC, 0x00
30.equ VDP1_PAL, 0x08
31.equ VDP1_RESERVED, 0x04
32
33.equ VDP12_STE, 0x08
34.equ VDP12_SCREEN_V224, 0x00
35.equ VDP12_SCREEN_V448, 0x04
36.equ VDP12_PROGRESSIVE, 0x00
37.equ VDP12_INTERLACED, 0x02
38.equ VDP12_SCREEN_H256, 0x00
39.equ VDP12_SCREEN_H320, 0x81
40
41.equ VDP16_MAP_V32, 0x00
42.equ VDP16_MAP_V64, 0x10
43.equ VDP16_MAP_V128, 0x30
44.equ VDP16_MAP_H32, 0x00
45.equ VDP16_MAP_H64, 0x01
46.equ VDP16_MAP_H128, 0x03
47
48.equ MMODE_MAIN, 0
49.equ MMODE_VAL_INPUT, 1
50.equ MMODE_EDIT_VAL, 2
51.equ MMODE_GOTO, 3
52
53
54##################################################
55# #
56# MACROS #
57# #
58##################################################
59
60
61/* Write val to VDP register reg */
62.macro write_vdp_reg reg val
63 move.w #((\reg << 8) + 0x8000 + \val),(a3)
64.endm
65
66
67/* For immediate addresses */
68.macro VRAM_ADDR reg adr
69 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
70.endm
71
72
73.macro CRAM_ADDR reg adr
74 move.l #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
75.endm
76
77
78# make VDP word from address adr and store in d0
79.macro XRAM_ADDR_var adr
80 move.l \adr,d0
81 lsl.l #8,d0
82 lsl.l #8,d0
83 rol.l #2,d0
84 lsl.b #2,d0
85 lsr.l #2,d0
86.endm
87
88
89.macro VRAM_ADDR_var adr
90 XRAM_ADDR_var \adr
91 or.l #0x40000000,d0
92.endm
93
94
95.macro CRAM_ADDR_var adr
96 XRAM_ADDR_var \adr
97 or.l #0xc0000000,d0
98.endm
99
100
101.macro VSCROLL_ADDR reg adr
102 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg
103.endm
104
105
106.macro HSCROLL_ADDR reg adr
107 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
108.endm
109
110
111# convert tile coords in d0, d1 to nametable addr to a0
112.macro XY2NT
113 lsl.w #6,d1
114 add.w d1,d0
115 lsl.w #1,d0
116 movea.l #0xe000,a0
117 add.w d0,a0
118.endm
119
120# check if some d-pad button (and modifier) is pressed
121.macro do_dpad bit op val
122 btst.l #\bit,d0
123 beq 0f
124 \op.l \val,a6
125 bra dpad_end
1260:
127.endm
128
129# convert a6 to normal addr
130# destroys d0
131.macro mk_a6_addr reg
132 move.l a6,\reg
133 moveq.l #0,d0
134 move.b \reg,d0
135 lsr.l #8,\reg
136 add.l d0,\reg
137.endm
138
139.macro change_mode mode_new mode_back
140 and.w #0xc0ff,d7
141 or.w #(\mode_back<<11)|(\mode_new<<8),d7
142.endm
143
144#################################################
145# #
146# DATA #
147# #
148#################################################
149
150colors:
151 dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
152 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
153 dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
154 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
155 dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
156 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
157colors_end:
158
159
160sprite_data:
161 /* Y size link attr X */
162 dc.w 0; dc.b 0x05; dc.b 0; dc.w 0x6002; dc.w 0
163sprite_data_end:
164
165txt_edit:
166 .ascii "- edit -\0"
167txt_a_confirm:
168 .ascii "A-confirm\0"
169
170##################################################
171# #
172# MAIN PROGRAM #
173# #
174##################################################
175
176.align 2
177
178main:
179 /* mask irqs during init */
180 move.w #0x2700,sr
181
182 movea.l #0,a6
183 move.l #0x8000,d7
184 moveq.l #0,d6
185
186 /* Init pads */
187 move.b #0x40,(0xa10009).l
188 move.b #0x40,(0xa10003).l
189
190 /* Initialize VDP */
191 jsr init_gfx
192
193 /* Load color data */
194 movea.l #0,a0
195 movea.l #colors,a1
196 moveq.l #(colors_end-colors)/2,d0
197 jsr load_colors
198
199 /* load patterns */
200 movea.l #0,a0
201 movea.l #font,a1
202 move.l #128,d0
203 jsr load_tiles
204
205 /* generate A layer map */
206 movea.l #0xe000,a1
207 move.l #28-1,d4
208lmaploop0:
209 movea.l a1,a0
210 jsr load_prepare
211
212 move.l #64/2-1,d3
2130: move.l #0x00000000,(a0)
214 dbra d3,0b
215
216 add.l #64*2,a1
217 dbra d4,lmaploop0
218
219 /* generate B layer map */
220 movea.l #0xc000,a0
221 jsr load_prepare
222
223 move.l #64*28/2-1,d3
2240: move.l #0x00000000,(a0)
225 dbra d3,0b
226
227 /* upload sprite data */
228 movea.l #0xfc00,a0
229 jsr load_prepare
230 movea.l #sprite_data,a1
231
232 move.l #(sprite_data_end-sprite_data)/2-1,d3
2330: move.l (a1)+,(a0)
234 dbra d3,0b
235
236 move.w #0x2000,sr
237
238##################################################
239# #
240# MAIN LOOP #
241# #
242##################################################
243
244# global regs:
245# a6 = page_start[31:8]|cursor_offs[7:0]
246# d7 = old_inputs[31:16]|edit_bytes[15:14]|g_mode_old[13:11]|g_mode[10:8]|irq_cnt[7:0]
247# d6 = edit_word_save[31:15]|edit_done[7]|autorep_cnt[3:0]
248# d5 = edit_word[31:8]|edit_pos[4:2]|byte_cnt[1:0]; tmp in main mode
249
250forever:
251 jsr wait_vsync
252 bra forever
253
254
255
256VBL:
257 addq.b #1,d7
258 movem.l d0-d4/a0-a5,-(a7)
259
260 moveq.l #0,d0
261 move.w d7,d0
262 lsr.w #6,d0
263 and.w #0x1c,d0
264 move.l (jumptab,pc,d0),a0
265 jmp (a0)
266jumptab:
267 dc.l mode_main
268 dc.l mode_val_input
269 dc.l mode_edit_val /* edit val in editor */
270 dc.l mode_goto
271 dc.l mode_main
272 dc.l mode_main
273 dc.l mode_main
274 dc.l mode_main
275
276##################### main #######################
277
278mode_main:
279 clr.l d1
280 move.l a6,d0
281 move.b d0,d1
282 lsr.l #8,d0
283 move.l d0,a1 /* current addr */
284 lsr.b #3,d1
285 neg.b d1
286 add.b #27-1,d1 /* line where the cursor sits */
287 swap d1
288
289 movea.l #0xe004,a2
290 move.l #27-1,d5 /* line counter for dbra */
291 or.l d1,d5
292
293draw_column:
294 move.l a2,a0
295 jsr load_prepare
296
297 /* addr */
298 move.l a1,d2
299 moveq.l #6,d3
300 jsr print_hex_preped
301
302 /* 4 shorts */
303 moveq.l #4,d3
304 moveq.l #4-1,d4
305draw_shorts:
306 move.w #' ',(a0)
307 move.w (a1)+,d2
308 jsr print_hex_preped
309 dbra d4,draw_shorts
310
311 move.l d5,d0
312 swap d0
313 cmp.w d5,d0
314 beq draw_cursor
315
316draw_chars_pre:
317 move.l #(' '<<16)|' ',(a0)
318
319 /* 8 chars */
320 subq.l #8,a1
321 moveq.l #8-1,d4
322draw_chars:
323 move.b (a1)+,d0
324 move.b d0,d1
325 sub.b #0x20,d1
326 cmp.b #0x60,d1
327 blo 0f
328 move.w #'.',d0
3290:
330 move.w d0,(a0)
331 dbra d4,draw_chars
332
333 add.w #0x80,a2
334 dbra d5,draw_column
335
336 /* status bar */
337 movea.l #0xe004+64*2*27,a0
338 jsr load_prepare
339 mk_a6_addr d2
340 move.l #0x4006,d3
341 jsr print_hex_preped
342
343 /* handle input */
344 jsr get_input /* x0cbrldu x1sa00du */
345
346 btst.l #16+4,d0 /* A - scroll modifier */
347 beq input_noa
348
349 do_dpad 16+0, sub, #0x0800
350 do_dpad 16+1, add, #0x0800
351 do_dpad 16+10, sub, #0xd800
352 do_dpad 16+11, add, #0xd800
353input_noa:
354 moveq.l #0,d1
355 move.w d7,d1
356 lsr.w #7,d1
357 lsr.w #7,d1
358
359 do_dpad 0, subq, #0x0008
360 do_dpad 1, addq, #0x0008
361 do_dpad 10, sub, d1
362 do_dpad 11, add, d1
363
364dpad_end:
365 /* update addr */
366 move.l a6,d1
367 cmp.b #0xf0,d1
368 blo 0f
369 sub.l #0xd800,a6
370 add.w #0x00d8,a6
371 bra 1f
3720:
373 cmp.b #0xd8,d1
374 blo 1f
375 add.l #0xd800,a6
376 sub.w #0x00d8,a6
3771:
378
379 /* other btns */
380 moveq.l #0,d1
381 btst.l #12,d0 /* B - switch byte/word mode */
382 beq input_nob
383 bclr.l #15,d7
384 add.w #0x4000,d7 /* changes between 01 10 */
385 move.l a6,d1
386 and.l #1,d1
387 sub.l d1,a6 /* make even, just in case */
388
389input_nob:
390 btst.l #13,d0 /* C - edit selected byte */
391 beq input_noc
392
393 change_mode MMODE_EDIT_VAL, MMODE_MAIN
394 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE)
395
396input_noc:
397 btst.l #5,d0 /* Start - goto */
398 beq input_nos
399
400 change_mode MMODE_GOTO, MMODE_MAIN
401 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE)
402
403input_nos:
404vbl_end:
405 movem.l (a7)+,d0-d4/a0-a5
406 rte
407
408
409draw_cursor:
410 move.l a6,d0
411 and.l #7,d0 /* byte offs */
412 move.l d0,d1
413 lsr.b #1,d1 /* which word */
414 move.b d1,d2
415 lsl.b #2,d2
416 add.b d2,d1 /* num of chars to skip */
417 lsl.b #1,d1
418 move.w #0x2004,d3
419
420 btst.l #15,d7
421 bne draw_cursor_word
422
423draw_cursor_byte:
424 move.b (-8,a1,d0),d2
425 and.b #1,d0
426 lsl.b #2,d0
427 add.b d0,d1
428 subq.b #2,d3
429 bra 0f
430
431draw_cursor_word:
432 move.w (-8,a1,d0),d2
4330:
434 lea (7*2,a2,d1),a0
435 jsr load_prepare
436 jsr print_hex_preped
437
438 move.l a2,a0
439 add.w #26*2,a0
440 jsr load_prepare /* restore a0 */
441
442 jmp draw_chars_pre
443
444
445#################### hedit #######################
446
447mode_edit_val:
448 btst.l #7,d6
449 bne mode_hedit_finish
450
451 /* read val to edit */
452 moveq.l #0,d5
453 mk_a6_addr d1
454 move.l d1,a0
455 btst.l #15,d7
456 bne 0f
457 move.b (a0),d5
458 lsl.l #8,d5
459 or.b #1,d5
460 bra 1f
4610:
462 move.w (a0),d5
463 lsl.l #8,d5
464 or.b #2,d5
4651:
466
467 change_mode MMODE_VAL_INPUT, MMODE_EDIT_VAL
468 jmp vbl_end
469
470mode_hedit_finish:
471 /* write the val */
472 mk_a6_addr d1
473 move.l d1,a0
474 lsr.l #8,d5
475
476 btst.l #15,d7
477 bne 0f
478 move.b d5,(a0)
479 bra 1f
4800:
481 move.w d5,(a0)
4821:
483
484 bra return_to_main
485
486##################### goto #######################
487
488mode_goto:
489 btst.l #7,d6
490 bne mode_goto_finish
491
492 moveq.l #0,d5
493 swap d6
494 move.w d6,d5
495 swap d6
496 swap d5
497 or.b #3,d5 /* 3 bytes */
498 bclr.l #7,d6
499 change_mode MMODE_VAL_INPUT, MMODE_GOTO
500 jmp vbl_end
501
502mode_goto_finish:
503 lsr.l #8,d5
504 move.l d5,d0
505 move.l d0,d1
506 and.l #7,d1
507 and.b #0xf8,d0
508 lsl.l #8,d0
509 or.l d1,d0
510 move.l d0,a6
511
512 lsr.l #8,d5
513 swap d6
514 move.w d5,d6
515 swap d6
516
517 bra return_to_main
518
519################### val edit #####################
520
521mode_val_input:
522 /* frame */
523 movea.l #0xe000+14*2+11*64*2,a1
524 moveq.l #6-1,d1
5250:
526 move.w a1,a0
527 jsr load_prepare
528 moveq.l #11-1,d0
5291:
530 move.w #0,(a0)
531 dbra d0,1b
532
533 add.w #64*2,a1
534 dbra d1,0b
535
536 /* text */
537 lea txt_edit,a0
538 move.l #15,d0
539 move.l #11,d1
540 move.l #0xc000,d2
541 jsr print
542
543 lea txt_a_confirm,a0
544 move.l #15,d0
545 move.l #15,d1
546 move.l #0xc000,d2
547 jsr print
548
549 /* edit field */
550 moveq.l #0,d0
551 moveq.l #0,d1
552 moveq.l #0,d3
553 move.b d5,d3
554 and.b #3,d3 /* edit field bytes */
555
556 move.b #19,d0
557 sub.b d3,d0
558 move.b #13,d1
559 move.l d5,d2
560 lsr.l #8,d2
561 add.b d3,d3
562 or.w #0x8000,d3
563 jsr print_hex
564
565 /* current char */
566 moveq.l #0,d0
567 moveq.l #0,d1
568
569 and.w #6,d3
570 move.b #19,d0
571 move.b d3,d1
572 lsr.b #1,d1 /* length in bytes */
573 sub.b d1,d0
574 move.b d5,d1
575 lsr.b #2,d1
576 and.b #7,d1 /* nibble to edit */
577 add.b d1,d0
578
579 sub.b d1,d3
580 sub.b #1,d3 /* chars to shift out */
581 lsl.b #2,d3
582 add.b #8,d3
583 move.l d5,d2
584 lsr.l d3,d2
585
586 move.b #13,d1
587 move.w #0xa001,d3
588 jsr print_hex
589
590 /* handle input */
591 jsr get_input /* x0cbrldu x1sa00du */
592
593 move.w d0,d1
594 and.w #0x0f00,d1
595 beq ai_no_dpad
596 move.b d5,d1
597 and.b #3,d1
598 add.b d1,d1 /* nibble count */
599 sub.b #1,d1 /* max n.t.e. val */
600 move.b d5,d2
601 lsr.b #2,d2
602 and.b #7,d2 /* nibble to edit */
603
604 move.b d0,d3
605 and.b #3,d3
606 beq ai_no_ud
607 moveq.l #0,d3
608 moveq.l #0,d4
609 move.b #0xf,d3
610 move.b #0x1,d4
611 sub.b d2,d1
612 lsl.b #2,d1
613 add.b #8,d1
614 lsl.l d1,d3 /* mask */
615 lsl.l d1,d4 /* what to add/sub */
616 move.l d5,d1
617 and.l d3,d1
618 btst.l #8,d0
619 beq 0f
620 add.l d4,d1
621 bra 1f
6220:
623 sub.l d4,d1
6241:
625 and.l d3,d1
626 eor.l #0xffffffff,d3
627 and.l d3,d5
628 or.l d1,d5
629 jmp vbl_end
630
631ai_no_ud:
632 btst.l #10,d0
633 bne 0f
634 add.b #1,d2
635 bra 1f
6360:
637 sub.b #1,d2
6381:
639 cmp.b #0,d2
640 bge 0f
641 move.b d1,d2
6420:
643 cmp.b d1,d2
644 ble 0f
645 move.b #0,d2
6460:
647 and.b #0xe3,d5
648 lsl.b #2,d2
649 or.b d2,d5
650 jmp vbl_end
651
652ai_no_dpad:
653 move.w d0,d1
654 and.w #0x1020,d1
655 beq ai_no_sb
656
657 bra return_to_main
658
659ai_no_sb:
660 btst.l #4,d0 /* A - confirm */
661 beq ai_no_input
662 bset.l #7,d6
663 move.w d7,d1 /* back to prev mode */
664 and.w #0x3800,d1
665 lsr.w #3,d1
666 and.w #0xc0ff,d7
667 or.w d1,d7
668
669ai_no_input:
670 jmp vbl_end
671
672
673# go back to main mode
674return_to_main:
675 bclr.l #7,d6 /* not edited */
676 change_mode MMODE_MAIN, MMODE_MAIN
677 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
678 jmp vbl_end
679
680
681#################################################
682# #
683# Initialize VDP registers #
684# #
685#################################################
686
687init_gfx:
688 move.l #GFXCNTL,a3
689 write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
690 write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED)
691 write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */
692 write_vdp_reg 3,(0xe000 >> 10) /* Window address */
693 write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */
694 write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */
695 write_vdp_reg 6,0
696 write_vdp_reg 7,0 /* Backdrop color */
697 write_vdp_reg 10,1 /* Lines per hblank interrupt */
698 write_vdp_reg 11,0 /* 2-cell vertical scrolling */
699 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
700 write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */
701 write_vdp_reg 15,2
702 write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */
703 write_vdp_reg 17,0
704 write_vdp_reg 18,0xff
705 rts
706
707
708# read single phase from controller
709# #a0 - addr
710# d0 - result
711# destroys d1,d2
712get_input:
713 move.b #0x40,(0xa10003)
714 nop
715 nop
716 nop
717 move.b (0xa10003),d0
718 move.b #0x00,(0xa10003)
719 lsl.w #8,d0
720 nop
721 move.b (0xa10003),d0
722 eor.w #0xffff,d0
723
724 swap d7
725 move.w d7,d1
726 eor.w d0,d1 /* changed btns */
727 move.w d0,d7 /* old val */
728 swap d7
729 and.w d0,d1 /* what changed now */
730 bne 0f
731
732 addq.b #1,d6
733 move.b d6,d2
734 and.b #7,d2 /* do autorepeat every 8 frames */
735 cmp.b #7,d2
736 bne 1f
737 move.w d0,d1
7380:
739 and.b #0xf8,d6
7401:
741 swap d0
742 move.w d1,d0
743 rts
744
745# Load tile data from ROM
746# a0: VRAM base
747# a1: pattern address
748# d0: number of tiles to load
749# destroys d1
750
751load_tiles:
752 move.l d0,d1
753 VRAM_ADDR_var a0
754 move.l d0,(GFXCNTL).l
755
756 move.l #GFXDATA,a0
757 lsl.w #3,d1
758 subq.l #1,d1
7590:
760 move.l (a1)+,(a0)
761 dbra d1,0b
762
763 rts
764
765
766# Prepare to write to VDP RAM @a0
767# sets a0 to VDP data port for convenience
768# a0: VRAM base
769# destroys d0
770
771load_prepare:
772 VRAM_ADDR_var a0
773 move.l d0,(GFXCNTL).l
774 move.l #GFXDATA,a0
775 rts
776
777
778# Load color data from ROM
779# a0: CRAM base
780# a1: color list address
781# d0: number of colors to load
782# destroys d1
783
784load_colors:
785 move.l d0,d1
786 CRAM_ADDR_var a0
787 move.l d0,(GFXCNTL).l
788
789 move.l #GFXDATA,a0
790 subq.w #1,d1
7910:
792 move.w (a1)+,(a0)
793 dbra d1,0b
794
795 rts
796
797
798# print
799# a0 - string
800# d0 - x
801# d1 - y
802# d2 - tile_bits[15:11]
803# destroys a1
804
805print:
806 move.l a0,a1
807 XY2NT
808 jsr load_prepare
809 move.l d2,d0
810 and.w #0xf800,d0
811
812_print_loop:
813 move.b (a1)+,d0
814 beq _print_end
815
816 move.w d0,(a0)
817 jmp _print_loop
818
819_print_end:
820 rts
821
822
823# print_hex
824# d0 - x
825# d1 - y
826# d2 - value
827# d3 - digit_cnt[0:7]|tile_bits[11:15]
828# destroys a0, preserves d3
829
830print_hex:
831 XY2NT
832 jsr load_prepare
833
834print_hex_preped:
835 moveq.l #0,d0
836 move.b d3,d0
837 move.l d0,d1
838 lsl.b #2,d0
839 ror.l d0,d2 /* prep value */
840 subq.l #1,d1 /* count */
841 move.w d3,d0
842 and.w #0xf800,d0 /* keep upper bits in d0 */
843
844_print_hex_loop:
845 rol.l #4,d2
846 move.b d2,d0
847 and.b #0xf,d0
848
849 add.b #'0',d0
850 cmp.b #'9',d0
851 ble 0f
852 addq.b #7,d0
8530:
854 move.w d0,(a0)
855 dbra d1,_print_hex_loop
856
857 rts
858
859
860#################################################
861# #
862# Wait for next VBlank interrupt #
863# #
864#################################################
865
866wait_vsync:
867 move.b d7,d0
868_wait_change:
869 stop #0x2000
870 cmp.b d7,d0
871 beq _wait_change
872 rts
873
874
875#################################################
876# #
877# RAM DATA #
878# #
879#################################################
880
881.bss
882
883# nothing :)
884
885.end
886
887# vim:filetype=asmM68k