1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 ; PengoAlpaca.asm 3 ; 4 ; ALPACA: A Multitasking operating system for Pengo Z80 arcade hardware 5 ; 6 ; Written by 7 ; Scott "Jerry" Lawrence 8 ; alpaca@umlautllama.com 9 ; 10 ; This source file is covered by the LGPL: 11 ; 12 ;; Alpaca - A Multitasking operating system for Z80 arcade hardware 13 ;; Copyright (C) 2003 Scott "Jerry" Lawrence 14 ;; alpaca@umlautllama.com 15 ;; 16 ;; This is free software; you can redistribute it and/or modify 17 ;; it under the terms of the GNU Lesser General Public License 18 ;; as published by the Free Software Foundation; either version 19 ;; 2 of the License, or (at your option) any later version. 20 ;; 21 ;; This software is distributed in the hope that it will be 22 ;; useful, but WITHOUT ANY WARRANTY; without even the implied 23 ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 24 ;; PURPOSE. See the GNU Lesser General Public License for 25 ;; more details. 26 ;; 27 ;; You should have received a copy of the GNU Lesser General 28 ;; Public License along with this library; if not, write to 29 ;; the Free Foundation, Inc., 59 Temple Place, Suite 330, 30 ;; Boston, MA 02111-1307 USA 31 ; 32 33 34 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 35 ; 36 ; This file is machine generated. Do not edit it by hand! 37 ; 38 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 39 40 41 .title alpaca 42 .module alpaca 43 44 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 45 ; some constants: 8FF0 46 stack = 0x8ff0 8000 47 vidram = 0x8000 8400 48 colram = 0x8400 8800 49 ram = 0x8800 9040 50 dsw0 = 0x9040 9080 51 in1 = 0x9080 90C0 52 in0 = 0x90c0 9000 53 specreg = 0x9000 00FF 54 speclen = 0x00ff 8FF2 55 sprtbase = 0x8ff2 0010 56 sprtlen = 0x0010 0001 57 p1_up = 0x01 0002 58 p1_down = 0x02 0004 59 p1_left = 0x04 0008 60 p1_right = 0x08 0010 61 coin1 = 0x10 0020 62 coin2 = 0x20 0040 63 coin3 = 0x40 0080 64 button1 = 0x80 0001 65 p2_up = 0x01 0002 66 p2_down = 0x02 0004 67 p2_left = 0x04 0008 68 p2_right = 0x08 0010 69 service = 0x10 0020 70 start1 = 0x20 0040 71 start2 = 0x40 0080 72 button1 = 0x80 8FF2 73 spritebase = 0x8ff2 0006 74 nsprites = 0x06 9022 75 spritecoords = 0x9022 9005 76 v1_wave = 0x9005 9011 77 v1_freq = 0x9011 9015 78 v1_vol = 0x9015 900A 79 v2_wave = 0x900a 9016 80 v2_freq = 0x9016 901A 81 v2_vol = 0x901a 900F 82 v3_wave = 0x900f 901B 83 v3_freq = 0x901b 901F 84 v3_vol = 0x901f 9040 85 irqen = 0x9040 9041 86 sounden = 0x9041 9043 87 flipscreen = 0x9043 9044 88 coincount = 0x9044 9070 89 watchdog = 0x9070 9042 90 palbank = 0x9042 9046 91 collutbank = 0x9046 9047 92 spritebank = 0x9047 93 94 95 ; constants for the task system 00C0 96 stacksize = 192 ; number of bytes per stack 00FF 97 openslot = 0xff ; the flag for an open slot 00FF 98 killslot = 0xff ; the flag for a slot to be killed 00FE 99 freetime = 0xfe ; the flag for a task giving up time 0007 100 taskon = 7 ; multitasking is enabled (bit 7) 101 102 ; constants for the GUI system: 103 ; GUI constants 104 ; cursor and wallpaper 0001 105 PcursorS = 1 ; sprite 1 for the cursor 0009 106 PcursorC = 9 ; color 9 for the cursor 107 00A2 108 PwpS = 162 ; wallpaper sprite 0010 109 PwpC = 0x10 ; wallpaper color 0x13- blues 110 0010 111 LlamaC = 0x10 ; llama color (might be the same as PwpC above) 0014 112 CprtC = 0x14 ; copyright color 11 113 ; flags 0001 114 F_Noframe = 1 ; no frame in render (hard flag) 0002 115 F_Frame = 2 ; frame in render (hard flag) 116 0001 117 F_Dirty = 1 ; frame needs redraw (soft flag) 0002 118 F_Focus = 2 ; frame is capturing focus currently 119 ; -- frame widgets -- 120 ; close 0080 121 PcloseS = 128 ; close widget sprite 0001 122 PcloseCS = 1 ; close widget selected color (5) 001E 123 PcloseCU = 0x1e ; close widget unselected color 124 125 ; raise 0083 126 PraiseS = 131 ; raise widget sprite 0001 127 PraiseCS = 1 ; raise widget selected color (5) 000C 128 PraiseCU = 0xc ; raise widget unselected color 129 130 ; -- frame ornaments -- 0009 131 PfrmTSel = 9 ; dragbar text selected color 0x14 0xb 0001 132 PfrmTUns = 1 ; dragbar text unselected color 133 0001 134 PfrmCSel = 1 ; frame selected color 001E 135 PfrmCUns = 0x1e ; frame unselected color 136 137 ; bottom corners 008A 138 PSWcornS = 138 ; southwest corner 008B 139 PSEcornS = 139 ; southeast corner 140 141 ; top corners 0001 142 PNWcornS = 1 ; northwest corner 140 0001 143 PNEcornS = 1 ; northeast corner 141 144 145 ; top bar 0081 146 PfN_W = 129 ; top left (145 or 129) 0020 147 PfN_N = 32 ; top center (146 or 32) 0082 148 PfN_E = 130 ; top right (147 or 130) 149 150 ; left bar 0084 151 PfW_N = 132 ; left top 0085 152 PfW_W = 133 ; left center 0086 153 PfW_S = 134 ; left bottom 154 155 ; right bar 0087 156 PfE_N = 135 ; right top 0088 157 PfE_E = 136 ; right center 0089 158 PfE_S = 137 ; right bottom 159 160 ; bottom bar 008E 161 PfS_W = 142 ; bottom left 008F 162 PfS_S = 143 ; bottom center 0090 163 PfS_E = 144 ; bottom right 164 ; widgets 0001 165 PwC = 1 ; generic widget color 007F 166 PwBGS = 127 ; window background sprite 167 168 ; button 0094 169 PwbLuS = 148 ; [ button left unselected sprite 0095 170 PwbRuS = 149 ; ] button right unselected sprite 171 172 ; selected button 0096 173 PwbLsS = 150 ; [[ button left selected sprite 0097 174 PwbRsS = 151 ; ]] button right selected sprite 175 176 ; checkbox 0098 177 PwcuS = 152 ; [ ] checkbox unselected sprite 0099 178 PwcsS = 153 ; [X] checkbox selected sprite 179 180 ; radio box 009A 181 PwruS = 154 ; ( ) radio unselected sprite 009B 182 PwrsS = 155 ; (X) radio selected sprite 183 184 ; slider 009C 185 PwsnS = 156 ; === slider notch sprite 009D 186 PwsbS = 157 ; =|= slider bar sprite 187 188 ; progress bar 009E 189 PwpoS = 158 ; progress bar open sprite 009F 190 PwpfS = 159 ; ### progress bar filled sprite 191 192 ; spin 00A0 193 PwHsS = 160 ; <> horizontal spin controller 00A1 194 PwVsS = 161 ; ^v vertical spin controller 195 ; Widget Types (for the frame-widget table) 196 0000 197 W_End = 0 ; end of the widget list 0001 198 W_Frame = 1 ; window frame (needs to be first) 199 200 ; frame flags: 0001 201 FF_Border = 1 ; use a border on the frame 0002 202 FF_NClose = 2 ; no close button 0004 203 FF_NRaise = 4 ; no raise button 204 0002 205 W_MButton = 2 ; momentary button 0003 206 W_SButton = 3 ; sticky button 207 0004 208 W_Radio = 4 ; radio button (flags is the group number) 0005 209 W_Check = 5 ; check button 210 0006 211 W_SText = 6 ; static text (text is the idx of a string) 0007 212 W_DText = 7 ; dynamic text (data is idx of ram) 213 0008 214 W_DInt = 8 ; dynamic integer (data is idx in the ram) 215 0009 216 W_HSlider = 9 ; horizontal slider 000A 217 W_VSlider = 10 ; vertical slider 218 000B 219 W_HSpin = 11 ; horizontal spin 000C 220 W_VSpin = 12 ; vertical spin 221 222 223 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 224 ; RAM allocation: 225 ; which task is in which slot (index into tasklist) 8808 226 taskslot = (ram + 8) ; 4 bytes, one per slot 8808 227 t0slot = (ram + 8) 8809 228 t1slot = (ram + 9) 880A 229 t2slot = (ram + 10) 880B 230 t3slot = (ram + 11) 231 ; control information for each slot (to be handled by switcher) 880C 232 taskctrl = (ram + 12) ; 4 bytes, one per slot 880C 233 t0ctrl = (ram + 12) 880D 234 t1ctrl = (ram + 13) 880E 235 t2ctrl = (ram + 14) 880F 236 t3ctrl = (ram + 15) 237 ; various flags about the task switcher system 8810 238 taskflag = (ram + 16) 239 ; stack pointers for the four slots 8800 240 taskstack = (ram + 0) ; 8 bytes, two per slot 8800 241 t0sp = (ram + 0) 8802 242 t1sp = (ram + 2) 8804 243 t2sp = (ram + 4) 8806 244 t3sp = (ram + 6) 245 ; timer counter (word) 8811 246 timer = (ram + 17) 247 ; messages 94A0 248 msgbase = (ram + 0x0ca0) 94DF 249 msgmax = (msgbase + 0x003f) 250 ; semaphores 94E0 251 semabase = (ram + 0x0ce0) 94EF 252 semamax = (semabase + 0x0F) 253 ; stack regions for the four tasks 8CF0 254 stackbottom = (stack-(stacksize*4)) ; 192 bytes (bottom of stack 3) 8DB0 255 stack3 = (stack-(stacksize*3)) ; 192 bytes 8E70 256 stack2 = (stack-(stacksize*2)) ; 192 bytes 8F30 257 stack1 = (stack-(stacksize*1)) ; 192 bytes 8FF0 258 stack0 = (stack) ; top of space - sprite ram 259 260 261 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 262 ; area configuration 263 ; we want absolute dataspace, with this area called "CODE" 264 .area .CODE (ABS) 265 266 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 267 ; RST functions 268 269 ; RST 00 270 .org 0x000 0000 271 .reset00: ; RST 00 - Init 0000 C3 85 00 272 jp .start 273 274 ; RST 08 275 .org 0x0008 0008 276 .reset08: ; RST 08 - Semaphore control 0008 C9 277 ret 278 279 ; RST 10 280 .org 0x0010 0010 281 .reset10: ; RST 10 - Malloc 0010 C9 282 ret 283 284 ; RST 18 285 .org 0x0018 0018 286 .reset18: ; RST 18 - Free 0018 C9 287 ret 288 289 ; RST 20 290 .org 0x0020 0020 291 .reset20: ; RST 20 - Message Push / Pop 0020 C9 292 ret 293 294 ; RST 28 295 .org 0x0028 0028 296 .reset28: ; RST 28 - TBD 0028 C9 297 ret 298 299 ; RST 30 300 .org 0x0030 0030 301 .reset30: ; RST 30 - TBD 0030 C9 302 ret 303 304 ; RST 38 305 .org 0x0038 0038 306 .reset38: ; RST 38 - Vblank Interrupt Service Routine 0038 C3 68 00 307 jp .isr 308 309 ; NMI 310 .org 0x0066 0066 311 .nmi: ; NMI handler 0066 ED 45 312 retn 313 314 315 316 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 317 ; interrupt service routine: 0068 318 .isr: 0068 F3 319 di ; disable interrupts (no re-entry!) 0069 F5 320 push af ; store aside some registers 006A C5 321 push bc 006B AF 322 xor a ; a = 0 006C 32 40 90 323 ld (irqen), a ; disable external interrupt mechanism 006F 32 70 90 324 ld (watchdog), a ; kick the dog 0072 ED 4B 11 88 325 ld bc, (timer) ; bc = timer 0076 03 326 inc bc ; bc++ 0077 ED 43 11 88 327 ld (timer), bc ; timer = bc 328 ;; task switch stuff 329 330 ; if switching is disabled, skip 331 ; if (taskflag) & bit7 == 0 332 ; jp .doneTask 333 334 ; current task is invalid (taskslot) == 0xff 335 ; skip to next task 336 ; push all regs 337 ; currentslot = (taskflag) 338 ; inc currentslot 339 ; currentslot &= 0x13 340 ; (taskflag) gets currentslot 341 ; jp .skipTask 342 343 ; current task has control MGMT items? 344 ; currentslot = (taskflag) & 0x03 345 ; 346 347 ; kill current task 348 ; currentslot = (taskflag) & 0x03 349 ; (taskslot)+currentslot gets [openslot] 350 351 ; start new task 352 353 ; restart current task 354 355 ; jp .doneTask 356 357 ; current task is running 358 ; decrement time 359 ; dec (tasktime) 360 ; FALL THROUGH 361 362 ; current task giving up its time (control)==[freetime] 363 ; time set to 0 364 ; ld (tasktime), 0 365 ; FALL THROUGH 366 367 ; current task ran out of time (tasktime) == 0 007B 368 .skipTask: 369 ; skip to next valid task 370 ; inc task & 0x03 until 371 ; we're back on ourselves 372 ; or 373 ; we find a valid task 374 ; reset tasktime 375 ; jp .doneTask 007B 376 .doneTask: 377 007B 3E 01 378 ld a, #0x01 ; a = 1 007D 32 40 90 379 ld (irqen), a ; enable external interrupt mechanism 0080 C1 380 pop bc ; restore those regs 0081 F1 381 pop af 0082 FB 382 ei ; enable processor interrupts 0083 ED 4D 383 reti ; return from interrupt routine 384 385 386 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 387 ; the core OS stuff: 0085 388 .start: 0085 F3 389 di ; disable processor interrupts 0086 31 F0 8F 390 ld sp, #(stack) ; setup the initial stack pointer 0089 ED 56 391 im 1 ; setup interrupt mode 1 392 393 ;; clear the special registers 008B 3E 00 394 ld a, #0x00 ; a = 0x00 008D 21 00 90 395 ld hl, #(specreg) ; hl = start of special registers 0090 06 FF 396 ld b, #(speclen) ; b = 0xC0 bytes to zero 0092 CD 55 01 397 call memset256 ; 0x5000-0x50C0 will get 0x00 398 399 ;; clear sprite registers 0095 3E 00 400 ld a, #0x00 ; a = 0x00 0097 21 F2 8F 401 ld hl, #(sprtbase) ; hl = start of sprite registers 009A 06 10 402 ld b, #(sprtlen) ; b = 0x10 16 bytes 009C CD 55 01 403 call memset256 ; 0x4ff0-0x4fff will get 0x00 404 405 ;; clear the screen ram 009F CD 64 01 406 call cls ; clear the screen RAM 407 408 ;; clear user ram 00A2 21 00 88 409 ld hl, #(ram) ; hl = base of RAM 00A5 3E 00 410 ld a, #0x00 ; a = 0 00A7 06 02 411 ld b, #0x02 ; b = 2 blocks of 256 bytes to clear 00A9 CD 5A 01 412 call memsetN ; clear the blocks 413 414 ;; initialize tasks 415 ; clear flags 00AC AF 416 xor a ; a=0 00AD 32 10 88 417 ld (taskflag), a ; clear all task flags 418 ; clear the dorman stack pointers 00B0 01 00 00 419 ld bc, #0x0000 ; bc = 0x0000 00B3 ED 43 00 88 420 ld (t0sp), bc ; task 0 stack pointer gets 0x0000 00B7 ED 43 02 88 421 ld (t1sp), bc ; task 1 stack pointer gets 0x0000 00BB ED 43 04 88 422 ld (t2sp), bc ; task 2 stack pointer gets 0x0000 00BF ED 43 06 88 423 ld (t3sp), bc ; task 3 stack pointer gets 0x0000 424 ; all slots are open 00C3 3E FF 425 ld a, #(openslot) ; a = openslot 00C5 32 08 88 426 ld (t0slot), a ; set task slot 0 as open 00C8 32 09 88 427 ld (t1slot), a ; set task slot 1 as open 00CB 32 0A 88 428 ld (t2slot), a ; set task slot 2 as open 00CE 32 0B 88 429 ld (t3slot), a ; set task slot 3 as open 430 ; enable the task switcher 00D1 3E 07 431 ld a, #(taskon) ; a = taskon 00D3 32 10 88 432 ld (taskflag), a ; set the flag 433 434 ;; setup pac interrupts 00D6 3E FF 435 ld a, #0xff ; fill register 'a' with 0xff 00D8 D3 00 436 out (0x00), a ; send the 0xff to port 0x00 00DA 3E 01 437 ld a, #0x01 ; fill register 'a' with 0x01 00DC 32 40 90 438 ld (irqen), a ; enable the external interrupt mechanism. 00DF FB 439 ei 440 441 ;; display splash screen 00E0 00 442 nop 443 444 ;; start runtime 00E1 CD 64 01 445 call cls 446 00E4 447 foo: 448 ;; fill some color ram with color 1 00E4 21 00 84 449 ld hl, #colram 00E7 3E 01 450 ld a, #0x01 00E9 06 04 451 ld b, #0x04 00EB CD 5A 01 452 call memsetN 453 00EE 01 0A 00 454 ld bc, #10 00F1 CD 75 01 455 call sleep 456 457 ;; fill some char ram with 'X' 00F4 21 00 80 458 ld hl, #vidram 00F7 3E 58 459 ld a, #0x58 00F9 06 04 460 ld b, #0x04 00FB CD 5A 01 461 call memsetN 462 00FE 01 0A 00 463 ld bc, #10 0101 CD 75 01 464 call sleep 465 0104 C3 11 01 466 jp over 0107 3E 01 467 ld a, #0x01 0109 CD 8A 01 468 call semalock 010C 3E 01 469 ld a, #0x01 010E CD 8A 01 470 call semalock 0111 471 over: 472 473 ;; fill some color ram with color 8 0111 21 00 84 474 ld hl, #colram 0114 3E 09 475 ld a, #0x09 0116 06 04 476 ld b, #0x04 0118 CD 5A 01 477 call memsetN 478 011B 01 0A 00 479 ld bc, #10 011E CD 75 01 480 call sleep 481 482 ;; fill some space with 'Y' 0121 21 00 80 483 ld hl, #vidram 0124 3E 59 484 ld a, #0x59 0126 06 04 485 ld b, #0x04 0128 CD 5A 01 486 call memsetN 487 012B 01 0A 00 488 ld bc, #10 012E CD 75 01 489 call sleep 490 491 ;; fill some color ram with color 0x0f 0131 21 00 84 492 ld hl, #colram 0134 3E 0F 493 ld a, #0x0F 0136 06 04 494 ld b, #0x04 0138 CD 5A 01 495 call memsetN 496 013B 01 0A 00 497 ld bc, #10 013E CD 75 01 498 call sleep 499 500 ;; fill some space with 'Z' 0141 21 00 80 501 ld hl, #vidram 0144 3E 5A 502 ld a, #0x5A 0146 06 04 503 ld b, #0x04 0148 CD 5A 01 504 call memsetN 505 014B 01 0A 00 506 ld bc, #10 014E CD 75 01 507 call sleep 508 0151 C3 E4 00 509 jp foo 0154 76 510 halt 511 512 513 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 514 ; some helpful utility functions 515 516 ; memset256 517 ;; memset256 - set up to 256 bytes of ram to a certain value 518 ; in a value to poke 519 ; in b number of bytes to set 0x00 for 256 520 ; in hl base address of the memory location 521 ; out - 522 ; mod hl, bc 0155 523 memset256: 0155 77 524 ld (hl), a ; *hl = 0 0156 23 525 inc hl ; hl++ 0157 10 FC 526 djnz memset256 ; decrement b, jump to memset256 if b>0 0159 C9 527 ret ; return 528 529 530 ; memsetN 531 ;; memsetN - set N blocks of ram to a certain value 532 ; in a value to poke 533 ; in b number of blocks to set 534 ; in hl base address of the memory location 535 ; out - 536 ; mod hl, bc 015A 537 memsetN: 015A C5 538 push bc ; set aside bc 015B 06 00 539 ld b, #0x00 ; b = 256 015D CD 55 01 540 call memset256 ; set 256 bytes 0160 C1 541 pop bc ; restore the outer bc 0161 10 F7 542 djnz memsetN ; if we're not done, set another chunk. 0163 C9 543 ret ; otherwise return 544 545 546 ; clear screen 547 ;; cls - clear the screen (color and video ram) 548 ; in - 549 ; out - 550 ; mod - 0164 551 cls: 0164 E5 552 push hl ; set aside some registers 0165 F5 553 push af 0166 C5 554 push bc 555 0167 21 00 80 556 ld hl, #(vidram) ; base of video ram 016A 3E 05 557 ld a, #0x05 ; clear the screen to 0x00 016C 06 08 558 ld b, #0x08 ; need to set 256 bytes 8 times. 559 016E CD 5A 01 560 call memsetN ; do it. 561 0171 C1 562 pop bc ; restore the registers 0172 F1 563 pop af 0173 E1 564 pop hl 0174 C9 565 ret ; return 566 567 568 ; sleep 569 ;; sleep - wait a specified number of ticks 570 ; in bc number of ticks to wait 571 ; out - 572 ; mod - 0175 573 sleep: 574 ; set side some registers 0175 C5 575 push bc 0176 F5 576 push af 0177 E5 577 push hl 578 ; compute the timeout into BC 0178 2A 11 88 579 ld hl, (timer) ; hl = timer 017B 09 580 add hl, bc ; hl += ticks to wait 017C E5 581 push hl ; bc = 017D C1 582 pop bc ; = hl 017E 583 .slp: 584 ; loop until the timeout comes 017E 2A 11 88 585 ld hl, (timer) ; hl = current time 0181 ED 42 586 sbc hl, bc ; set flags 0183 FA 7E 01 587 jp M, .slp ; if (HL >= BC) then JP .slp2 588 ; restore the registers 0186 E1 589 pop hl 0187 F1 590 pop af 0188 C1 591 pop bc 592 ; return 0189 C9 593 ret 594 595 596 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 597 ; semaphore control 598 599 ; lock semaphore 600 ;; semalock - lock a semaphore 601 ; in a which semaphore to lock 602 ; out - 603 ; mod - 018A 604 semalock: 605 ; set aside registers 018A F5 606 push af 018B C5 607 push bc 018C E5 608 push hl 609 ; set up the address 018D E6 0F 610 and #0x0F ; limit A to 0..15 018F 4F 611 ld c, a ; c is the current semaphore number 0190 06 00 612 ld b, #0x00 ; b=0 (bc = 0x00SS) 0192 2A E0 94 613 ld hl, (semabase) ; hl = base address 0195 09 614 add hl, bc ; hl = address of this semaphore 0196 615 .sl2: 0196 CB 4E 616 bit 1, (hl) 0198 C2 96 01 617 jp NZ, .sl2 ; while it's set, loop 618 ; set the bit 019B CB CE 619 set 1, (hl) ; lock the semaphore 620 ; restore registers 019D E1 621 pop hl 019E C1 622 pop bc 019F F1 623 pop af 624 ; return 01A0 C9 625 ret 626 627 ; release semaphore 628 ;; semarel - release a semaphore 629 ; in a which semaphore to release 630 ; out - 631 ; mod - 01A1 632 semarel: 633 ; set aside registers 01A1 F5 634 push af 01A2 C5 635 push bc 01A3 E5 636 push hl 637 ; set up the address 01A4 E6 0F 638 and #0x0F ; limit A to 0..15 01A6 4F 639 ld c, a ; c is the current semaphore number 01A7 06 00 640 ld b, #0x00 ; b=0 (bc = 0x000S) 01A9 2A E0 94 641 ld hl, (semabase) ; hl = base address 01AC 09 642 add hl, bc ; hl = address of this semaphore 643 ; clear the semaphore 01AD CB 8E 644 res 1, (hl) ; clear the bit 645 ; restore registers 01AF E1 646 pop hl 01B0 C1 647 pop bc 01B1 F1 648 pop af 649 ; return 01B2 C9 650 ret 651 652 653 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 654 ; task exec and kill routines 655 656 ;; execstart - starts up a new task 657 ; in E task number to start 658 ; in D task slot to use (0..3) 659 ; out - 660 ; mod - 01B3 661 execstart: 662 ; save registers we're using 01B3 F5 663 push af 01B4 D5 664 push de 01B5 C5 665 push bc 01B6 E5 666 push hl 667 ; limit E (task) to 127 01B7 CB BB 668 res 7, e ; limit task number to 127 669 ; limit D (slot) 01B9 7A 670 ld a, d ; a=d 01BA E6 03 671 and #0x03 ; slot is 0,1,2, or 3 01BC 4F 672 ld c, a ; c=a 01BD 06 00 673 ld b, #0x00 ; b=0x00, bc = 0x000S 674 ; set the control value 01BF 21 0C 88 675 ld hl, #(taskctrl) ; set up the control register 01C2 09 676 add hl, bc ; hl = base + offset 01C3 73 677 ld (hl), e ; taskctrl[d] = e 678 ; restore the registers 01C4 E1 679 pop hl 01C5 C1 680 pop bc 01C6 D1 681 pop de 01C7 F1 682 pop af 683 ; return 01C8 C9 684 ret 685 686 ;; execkill - kills a running task 687 ; in D task slot to kill 688 ; out - 689 ; mod - 01C9 690 execkill: 691 ; save registers we're using 01C9 F5 692 push af 01CA D5 693 push de 01CB C5 694 push bc 01CC E5 695 push hl 696 ; limit D (slot) and shove it into C 01CD 7A 697 ld a, d ; a=d 01CE E6 03 698 and #0x03 ; slot is 0,1,2, or 3 01D0 4F 699 ld c, a ; c=a 01D1 06 00 700 ld b, #0x00 ; b=0x00, bc = 0x000S 701 ; set the control value 01D3 21 0C 88 702 ld hl, #(taskctrl) ; set up the control register 01D6 09 703 add hl, bc ; hl = base + offset 01D7 36 FF 704 ld (hl), #(killslot) ; taskctrl[d] = KILL! 705 ; restore the registers 01D9 E1 706 pop hl 01DA C1 707 pop bc 01DB D1 708 pop de 01DC F1 709 pop af 710 ; return 01DD C9 711 ret 712 713 714 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 715 ; The tasks 716 717 ; task list -- list of all available tasks 718 ; list of all tasks available, null terminated 01DE 719 tasklist: 01DE E8 01 720 .word t0header 01E0 26 02 721 .word t1header 01E2 50 02 722 .word t2header 01E4 8E 02 723 .word t3header 01E6 00 00 724 .word 0x0000 725 726 727 ;;;;;;;;;;;;;;;;;;;; 728 ; task number 0 729 ;; Task 0 - PTUI 01E8 730 t0header: 01E8 C9 4A 73 4C 731 .byte 0xc9, 0x4a, 0x73, 0x4c ; cookie 01EC 01 732 .byte 0x01 ; version 01ED 04 733 .byte 0x04 ; requested timeslices 01EE F2 01 734 .word t0name ; name 01F0 FA 01 735 .word t0process ; process function 736 01F2 737 t0name: 01F2 06 738 .byte 6 ; strlen 01F3 54 61 73 6B 20 30 739 .asciz "Task 0" ; name 00 740 01FA 741 t0process: 01FA 21 00 84 742 ld hl, #(colram) ; base of color ram 01FD 3E 01 743 ld a, #0x01 ; clear the screen to 0x00 01FF 06 04 744 ld b, #0x04 ; 256*4 = 1k 0201 CD 5A 01 745 call memsetN ; do it. 746 0204 747 t0p2: 0204 21 00 80 748 ld hl, #(vidram) ; base of video ram 0207 3E 41 749 ld a, #0x41 ; 'A' 0209 06 04 750 ld b, #0x04 ; 256*4 = 1k 020B CD 5A 01 751 call memsetN 752 020E 21 00 80 753 ld hl, #(vidram) ; base of video ram 0211 3E 42 754 ld a, #0x42 ; 'B' 0213 06 04 755 ld b, #0x04 ; 256*4 = 1k 0215 CD 5A 01 756 call memsetN 757 0218 21 00 80 758 ld hl, #(vidram) ; base of video ram 021B 3E 43 759 ld a, #0x43 ; 'C' 021D 06 04 760 ld b, #0x04 ; 256*4 = 1k 021F CD 5A 01 761 call memsetN 762 0222 C3 04 02 763 jp t0p2 0225 76 764 halt 765 766 767 ;;;;;;;;;;;;;;;;;;;; 768 ; task number 1 769 ;; Task 1 - TBD 0226 770 t1header: 0226 C9 4A 73 4C 771 .byte 0xc9, 0x4a, 0x73, 0x4c ; cookie 022A 01 772 .byte 0x01 ; version 022B 04 773 .byte 0x04 ; requested timeslices 022C 30 02 774 .word t1name ; name 022E 38 02 775 .word t1process ; process function 776 0230 777 t1name: 0230 06 778 .byte 6 ; strlen 0231 54 61 73 6B 20 31 779 .asciz "Task 1" ; name 00 780 0238 781 t1process: 0238 21 00 84 782 ld hl, #(colram) ; base of color ram 023B 3E 01 783 ld a, #0x01 ; clear the screen to blue 023D 06 04 784 ld b, #0x04 ; 256*4 = 1k 023F CD 5A 01 785 call memsetN 786 0242 21 00 84 787 ld hl, #(colram) ; base of color ram 0245 3E 09 788 ld a, #0x09 ; clear the screen to red 0247 06 04 789 ld b, #0x04 ; 256*4 = 1k 0249 CD 5A 01 790 call memsetN 791 024C C3 38 02 792 jp t1process 024F 76 793 halt 794 795 796 ;;;;;;;;;;;;;;;;;;;; 797 ; task number 2 798 ;; Task 2 - TBD 0250 799 t2header: 0250 C9 4A 73 4C 800 .byte 0xc9, 0x4a, 0x73, 0x4c ; cookie 0254 01 801 .byte 0x01 ; version 0255 04 802 .byte 0x04 ; requested timeslices 0256 5A 02 803 .word t2name ; name 0258 62 02 804 .word t2process ; process function 805 025A 806 t2name: 025A 06 807 .byte 6 ; strlen 025B 54 61 73 6B 20 32 808 .asciz "Task 2" ; name 00 809 0262 810 t2process: 0262 21 00 84 811 ld hl, #(colram) ; base of color ram 0265 3E 01 812 ld a, #0x01 ; clear the screen to 0x00 0267 06 04 813 ld b, #0x04 ; 256*4 = 1k 0269 CD 5A 01 814 call memsetN 815 026C 21 00 80 816 ld hl, #(vidram) ; base of video ram 026F 3E 61 817 ld a, #0x61 ; 'a' 0271 06 04 818 ld b, #0x04 ; 256*4 = 1k 0273 CD 5A 01 819 call memsetN 820 0276 21 00 80 821 ld hl, #(vidram) ; base of video ram 0279 3E 62 822 ld a, #0x62 ; 'b' 027B 06 04 823 ld b, #0x04 ; 256*4 = 1k 027D CD 5A 01 824 call memsetN 825 0280 21 00 80 826 ld hl, #(vidram) ; base of video ram 0283 3E 63 827 ld a, #0x63 ; 'c' 0285 06 04 828 ld b, #0x04 ; 256*4 = 1k 0287 CD 5A 01 829 call memsetN 830 028A C3 62 02 831 jp t2process 028D 76 832 halt 833 834 835 ;;;;;;;;;;;;;;;;;;;; 836 ; task number 3 837 ;; Task 3 - TBD 028E 838 t3header: 028E C9 4A 73 4C 839 .byte 0xc9, 0x4a, 0x73, 0x4c ; cookie 0292 01 840 .byte 0x01 ; version 0293 04 841 .byte 0x04 ; requested timeslices 0294 98 02 842 .word t3name ; name 0296 A0 02 843 .word t3process ; process function 844 0298 845 t3name: 0298 06 846 .byte 6 ; strlen 0299 54 61 73 6B 20 33 847 .asciz "Task 3" ; name 00 848 02A0 849 t3process: 02A0 21 00 84 850 ld hl, #(colram) ; base of color ram 02A3 3E 01 851 ld a, #0x01 ; clear the screen to 0x00 02A5 06 04 852 ld b, #0x04 ; 256*4 = 1k 02A7 CD 5A 01 853 call memsetN 854 02AA 21 00 80 855 ld hl, #(vidram) ; base of video ram 02AD 3E 78 856 ld a, #0x78 ; 'X' 02AF 06 04 857 ld b, #0x04 ; 256*4 = 1k 02B1 CD 5A 01 858 call memsetN 859 02B4 21 00 80 860 ld hl, #(vidram) ; base of video ram 02B7 3E 79 861 ld a, #0x79 ; 'Y' 02B9 06 04 862 ld b, #0x04 ; 256*4 = 1k 02BB CD 5A 01 863 call memsetN 864 02BE 21 00 80 865 ld hl, #(vidram) ; base of video ram 02C1 3E 7A 866 ld a, #0x7a ; 'Z' 02C3 06 04 867 ld b, #0x04 ; 256*4 = 1k 02C5 CD 5A 01 868 call memsetN 869 02C8 C3 A0 02 870 jp t3process 02CB 76 871 halt ASxxxx Assembler V01.50 (Zilog Z80 / Hitachi HD64180), page 1. alpaca Symbol Table 1 .doneTask 007B R 1 .isr 0068 R 1 .nmi 0066 R 1 .reset00 0000 R 1 .reset08 0008 R 1 .reset10 0010 R 1 .reset18 0018 R 1 .reset20 0020 R 1 .reset28 0028 R 1 .reset30 0030 R 1 .reset38 0038 R 1 .skipTask 007B R 1 .sl2 0196 R 1 .slp 017E R 1 .start 0085 R CprtC = 0014 FF_Border = 0001 FF_NClose = 0002 FF_NRaise = 0004 F_Dirty = 0001 F_Focus = 0002 F_Frame = 0002 F_Noframe = 0001 LlamaC = 0010 PNEcornS = 0001 PNWcornS = 0001 PSEcornS = 008B PSWcornS = 008A PcloseCS = 0001 PcloseCU = 001E PcloseS = 0080 PcursorC = 0009 PcursorS = 0001 PfE_E = 0088 PfE_N = 0087 PfE_S = 0089 PfN_E = 0082 PfN_N = 0020 PfN_W = 0081 PfS_E = 0090 PfS_S = 008F PfS_W = 008E PfW_N = 0084 PfW_S = 0086 PfW_W = 0085 PfrmCSel = 0001 PfrmCUns = 001E PfrmTSel = 0009 PfrmTUns = 0001 PraiseCS = 0001 PraiseCU = 000C PraiseS = 0083 PwBGS = 007F PwC = 0001 PwHsS = 00A0 PwVsS = 00A1 PwbLsS = 0096 PwbLuS = 0094 PwbRsS = 0097 PwbRuS = 0095 PwcsS = 0099 PwcuS = 0098 PwpC = 0010 PwpS = 00A2 PwpfS = 009F PwpoS = 009E PwrsS = 009B PwruS = 009A PwsbS = 009D PwsnS = 009C W_Check = 0005 W_DInt = 0008 W_DText = 0007 W_End = 0000 W_Frame = 0001 W_HSlider = 0009 W_HSpin = 000B W_MButton = 0002 W_Radio = 0004 W_SButton = 0003 W_SText = 0006 W_VSlider = 000A W_VSpin = 000C button1 = 0080 1 cls 0164 R coin1 = 0010 coin2 = 0020 coin3 = 0040 coincount = 9044 collutbank = 9046 colram = 8400 dsw0 = 9040 1 execkill 01C9 R 1 execstart 01B3 R flipscreen = 9043 1 foo 00E4 R freetime = 00FE in0 = 90C0 in1 = 9080 irqen = 9040 killslot = 00FF 1 memset256 0155 R 1 memsetN 015A R msgbase = 94A0 msgmax = 94DF nsprites = 0006 openslot = 00FF 1 over 0111 R p1_down = 0002 p1_left = 0004 p1_right = 0008 p1_up = 0001 p2_down = 0002 p2_left = 0004 p2_right = 0008 p2_up = 0001 palbank = 9042 ram = 8800 semabase = 94E0 1 semalock 018A R semamax = 94EF 1 semarel 01A1 R service = 0010 1 sleep 0175 R sounden = 9041 speclen = 00FF specreg = 9000 spritebank = 9047 spritebase = 8FF2 spritecoords = 9022 sprtbase = 8FF2 sprtlen = 0010 stack = 8FF0 stack0 = 8FF0 stack1 = 8F30 stack2 = 8E70 stack3 = 8DB0 stackbottom = 8CF0 stacksize = 00C0 start1 = 0020 start2 = 0040 t0ctrl = 880C 1 t0header 01E8 R 1 t0name 01F2 R 1 t0p2 0204 R 1 t0process 01FA R t0slot = 8808 t0sp = 8800 t1ctrl = 880D 1 t1header 0226 R 1 t1name 0230 R 1 t1process 0238 R t1slot = 8809 t1sp = 8802 t2ctrl = 880E 1 t2header 0250 R 1 t2name 025A R 1 t2process 0262 R t2slot = 880A t2sp = 8804 t3ctrl = 880F 1 t3header 028E R 1 t3name 0298 R 1 t3process 02A0 R t3slot = 880B t3sp = 8806 taskctrl = 880C taskflag = 8810 1 tasklist 01DE R taskon = 0007 taskslot = 8808 taskstack = 8800 timer = 8811 v1_freq = 9011 v1_vol = 9015 v1_wave = 9005 v2_freq = 9016 v2_vol = 901A v2_wave = 900A v3_freq = 901B v3_vol = 901F v3_wave = 900F vidram = 8000 watchdog = 9070 ASxxxx Assembler V01.50 (Zilog Z80 / Hitachi HD64180), page 2. alpaca Area Table 0 _CODE size 0 flags 0 1 .CODE size 2CC flags C