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