part1.asm 34.8 KB
Newer Older
1
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
Ricardo Quesada's avatar
Ricardo Quesada committed
2
; "64K RAM Ought to be enough" - Part 1
3
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
4 5 6
; Pungas de Villa Martelli - http://pungas.space
;
; code: riq (http://retro.moe)
7
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
8 9 10

bits    16
cpu     8086
11
org     0x100
12

13 14 15 16
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; MACROS
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
%define DEBUG 0                                 ;0=diabled, 1=enabled
17
%define EMULATOR 0                              ;1=run on emulator
18

19
GFX_SEG         equ     0xb800                  ;0x1800 for PCJr with 32k video ram
Ricardo Quesada's avatar
Ricardo Quesada committed
20
                                                ;0xb800 for 16k modes
21
CHAR_OFFSET     equ     (24*8/2)*80             ;start drawing at row 24
22

23 24 25 26
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
section .text
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;

27 28 29 30 31
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
;
; CODE
;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
32
start:
Ricardo Quesada's avatar
Ricardo Quesada committed
33 34
        cld                                     ;forward direction

35 36
        push    cs
        pop     ds                              ;ds=cs
Ricardo Quesada's avatar
Ricardo Quesada committed
37 38 39 40 41 42 43
        mov     ax,GFX_SEG
        mov     es,ax                           ;es = GFX segment.
                                                ; should be valid everywhere. if modified
                                                ; use push/pop
        call    intro_init
        call    intro_main_loop
        call    intro_cleanup
44

45
        ; set video mode used in next part
46
        mov     ax,0x0089                       ;320x200x16 mode
47
        int     0x10                            ;don't clean screen
48

49
        mov     ax,0x4c01                       ;ricarDOS: load next file. Don't print anything, just load file.
50
        int     0x21                            ;DOS: exit
51 52

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
Ricardo Quesada's avatar
Ricardo Quesada committed
53
intro_init:
Ricardo Quesada's avatar
Ricardo Quesada committed
54

Ricardo Quesada's avatar
Ricardo Quesada committed
55 56
        ;init video mode. don't clear screen
        ;display gfx that is already loaded in memory
Ricardo Quesada's avatar
Ricardo Quesada committed
57
        mov     ax,0x0088                       ;160x200 16 colors
58 59 60 61 62
        int     0x10                            ;don't clean screen

        mov     ax,0x0583                       ;set CPU/CRT pages
        mov     bx,0x0303                       ;use page 3 for video memory/map 0xb800
        int     0x10                            ;page 3 means: starts at 0x0c00 (48k offset)
63

Ricardo Quesada's avatar
Ricardo Quesada committed
64 65
        call    delete_640

66
        ;turning off the drive motor is needed to prevent
67 68 69 70
        ;it from being on the whole time.
        mov     bp,ds                           ;save ds
        sub     ax,ax
        mov     ds,ax                           ;ds = 0 (zero page)
71 72
        mov     byte [0x0440],0                 ;motor count to zero
        and     byte [0x043f],0xf0              ;turn off motor running bits
73 74 75
        mov     al,0x80
        out     0xf2,al                         ;turn off floppy motor
        mov     ds,bp                           ;restore ds
76

Ricardo Quesada's avatar
Ricardo Quesada committed
77 78 79 80
        ;init video mode.
        ;display gfx that is already loaded in memory
        mov     ax,0x0004                       ;320x200 4 colors
        int     0x10
Ricardo Quesada's avatar
Ricardo Quesada committed
81

Ricardo Quesada's avatar
Ricardo Quesada committed
82

83 84 85 86
        ;init music
        mov     ax,pvm_song                     ;start music offset
        call    music_init                      ;init music

Ricardo Quesada's avatar
Ricardo Quesada committed
87
        call    gfx_init
88

Ricardo Quesada's avatar
Ricardo Quesada committed
89
        ; should be the last one to get initialized
Ricardo Quesada's avatar
Ricardo Quesada committed
90 91
        mov     ax,irq_8_handler                ;handler address
        mov     cx,198                          ;horizontal raster line for the IRQ
Ricardo Quesada's avatar
Ricardo Quesada committed
92
        jmp     irq_8_init
93

Ricardo Quesada's avatar
Ricardo Quesada committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; delay
;       in: lenghts of delay
delay:
        push    cx
.l1:
        mov     cx,0x2000
.l0:
        loop    .l0
        dec     bx
        jnz     .l1
        pop     cx
        ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; deletes the 0 from 640 converting it to 64
delete_640:

        ;draw diagonal top-left to bottom-right
        mov     di,16
        mov     cx,0                            ;initial values. col
114 115
        mov     dx,150                          ;initial values. row
        sub     bx,bx                           ;page 0
Ricardo Quesada's avatar
Ricardo Quesada committed
116

117
.l0:
Ricardo Quesada's avatar
Ricardo Quesada committed
118 119 120
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10

121 122 123 124 125 126 127 128 129 130 131 132
        inc     dx                              ;row++
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10

        inc     dx                              ;row++
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10

        dec     dx                              ;row--
        dec     dx                              ;row--
        inc     cx                              ;col++
        mov     ax,0x0c04                       ;draw dot, color red
Ricardo Quesada's avatar
Ricardo Quesada committed
133
        int     0x10                            ;draw dot
134

Ricardo Quesada's avatar
Ricardo Quesada committed
135 136
        inc     dx                              ;row++

137
        call    beep
Ricardo Quesada's avatar
Ricardo Quesada committed
138 139 140 141 142 143 144

        dec     di
        jnz     .l0

        ;draw diagonal top-right to bottom-left
        mov     di,16
        mov     cx,16                           ;initial values. col
145
        mov     dx,150                          ;initial values. row
Ricardo Quesada's avatar
Ricardo Quesada committed
146

147
.l1:
148 149 150
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10
        inc     dx                              ;row++
Ricardo Quesada's avatar
Ricardo Quesada committed
151 152 153
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10

154 155 156 157 158 159 160 161 162
        inc     dx                              ;row++
        mov     ax,0x0c04                       ;draw dot, color red
        int     0x10

        dec     dx                              ;row--
        dec     dx                              ;row--

        dec     cx                              ;col--
        mov     ax,0x0c04                       ;draw dot, color red
Ricardo Quesada's avatar
Ricardo Quesada committed
163
        int     0x10                            ;draw dot
164

Ricardo Quesada's avatar
Ricardo Quesada committed
165 166
        inc     dx                              ;row++

167
        call    beep
Ricardo Quesada's avatar
Ricardo Quesada committed
168 169 170 171 172 173

        dec     di
        jnz     .l1

        ret

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; beep
beep:
        push    ax
        push    cx

        mov     al,0b1011_0110
        out     0x43,al

        mov     ax,0x5533
        out     0x42,al
        mov     al,ah
        out     0x42,al

        in      al,0x61
        mov     ah,al
        or      al,3
        out     0x61,al

        mov     cx,0x6000
.delay0:
        loop    .delay0

        mov     al,ah
        out     0x61,al

        mov     cx,0x6000
.delay1:
        loop    .delay1

        pop     cx
        pop     ax
        ret

208
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
209 210 211 212
; draw a big char in the screen.
; only draws the segments that are needed: will turn on/off only the needed
; segments by doing a "diff" (simple xoring masks) of the previous char
;
213 214
; IN:
;       si = pointer to table of char to draw
215
render_bigchar:
216

217 218 219
        cmp     byte [is_flicker_free],0        ;flicker free enabled?
        jz      .l0                             ; no, so skip

220
        ; begin: update background color
Ricardo Quesada's avatar
Ricardo Quesada committed
221
.wait_retrace:
Ricardo Quesada's avatar
Ricardo Quesada committed
222 223 224
;        cmp     byte [vert_retrace],0                   ;wait for vertical retrace
;        jz      .wait_retrace
;        mov     byte [vert_retrace],0                   ;clear vert retrace
225

Ricardo Quesada's avatar
Ricardo Quesada committed
226
        mov     dx,0x03da
227
        mov     cx,[back_fore_color]            ;cx=new color (to be used in xchg later)
228 229 230

        ; change background color to background color
        sub     bx,bx                           ;bx=0 (to be used in xchg later)
231 232 233
        mov     al,0x11                         ;color index = 1
        out     dx,al                           ;dx=0x03da (register)

234 235 236 237 238 239 240 241 242 243 244 245 246 247
        mov     al,cl                           ;set color
        out     dx,al                           ;set new color (data)

        xchg    ax,bx                           ;ax = 0
        out     dx,al                           ;reset

        in      al,dx                           ;reset to register again

        ; change foreground color to background color
        sub     bx,bx                           ;bx=0 (to be used in xchg later)
        mov     al,0x10                         ;color index = 0
        out     dx,al                           ;dx=0x03da (register)

        mov     al,cl                           ;fast way to set al with new color
248 249 250 251 252 253 254
        out     dx,al                           ;set new color (data)

        xchg    ax,bx                           ;fast way to set al to zero
        out     dx,al                           ;update color (register)

        in      al,dx                           ;reset to register again
        ; end: update background color
Ricardo Quesada's avatar
Ricardo Quesada committed
255

256
.l0:
257
        push    si                                      ;save si for later
258 259

        %assign XX 0
260
        %rep 4                                          ;do it 4 times: 55 segments fit into 64 bits
261 262 263
                mov     ax,[old_segments + XX]          ;read mask of 16-bit
                xor     ax,[si + XX]                    ;xor-it with prev mask
                mov     [segments_to_draw + XX],ax      ;bits that are 'on' are the ones that need to be updated
264 265 266 267
        %assign XX XX+2
        %endrep


268
        sub     bx,bx                                   ;index for call table
269 270

        %assign XX 0
271
        %rep 4                                          ;do it 4 times: 55 segments fit in 64 bits
272 273 274
        %push repeat                                    ;push nasm context, needed for local labels
                mov     dx,[segments_to_draw + XX]      ;get mask bit (64-bits mask. 16 at a time)
                mov     ax,[old_segments + XX]          ;whether to call seg_on or seg_off
275 276 277 278 279 280
                mov     cx,16                           ;inner loop: 16 bits
        %$l_inner:
                shr     ax,1                            ;old segs: mask >> 1.
                rcr     dx,1                            ;to draw segs: mask >> 1 (save last previous state in MSB)
                jnc     %$do_nothing                    ; if 0, skip, do nothing

281
                push    cx                              ;save cx/ax, since they are used in the draw routines
282
                push    ax
283 284
                push    ds

285 286
                test    dx,0b10000000_00000000          ;MSB from old_segments
                jnz     %$turn_off                      ;do the opposite: if old was on, turn it off
287
                call    [seg_on_call_table + bx]        ;turn segment on
288 289
                jmp     %$l0
        %$turn_off:
290
                call    [seg_off_call_table + bx]       ;turn segment off
291
        %$l0:
292 293
                pop     ds
                pop     ax                              ;restore cx/ax
294 295 296 297 298 299
                pop     cx

        %$do_nothing:
                inc     bx                              ;update pointer to next segment to call
                inc     bx
                loop    %$l_inner
300
        %pop                                            ;pop context
301 302 303
        %assign XX XX+2
        %endrep

304
        pop     si                                      ;contains pointer to char to draw
305 306

        %assign XX 0
307
        %rep 4                                          ;do it 4 times: 55 segments fit in 64 bits
308 309
                mov     ax,[si + XX]                    ;update old_segments
                mov     [old_segments + XX],ax
310 311
        %assign XX XX+2
        %endrep
312

313
        cmp     byte [is_flicker_free],0                ;flicker free?
314
        jz      .end                                    ; no, so skip it
315

316
        ; begin: update background / foreground color
Ricardo Quesada's avatar
Ricardo Quesada committed
317 318 319 320 321
        call    wait_vertical_retrace
;.l1:    cmp     byte [vert_retrace],0                   ;wait for vertical retrace
;        jz      .l1
;        mov     byte [vert_retrace],0                   ;clear vert retrace
;        mov     dx,0x03da
322

Ricardo Quesada's avatar
Ricardo Quesada committed
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        sub     bx,bx                                   ;to be used later
        mov     cx,[back_fore_color]                    ;background / foreground colors
        mov     al,0x10                                 ;color index = 0
        out     dx,al                                   ;dx=0x03da (register)

        mov     al,cl                                   ;background color
        out     dx,al                                   ;set new color (data)

        xchg    ax,bx                                   ;ax = 0
        out     dx,al                                   ;reset

        in      al,dx                                   ;reset to register again

        mov     al,0x11                                 ;color index = 1
        out     dx,al                                   ;dx=0x03da (register)

        mov     al,ch                                   ;foreground color
        out     dx,al                                   ;update color (register)

        xchg    ax,bx                                   ;ax = 0
        out     dx,al                                   ;reset

        in      al,dx                                   ;reset to register again
346
        ; end: update background / foreground color
Ricardo Quesada's avatar
Ricardo Quesada committed
347

348
.end:
349 350
        ret

351

352
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
Ricardo Quesada's avatar
Ricardo Quesada committed
353
intro_cleanup:
354
        call    irq_8_cleanup
Ricardo Quesada's avatar
Ricardo Quesada committed
355
        jmp     music_cleanup
356 357

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
Ricardo Quesada's avatar
Ricardo Quesada committed
358
intro_main_loop:
359
.main_loop:
360 361 362 363 364 365 366 367 368 369 370 371
        ;key pressed?
%if EMULATOR
        push    ds
        sub     ax,ax
        mov     ds,ax                           ;ds = zero page
        mov     ax,[0x041a]                     ;keyboard buffer head
        cmp     ax,[0x041c]                     ;keyboard buffer tail
        pop     ds
%else
        in      al,0x62                         ;on real hardware, test keystroke missed?
        and     al,1                            ; so that we can disable IRQ9
%endif
Ricardo Quesada's avatar
Ricardo Quesada committed
372
        jnz     .exit                           ;exit if
Ricardo Quesada's avatar
Ricardo Quesada committed
373 374

        cmp     byte [bigchar_to_render],0      ;is there any bigchar to render?
Ricardo Quesada's avatar
Ricardo Quesada committed
375
        jnz     .render_char
Ricardo Quesada's avatar
Ricardo Quesada committed
376 377 378

        cmp     byte [end_condition],0          ;animation finished?
        jz      .main_loop                      ;no, so keep looping
379

380 381
.exit:
        ret                                     ;exit main loop.
382

Ricardo Quesada's avatar
Ricardo Quesada committed
383
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
Ricardo Quesada's avatar
Ricardo Quesada committed
384
.render_char:
Ricardo Quesada's avatar
Ricardo Quesada committed
385 386 387 388 389 390 391 392
        sub     bh,bh                           ;ah = 0. ax will be used
        mov     bl,byte [bigchar_to_render]
        sub     bl,0x20                         ;char table starts at 0x20 (ascii fo space)

        shl     bx,1                            ;pow(ax,3) == ax * 8
        shl     bx,1                            ; since each entry takes 8 bytes
        shl     bx,1                            ; up to 64 segments each
        lea     si,[table_space+bx]
393
        call    render_bigchar
Ricardo Quesada's avatar
Ricardo Quesada committed
394 395 396 397 398

        mov     al,[bigchar_to_render]
        call    render_smallchar                ;render small char after big char so they are in sync

        mov     byte [bigchar_to_render],0      ;trigger that the char has been rendered
Ricardo Quesada's avatar
Ricardo Quesada committed
399 400
        jmp     .main_loop

401 402 403 404 405 406 407
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; IN:
;    al = char to render
render_smallchar:
        mov     bl,al                           ;move al into bl
        sub     bh,bh
        sub     bl,0x20                         ;reset offset to 0, since charset starts at 0x20
408 409
        mov     cl,4
        shl     bx,cl                           ;multiply by 16, since each char takes 16 bytes
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436

        mov     ax,8192-2                       ;constant used for "add" (reg faster than imm)
        mov     cx,8192+2-80                    ;constant used for "sub" (reg faster than imm)

        lea     si,[charset + bx]               ;calculate source
        mov     di,[char_offset]                ;get destintation
        movsw                                   ;copy 1st row (2 bytes)
        add     di,ax
        movsw                                   ;copy 2nd row (2 bytes)
        sub     di,cx
        movsw                                   ;copy 3rd row (2 bytes)
        add     di,ax
        movsw                                   ;copy 4th row (2 bytes)
        sub     di,cx
        movsw                                   ;copy 5th row (2 bytes)
        add     di,ax
        movsw                                   ;copy 6th row (2 bytes)
        sub     di,cx
        movsw                                   ;copy 7th row (2 bytes)
        add     di,ax
        movsw                                   ;copy 8th row (2 bytes)

        add     word [char_offset],2            ;update cursor for next char

        ret


437

438
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
439
irq_8_handler:
Ricardo Quesada's avatar
Ricardo Quesada committed
440
        pushf
441
        push    es                              ;since we might be interrupting
Ricardo Quesada's avatar
Ricardo Quesada committed
442 443
        push    ds                              ; the main routine, we need to
        push    si                              ; save all used registers
444 445 446 447 448
        push    di
        push    dx
        push    cx
        push    bx
        push    ax
449
        push    bp
450

451 452
        mov     ax,cs
        mov     ds,ax
Ricardo Quesada's avatar
Ricardo Quesada committed
453
        mov     ax,GFX_SEG
454
        mov     es,ax
455

456
        call    music_play
457
        call    text_writer_update
Ricardo Quesada's avatar
Ricardo Quesada committed
458

459 460
        inc     byte [vert_retrace]             ;flag that a vert retrace occurred

461 462 463
        mov     al,0x20                         ;send the EOI signal
        out     0x20,al                         ; to the IRQ controller

464
        pop     bp
465 466 467 468 469 470 471 472
        pop     ax
        pop     bx
        pop     cx
        pop     dx
        pop     di
        pop     si
        pop     ds
        pop     es
Ricardo Quesada's avatar
Ricardo Quesada committed
473
        popf
474

475
        iret
476

Ricardo Quesada's avatar
Ricardo Quesada committed
477 478 479
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
gfx_init:
        ; default palette for the 4 CGA colors
480
        ;call    wait_vertical_retrace
481
        mov     dx,0x03da
Ricardo Quesada's avatar
Ricardo Quesada committed
482
        mov     si,palette_default
Ricardo Quesada's avatar
Ricardo Quesada committed
483
        mov     bl,0x10                         ;first color
Ricardo Quesada's avatar
Ricardo Quesada committed
484 485 486 487 488
        sub     di,di                           ;used to xchg with ax
                                                ; (faster way to set ax to 0)
        mov     cx,4                            ;update 4 colors
.l0:
        mov     al,bl                           ;color to update
Ricardo Quesada's avatar
Ricardo Quesada committed
489
        out     dx,al                           ;dx=0x03da (register)
Ricardo Quesada's avatar
Ricardo Quesada committed
490 491

        lodsb
Ricardo Quesada's avatar
Ricardo Quesada committed
492
        out     dx,ax                           ;color
Ricardo Quesada's avatar
Ricardo Quesada committed
493 494

        xchg    ax,di                           ;fatest way to set al to 0
Ricardo Quesada's avatar
Ricardo Quesada committed
495
        out     dx,al                           ;(register)
Ricardo Quesada's avatar
Ricardo Quesada committed
496

Ricardo Quesada's avatar
Ricardo Quesada committed
497
        in      al,dx                           ;reset to register again
Ricardo Quesada's avatar
Ricardo Quesada committed
498 499 500 501
        inc     bl                              ;next color

        loop    .l0

Ricardo Quesada's avatar
Ricardo Quesada committed
502 503
        ; erase bottom line for text writer
        call    text_writer_clean_bottom_line
Ricardo Quesada's avatar
Ricardo Quesada committed
504 505 506

        ; update some vars
        mov     word [char_offset],CHAR_OFFSET  ;start drawing at row 24
Ricardo Quesada's avatar
Ricardo Quesada committed
507
        mov     byte [text_writer_delay],1      ;wait one frame
Ricardo Quesada's avatar
Ricardo Quesada committed
508 509
                                                ; before rendering next char
        ret
510

511 512 513 514 515 516 517
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
text_writer_update:
        dec     byte [text_writer_delay]
        jz      .l0
        ret
.l0:
        mov     byte [text_writer_delay],7      ;wait a few cycles
518
.read_char:
519
        ;bx is being used later, don't overwrite it
520 521 522
        mov     bx, word [text_writer_offset]
        inc     word [text_writer_offset]
        mov     al, [text_writer_msg + bx]
523 524

        mov     cl,al                           ;save al in bl, to be used if drawing char
Ricardo Quesada's avatar
Ricardo Quesada committed
525
        or      al,al                           ;al == 0? last char ?
526
        jz      .start_again
Ricardo Quesada's avatar
Ricardo Quesada committed
527
        dec     al                              ;al == 1?
Ricardo Quesada's avatar
Ricardo Quesada committed
528
        jz      text_writer_clean_bottom_line
Ricardo Quesada's avatar
Ricardo Quesada committed
529
        dec     al                              ;al == 2?
530
        jz      .disable_flicker_free
Ricardo Quesada's avatar
Ricardo Quesada committed
531
        dec     al                              ;al == 3?
532
        jz      .enable_flicker_free
533
        dec     al                              ;al == 4?
534
        jz      .change_palette
535 536 537 538
        dec     al                              ;al == 5?
        jz      .set_horizontal_pos
        dec     al                              ;al == 6?
        jz      .set_delay
539 540

        ;fall-through. draw char
541
.write:
542
        mov     [bigchar_to_render],cl
Ricardo Quesada's avatar
Ricardo Quesada committed
543
        ret
544

545 546 547 548 549 550 551 552
.enable_flicker_free:
        mov     byte [is_flicker_free],1        ;enable flicker free
        jmp     .read_char                      ;read next char

.disable_flicker_free:
        mov     byte [is_flicker_free],0        ;disable flicker free
        jmp     .read_char                      ;read next char

553 554 555 556
.change_palette:
        ;bx contains index, re-use it
        inc     word [text_writer_offset]       ;update index to text
        inc     bx                              ;update bx (used as index)
557 558
        mov     bl,[text_writer_msg + bx]       ;get palette index
        sub     bh,bh                           ;MSB of bx is 0
559 560 561 562 563
        shl     bx,1                            ;each palette entry takes 2 bytes
        mov     cx,[palette_tbl + bx]
        mov     [back_fore_color],cx            ;replace palette with new one
        jmp     .read_char                      ;read next char

564 565 566 567 568 569 570 571 572 573 574 575 576
.set_horizontal_pos:
        ;bx contains index, re-use it
        inc     word [text_writer_offset]       ;update index to text
        inc     bx                              ;update bx (used as index)
        mov     al,[text_writer_msg + bx]       ;get new horizontal position
        sub     ah,ah                           ;ax contains new pos
        shl     ax,1                            ;multiply by 2: each char takes 2 bytes
                                                ; 1 pixels == 2 bits
        add     ax,CHAR_OFFSET                  ;update offset
        mov     word [char_offset], ax
        jmp     .read_char                      ;read next char

.set_delay:
Ricardo Quesada's avatar
Ricardo Quesada committed
577 578 579
        mov     byte [text_writer_delay],30     ;sets a half-a-second delay
        ret                                     ;dont' read next char, since it will reset
                                                ; the delay
580

581
.start_again:
Ricardo Quesada's avatar
Ricardo Quesada committed
582 583
        mov     byte [end_condition],1          ;end animation
        ;mov     word [text_writer_offset],0     ;reset offset
584
        ; fall-through to text_writer_clean_bottom_line
585

Ricardo Quesada's avatar
Ricardo Quesada committed
586 587
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
text_writer_clean_bottom_line:
588 589 590
        mov     di,CHAR_OFFSET
        mov     word [char_offset],di           ;reset destination for char
        mov     cx,40*4
Ricardo Quesada's avatar
Ricardo Quesada committed
591
        mov     ax,0b10101010_10101010          ;clear color is 0b10
592 593 594 595 596 597 598
        rep stosw

        mov     di,CHAR_OFFSET + 8192
        mov     cx,40*4
        rep stosw
        ret

599 600 601 602 603 604 605 606
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; Rest of code: includes
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
%include 'common/utils.asm'
%include 'common/music_player.asm'
%include 'part1/segment55_data.asm'
%include 'part1/segment55_table.asm'

607 608
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
;
609
; DATA
610 611 612 613
;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
614
; music
615
pvm_song:
616
        incbin 'part1/uctumi-cumparsita.pvm'
617 618 619 620 621

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
; vars
end_condition:          db 0                    ;when 1, banner animation sequence finishes

Ricardo Quesada's avatar
Ricardo Quesada committed
622 623
bigchar_to_render:      db 0                    ;when 0, render finished/not needed. else, contains the ASCII to be rendered

624 625 626
is_flicker_free:        db 1                    ;whether or not foreground color is the same as background
                                                ; while painting big char to prevent
                                                ; flicker-free drawing
627
vert_retrace:           db 0                    ;a verticla retrace have just occurred
Ricardo Quesada's avatar
Ricardo Quesada committed
628 629 630
palette_default:        db 0, 15, 0, 15         ;black/white, black/white
back_fore_color:        dw 0x000f               ;background / foreground colors
                                                ; used for the big letters
631

632
                                                ;   background/foreground
633
palette_tbl:            dw 0x000f               ;0: white/black
Ricardo Quesada's avatar
Ricardo Quesada committed
634
                        dw 0x010f               ;1: white/blue
635
                        dw 0x0400               ;2: black/red
636 637 638 639 640 641 642 643 644 645 646
                        dw 0x0d0b               ;3: magenta/cyan
                        dw 0x0e09               ;4: yellow/blue
                        dw 0x090e               ;5: blue/yellow
                        dw 0x0c08               ;6: red/gray
                        dw 0x080c               ;7: gray/red
                        dw 0x0a05               ;8: green/dark magenta
                        dw 0x050a               ;9: dark magenta/green
                        dw 0x010c               ;10: dark blue/red
                        dw 0x0c01               ;11: red/dark blue
                        dw 0x030e               ;12: dark cyan/yellow
                        dw 0x0e03               ;13: yellow/dark cyan
647
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
648 649 650
old_segments:
        dw 0,0,0,0

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
segments_to_draw:
        dw 0,0,0,0

seg_on_call_table:
        dw segment_0_on
        dw segment_1_on
        dw segment_2_on
        dw segment_3_on
        dw segment_4_on
        dw segment_5_on
        dw segment_6_on
        dw segment_7_on
        dw segment_8_on
        dw segment_9_on
        dw segment_10_on
        dw segment_11_on
        dw segment_12_on
        dw segment_13_on
        dw segment_14_on
        dw segment_15_on
        dw segment_16_on
        dw segment_17_on
        dw segment_18_on
        dw segment_19_on
        dw segment_20_on
        dw segment_21_on
        dw segment_22_on
        dw segment_23_on
        dw segment_24_on
        dw segment_25_on
        dw segment_26_on
        dw segment_27_on
        dw segment_28_on
        dw segment_29_on
        dw segment_30_on
        dw segment_31_on
        dw segment_32_on
        dw segment_33_on
        dw segment_34_on
        dw segment_35_on
        dw segment_36_on
        dw segment_37_on
        dw segment_38_on
        dw segment_39_on
        dw segment_40_on
        dw segment_41_on
        dw segment_42_on
        dw segment_43_on
        dw segment_44_on
        dw segment_45_on
        dw segment_46_on
        dw segment_47_on
        dw segment_48_on
        dw segment_49_on
        dw segment_50_on
        dw segment_51_on
        dw segment_52_on
        dw segment_53_on
        dw segment_54_on
710

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
seg_off_call_table:
        dw segment_0_off
        dw segment_1_off
        dw segment_2_off
        dw segment_3_off
        dw segment_4_off
        dw segment_5_off
        dw segment_6_off
        dw segment_7_off
        dw segment_8_off
        dw segment_9_off
        dw segment_10_off
        dw segment_11_off
        dw segment_12_off
        dw segment_13_off
        dw segment_14_off
        dw segment_15_off
        dw segment_16_off
        dw segment_17_off
        dw segment_18_off
        dw segment_19_off
        dw segment_20_off
        dw segment_21_off
        dw segment_22_off
        dw segment_23_off
        dw segment_24_off
        dw segment_25_off
        dw segment_26_off
        dw segment_27_off
        dw segment_28_off
        dw segment_29_off
        dw segment_30_off
        dw segment_31_off
        dw segment_32_off
        dw segment_33_off
        dw segment_34_off
        dw segment_35_off
        dw segment_36_off
        dw segment_37_off
        dw segment_38_off
        dw segment_39_off
        dw segment_40_off
        dw segment_41_off
        dw segment_42_off
        dw segment_43_off
        dw segment_44_off
        dw segment_45_off
        dw segment_46_off
        dw segment_47_off
        dw segment_48_off
        dw segment_49_off
        dw segment_50_off
        dw segment_51_off
        dw segment_52_off
        dw segment_53_off
        dw segment_54_off

768 769 770 771 772
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
char_offset:
        dw 0                                    ;offset used to render a char
                                                ; from the charset
charset:
Ricardo Quesada's avatar
Ricardo Quesada committed
773
        incbin 'part1/charset_0x20_0x60.bin'      ;the charset already expanded for mode 320x200 @ 4 colors
774 775 776

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;
text_writer_delay:
777
        db 0                                    ;ticks to wait until next char it written
778 779 780
text_writer_offset:
        dw 0                                    ;offset in the text. next char to be written
text_writer_msg:
781 782 783 784 785

TEXT_CMD_CLEAR_LINE equ 1
TEXT_CMD_FLICKER_FREE_OFF equ 2
TEXT_CMD_FLICKER_FREE_ON equ 3
TEXT_CMD_CHANGE_PALETTE equ 4
786 787
TEXT_CMD_START_POS equ 5
TEXT_CMD_DELAY equ 6
788

789
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
790 791 792
;        db 2                                            ;turn off "flicker-free"
;        db '$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%',1
;        db 3                                            ;re-enable "flicker-free"
793
        db TEXT_CMD_START_POS,8                         ;set start pos
794
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
795 796 797
        db         'PUNGAS DE VILLA MARTELLI '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

798
        db TEXT_CMD_START_POS,16                         ;set start pos
799
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
800 801 802 803
        db                 'PRESENTS '
        db TEXT_CMD_DELAY,TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_START_POS,8                         ;set start pos
804
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
805
        db         'A DEMO FOR THE '
806
        db TEXT_CMD_CHANGE_PALETTE,1                    ;set palette blue/black
Ricardo Quesada's avatar
Ricardo Quesada committed
807 808
        db                         'IBM PCJR%& '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE
809 810
        db TEXT_CMD_CHANGE_PALETTE,0                    ;set palette black/white

Ricardo Quesada's avatar
Ricardo Quesada committed
811
        db TEXT_CMD_START_POS,15                        ;set start pos
812
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
813 814
        db                '%&ANY PCJR '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE
815 816 817

        db TEXT_CMD_START_POS,3                         ;set start pos
           ;0123456789012345678901234567890123456789
Ricardo Quesada's avatar
Ricardo Quesada committed
818 819 820 821 822 823 824 825 826 827 828
        db    'INCLUDING THE 64K-RAM-ONLY VERSION '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_START_POS,8                         ;set start pos
           ;0123456789012345678901234567890123456789',
        db         'WHICH HAPPENS TO BE%& '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_START_POS,9                         ;set start pos
           ;0123456789012345678901234567890123456789',
        db          '%&THE SLOWEST PC EVER! '
829
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
830
        db '! '
831
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
832
        db '! '
833
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
834
        db '! '
835
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
836
        db '! '
837
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
838
        db '! '
839
        db TEXT_CMD_START_POS,30
Ricardo Quesada's avatar
Ricardo Quesada committed
840 841 842 843 844 845 846 847 848 849 850
        db '! '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE


        db TEXT_CMD_START_POS,4                         ;set start pos
           ;0123456789012345678901234567890123456789',
        db     'EVEN SLOWER THAN THE IBM PC 5150 '
        db TEXT_CMD_DELAY, TEXT_CMD_DELAY, TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_START_POS,18                        ;set start pos
           ;0123456789012345678901234567890123456789',
851
        db                   'AND%& '
Ricardo Quesada's avatar
Ricardo Quesada committed
852 853 854 855 856 857 858 859 860 861 862 863 864
        db TEXT_CMD_DELAY,TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE
           ;0123456789012345678901234567890123456789',
        db 'DID YOU KNOW THAT EVEN THE COMMODORE 64 '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

        db 'HAS MORE MEMORY THAN THE 64K-ONLY PCJR? '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_START_POS,10                         ;set start pos
           ;0123456789012345678901234567890123456789',
        db           'LET ME SAY THAT AGAIN: '
        db TEXT_CMD_DELAY
        db TEXT_CMD_START_POS,10                         ;set start pos
865
        db           '                      '
Ricardo Quesada's avatar
Ricardo Quesada committed
866 867 868 869 870 871
        db TEXT_CMD_CLEAR_LINE

        db TEXT_CMD_CHANGE_PALETTE,2
           ;0123456789012345678901234567890123456789',
        db ' THE 64K-RAM-ONLY PCJR IS SO BAD THAT%& '
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE
872 873

           ;0123456789012345678901234567890123456789',
Ricardo Quesada's avatar
Ricardo Quesada committed
874
        db '  EVEN THE C64 HAS MORE USABLE MEMORY! '
Ricardo Quesada's avatar
Ricardo Quesada committed
875 876 877 878 879 880 881 882 883
        db TEXT_CMD_DELAY,TEXT_CMD_CLEAR_LINE
        db TEXT_CMD_CHANGE_PALETTE,0

        db TEXT_CMD_START_POS,2                         ;set start pos
           ;0123456789012345678901234567890123456789',
        db   'ON THE POSITIVE SIDE THE PCJR HAS%& '
        db TEXT_CMD_DELAY
        db TEXT_CMD_CLEAR_LINE

884
        db TEXT_CMD_START_POS,2                         ;set start pos
Ricardo Quesada's avatar
Ricardo Quesada committed
885
           ;0123456789012345678901234567890123456789',
886
        db   '%&A 320 X 200 @ 16-COLOR VIDEO MODE '
Ricardo Quesada's avatar
Ricardo Quesada committed
887 888 889
        db TEXT_CMD_DELAY
        db TEXT_CMD_CLEAR_LINE

890 891 892 893 894 895 896 897

           ;0123456789012345678901234567890123456789',
        db 2                                    ;turn off "flicker-free"
        db '$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#',1         ;bat animation
        db 3                                    ;turn on "flicker-free" again

        db 1                                    ;clean line

898
        db TEXT_CMD_START_POS,8                         ;set start pos
Ricardo Quesada's avatar
Ricardo Quesada committed
899 900 901
        dw 0x0104                                       ;change palette
        db 'P'
        dw 0x0304                                       ;change palette
902
        db 'U'
Ricardo Quesada's avatar
Ricardo Quesada committed
903
        dw 0x0504                                       ;change palette
904
        db 'N'
Ricardo Quesada's avatar
Ricardo Quesada committed
905
        dw 0x0c04
906
        db 'G'
Ricardo Quesada's avatar
Ricardo Quesada committed
907
        dw 0x0204
908
        db 'A'
Ricardo Quesada's avatar
Ricardo Quesada committed
909
        dw 0x0404
910 911 912
        db 'S'
        dw 0x0004
        db ' '
913
        dw 0x0104                                       ;change palette
914
        db 'D'
915
        dw 0x0304                                       ;change palette
916 917 918 919
        db 'E'
        dw 0x0504                                       ;change palette
        db ' '
        dw 0x0c04
920
        db 'V'
921 922 923 924 925 926 927 928
        dw 0x0204
        db 'I'
        dw 0x0404
        db 'L'
        dw 0x0604
        db 'L'
        dw 0x0004
        db 'A'  
929
        dw 0x0504                                       ;change palette
930 931
        db ' '
        dw 0x0104                                       ;change palette
932
        db 'M'
933 934 935 936
        dw 0x0304                                       ;change palette
        db 'A'
        dw 0x0504                                       ;change palette
        db 'R'
937
        dw 0x0c04
938
        db 'T'
939
        dw 0x0204
940
        db 'E'
941
        dw 0x0404
942 943 944
        db 'L'
        dw 0x0404
        db 'L'
945
        dw 0x0604
946 947 948
        db 'I'
        dw 0x0004
        db ' '
949

950 951 952
        db TEXT_CMD_DELAY
        db TEXT_CMD_DELAY
        db TEXT_CMD_DELAY
953
        db 0