sd:getting_stuff_done_in_assembly_language
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sd:getting_stuff_done_in_assembly_language [2026/06/01 02:34] – appledog | sd:getting_stuff_done_in_assembly_language [2026/06/01 14:44] (current) – appledog | ||
|---|---|---|---|
| Line 123: | Line 123: | ||
| </ | </ | ||
| - | === Moving right along | + | === Random Numbers |
| - | We're not going to provide examples of other basic stuff too much, but we will show you this demo program | + | Random numbers are really useful. Here, we demonstrate the xorshift generator |
| <codify armasm> | <codify armasm> | ||
| + | ; Example 4: Random Numbers | ||
| + | |||
| .address $C000 | .address $C000 | ||
| Line 170: | Line 172: | ||
| ; ============================================================================ | ; ============================================================================ | ||
| - | ; AH=00h - Random Number | + | ; AH=00h - Random Number |
| ; Input: | ; Input: | ||
| - | ; Output: B = random 16-bit | + | ; Output: |
| - | ; Notes: | + | ; Notes: |
| - | ; | + | |
| ; ============================================================================ | ; ============================================================================ | ||
| Line 201: | Line 202: | ||
| ; ============================================================================ | ; ============================================================================ | ||
| - | == Terminal | + | === Putting It All Together: Menus |
| + | The engine for all these games we love such as Bard's Tale, Ulima, Nethack, King's quest, Alice in wonderland, Maniac Mansion, all were based on text engines. If the engine is good, a modicum of graphics will suffice. The big deal with retro games is that it's all about the gameplay, and the graphics serve the gameplay. What people miss in today' | ||
| + | |||
| + | The first thing you need to do is write some menus. Fundamentally printing the menus is easy, but you may wish to color the title of the menus, so you will need to learn how to do colored text. Also, you want to do input validation, so let's work on that too. | ||
| + | |||
| + | First, colored text. it's exactly the same as writing normal text, except you write a color byte. Here, i've added a special function to change the default color text is written in TTY mode. You can also set the color of text at an X and Y location, but that can become tedious because you have to do it character by character. | ||
| + | |||
| + | <codify armasm> | ||
| + | ; Example 5: Menus and Colored Text | ||
| + | |||
| + | .address $C000 | ||
| + | |||
| + | start: | ||
| + | ; Clear screen. | ||
| + | LDAH $10 | ||
| + | INT $10 | ||
| + | |||
| + | ; Set cursor position to X=0, Y=10. | ||
| + | LDX #0 | ||
| + | LDY #10 | ||
| + | LDAH $15 ; set cursor position | ||
| + | INT $10 | ||
| + | |||
| + | LDAH $50 ; Set teletype text default color | ||
| + | LDAL $2F ; color data in AL: BG=2, FG=F (here, orange) | ||
| + | INT $10 | ||
| + | |||
| + | LDBLX @str_menu_title | ||
| + | LDAH $66 ; BASIC IO_PUTSTRING | ||
| + | INT 0x05 | ||
| + | |||
| + | LDAH $50 ; Set teletype text default color | ||
| + | LDAL $29 ; color data default for mode 1 | ||
| + | INT $10 | ||
| + | |||
| + | LDBLX @str_menu | ||
| + | LDAH $66 ; BASIC IO_PUTSTRING | ||
| + | INT 0x05 | ||
| + | |||
| + | LDAH $02 ; blocking getkey | ||
| + | INT 0x10 | ||
| + | |||
| + | RET | ||
| + | |||
| + | |||
| + | str_menu_title: | ||
| + | | ||
| + | |||
| + | str_menu: | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | == Major Concept: The Cursor | ||
| Before we proceed, it's nice to be able to completely control the terminal. That means, instead of relying solely on PRINT and INPUT we have character level control. | Before we proceed, it's nice to be able to completely control the terminal. That means, instead of relying solely on PRINT and INPUT we have character level control. | ||
| Line 215: | Line 273: | ||
| <codify armasm> | <codify armasm> | ||
| + | ; Example 6: The Cursor | ||
| + | |||
| .address $C000 | .address $C000 | ||
| Line 262: | Line 322: | ||
| </ | </ | ||
| - | == Writing the game engine | + | === Keeping Track Yourself |
| - | The engine for all these games we love such as Bard's Tale, Ulima, Nethack, King's quest, Alice in wonderland, Maniac Mansion, all were based on text engines. If the engine is good, a modicum of graphics will suffice. The big deal with retro games is that it's all about the gameplay, and the graphics serve the gameplay. What people miss in today' | + | In a game, you don't really need the cursor. So instead of using a teletyle print function and calling INT $10, AH=$16, you can just give the values you want for your game screen. Here' |
| - | === Menus | + | <codify armasm> |
| - | The first thing you need to do is write some menus. Fundamentally printing the menus is easy, but you may wish to color the title of the menus, so you will need to learn how to do colored text. Also, you want to do input validation, so let's work on that too. | + | ; Example 7: put_ccxy |
| - | First, colored text. it's exactly the same as writing normal text, except you write a color byte. Here, i've added a special function to change the default color text is written in TTY mode. You can also set the color of text at an X and Y location, but that can become tedious because you have to do it character by character. | ||
| - | |||
| - | <codify armasm> | ||
| .address $C000 | .address $C000 | ||
| start: | start: | ||
| - | ; Clear screen. | ||
| - | LDAH $10 | ||
| - | INT $10 | ||
| - | |||
| - | ; Set cursor position to X=0, Y=10. | ||
| LDX #0 | LDX #0 | ||
| LDY #10 | LDY #10 | ||
| - | | + | |
| + | LDB #' | ||
| + | |||
| + | CALL @put_ccxy | ||
| + | RET | ||
| + | |||
| + | ; put_ccxy(B, X, Y, C) | ||
| + | ; Put Character and Color at X, T | ||
| + | ; INPUT: | ||
| + | ; B -- ascii code | ||
| + | ; X -- x location on screen | ||
| + | ; Y -- y location on screen | ||
| + | ; C -- hi nibble (BG) and low niblle (FG) | ||
| + | ; | ||
| + | put_ccxy: | ||
| + | ; Write character in AL at X, Y | ||
| + | LDAH $11 | ||
| INT $10 | INT $10 | ||
| - | | + | |
| - | LDAL $2F ; | + | ; Input: |
| + | LDAH $13 | ||
| INT $10 | INT $10 | ||
| - | | + | |
| - | LDAH $66 ; BASIC IO_PUTSTRING | + | </ |
| - | INT 0x05 | + | |
| - | LDAH $50 | + | == DEFCHAR Graphics |
| - | | + | Mode 1 Graphics is the first step in our graphics adventure. Mode 1 Graphics has two limitations. One, since you are redefining the character set to do graphics, everything must be drawn using 8x8 monocolor stamps (like characters). Two, you can only have 256 of them. |
| + | |||
| + | First, use int10h_font_set_char and int10h_glyph_pack to define the character: | ||
| + | |||
| + | ; ---------------------------------------------------------------------------- | ||
| + | ; AH=49h - glyph_pack -- pack an 8x8 grid and install it as a font glyph | ||
| + | ; | ||
| + | ; ELM = pointer to 64 source chars (8 rows x 8 cols, row-major) | ||
| + | ; | ||
| + | ; MSB = leftmost column | ||
| + | ; | ||
| + | ; ---------------------------------------------------------------------------- | ||
| + | |||
| + | You can also use AH=48h if you have the pre-compiled bytes: | ||
| + | |||
| + | ; ---------------------------------------------------------------------------- | ||
| + | ; AH=48h - font_set_char -- install an 8-byte glyph into the font | ||
| + | ; | ||
| + | ; ELM = pointer to 8 source bytes | ||
| + | ; | ||
| + | ; | ||
| + | ; ---------------------------------------------------------------------------- | ||
| + | |||
| + | Here's how it works: | ||
| + | |||
| + | <codify armasm> | ||
| + | ; Example 8: DEFCHAR | ||
| + | |||
| + | .address | ||
| + | |||
| + | start: | ||
| + | | ||
| + | LDAH $49 | ||
| + | LDAL #' | ||
| INT $10 | INT $10 | ||
| + | RET | ||
| + | ; Now the ! is replaced by a smiley. | ||
| + | | ||
| + | | ||
| + | smiley: | ||
| + | .bytes " | ||
| + | .bytes " | ||
| + | .bytes " | ||
| + | .bytes " # # " | ||
| + | .bytes " # # " | ||
| + | .bytes " | ||
| + | .bytes " | ||
| + | .bytes " | ||
| + | </ | ||
| - | LDBLX @str_menu | + | Unfortunately, |
| - | LDAH $66 ; | + | |
| - | INT 0x05 | + | === Using this concept in Mode 3 |
| + | Now, interestingly enough, you can translate this graphics technique directly into Mode 3. First, let's adapt BASIC' | ||
| + | |||
| + | ; ---------------------------------------------------------------------------- | ||
| + | ; AH=61h -- stamp_char -- render a glyph onto mode-3, transparent background | ||
| + | ; | ||
| + | ; | ||
| + | ; | ||
| + | ; CL = foreground color (only looks at low nibble) | ||
| + | ; | ||
| + | ; glyph source = VM1_CHAR_ROM ($01E000) | ||
| + | ; ---------------------------------------------------------------------------- | ||
| + | |||
| + | We'll toss in some fancy arrow key movement and a q for quit key, to spice things up: | ||
| + | |||
| + | <codify armasm> | ||
| + | ; Example 9: stamp_char | ||
| + | |||
| + | .address $C000 | ||
| + | |||
| + | start: | ||
| + | ; Switch to mode 3 | ||
| + | LDA $4003 ; 40h = set mode, 3 = mode 3 | ||
| + | INT $10 | ||
| + | |||
| + | ; Clear screen | ||
| + | LDAH $20 | ||
| + | INT $10 | ||
| + | |||
| + | LDX #0 | ||
| + | LDY #0 | ||
| + | |||
| + | loop: | ||
| + | ; | ||
| + | LDAL #' | ||
| + | LDAH $61 ; stamp char | ||
| + | LDC #9 ; dark blue | ||
| + | INT $18 | ||
| LDAH $02 ; blocking getkey | LDAH $02 ; blocking getkey | ||
| INT 0x10 | INT 0x10 | ||
| - | | + | |
| + | LDC #0 ; black background | ||
| + | INT $18 | ||
| + | CMP AL, #' | ||
| + | JZ @exit | ||
| + | CMP AL, #' | ||
| + | JZ @exit | ||
| - | str_menu_title: | + | CMP AL, #128 |
| - | .bytes " | + | JZ @move_left |
| + | CMP AL, #129 | ||
| + | JZ @move_down | ||
| + | CMP AL, #130 | ||
| + | JZ @move_up | ||
| + | CMP AL, #131 | ||
| + | JZ @move_right | ||
| - | str_menu: | + | JMP @loop |
| - | .bytes " | + | |
| - | .bytes " | + | move_left: |
| - | .bytes " | + | |
| - | | + | |
| - | .bytes " | + | |
| - | .bytes " | + | |
| + | LDX #0 ; Don't allow X to go below 0. | ||
| + | JMP @loop | ||
| + | |||
| + | move_right: | ||
| + | INC X | ||
| + | INC X | ||
| + | CMP X, #312 | ||
| + | JNC @loop | ||
| + | |||
| + | ; C is set if X was >= 312 | ||
| + | LDX #311 | ||
| + | JMP @loop | ||
| + | |||
| + | |||
| + | move_up: | ||
| + | DEC Y | ||
| + | DEC Y | ||
| + | JNN @loop | ||
| + | |||
| + | LDY #0 | ||
| + | JMP @loop | ||
| + | |||
| + | move_down: | ||
| + | INC Y | ||
| + | INC Y | ||
| + | CMP Y, #191 | ||
| + | JNC @loop | ||
| + | |||
| + | LDY #191 | ||
| + | JMP @loop | ||
| + | |||
| + | exit: | ||
| + | ; Switch back to mode 1 | ||
| + | LDA $4001 | ||
| + | INT $10 | ||
| + | RET | ||
| </ | </ | ||
| - | == DEFCHAR | + | === Multi-Color Character |
| - | Mode 1 Graphics is the first step in our graphics adventure. | + | The way to do multicolor |
| - | First, use int10h_font_set_char and int10h_glyph_pack | + | == Music |
| + | Randomly, in the middle of nowhere, we will explain | ||
| - | letter_a: | + | <codify BASIC> |
| - | | + | 10 PLAY "XV1 MN W5 XP3000 O4 L4 T180" |
| - | | + | 15 PLAY "XV2 MN W5 XP3500 O3 L4 T180" |
| - | | + | 20 PLAY "XV1 F1" |
| - | | + | 25 PLAY "XV2 R1" |
| - | .bytes " | + | 30 PLAY "XV1 A4. B-8 > C4 C4 <" |
| - | | + | 35 PLAY "XV2 R1" |
| - | | + | 40 PLAY "XV1 B-4 A4 G4 F4" |
| - | .bytes " | + | 45 PLAY "XV2 R1" |
| + | 50 PLAY "XV1 > C2 C4. C8 <" | ||
| + | 55 PLAY "XV2 R2 F4. F8" | ||
| + | 60 PLAY "XV1 > C4 D2 C4 <" | ||
| + | 65 PLAY "XV2 F4 < B-2 A4" | ||
| + | 70 PLAY "XV1 B-4 A4 G4 G4" | ||
| + | 75 PLAY "XV2 B-4 F4 > C4 C4" | ||
| + | 80 PLAY "XV1 A1" | ||
| + | 85 PLAY "XV2 < F1" | ||
| + | </ | ||
| + | Now you may wonder, why incorporate a BASIC example? Here, we can use BASIC to quickly test musical ideas. When it's time to put them into a game, we do this: | ||
| <codify armasm> | <codify armasm> | ||
| - | LDBLX @letter_a | + | ; Example 10: Music |
| - | LDFLD @buf | + | |
| - | LDAH $49 | + | |
| - | INT 0x10 | + | |
| - | + | ||
| - | + | ||
| - | | + | |
| + | .address $C000 | ||
| - | buf: | + | LDELM @fair_phyllis |
| - | .bytes | + | LDAH $52 ; Play Song |
| + | INT $11 | ||
| + | RET | ||
| + | |||
| + | fair_phyllis: | ||
| + | .bytes | ||
| + | .bytes "XV2 MN W5 XP3500 O3 L4 T180" | ||
| + | .bytes "XV1 F1 " | ||
| + | .bytes "XV2 R1 " | ||
| + | .bytes "XV1 A4. B-8 > C4 C4 < " | ||
| + | .bytes "XV2 R1 " | ||
| + | .bytes "XV1 B-4 A4 G4 F4 " | ||
| + | .bytes "XV2 R1 " | ||
| + | .bytes "XV1 > C2 C4. C8 < " | ||
| + | .bytes "XV2 R2 F4. F8 " | ||
| + | .bytes "XV1 > C4 D2 C4 < " | ||
| + | .bytes "XV2 F4 < B-2 A4 " | ||
| + | .bytes "XV1 B-4 A4 G4 G4 " | ||
| + | .bytes "XV2 B-4 F4 > C4 C4 " | ||
| + | .bytes "XV1 A1 " | ||
| + | .bytes "XV2 < F1", 0 | ||
| + | </ | ||
sd/getting_stuff_done_in_assembly_language.1780281282.txt.gz · Last modified: by appledog
