home *** CD-ROM | disk | FTP | other *** search
/ ticalc.org / ticalc_org_rev_b.iso / archives / 86 / asm / source / orzed86.asm < prev    next >
Encoding:
Assembly Source File  |  2001-07-01  |  18.3 KB  |  566 lines

  1. ;OrzEd-IC now uses the consolidated ACZ includes available with AsmStudio 3.1 or from the ACZ
  2. ; homepage at http://acz.calc.org/
  3. #include "ram86.h"
  4. #include "rom86.h"
  5. #include "asm86.h"
  6.  
  7. #define lTable1 progEnd
  8. #define lTable2 progEnd + $20
  9. #define lTable3 progEnd + $40
  10. #define dataEnd progEnd + $60
  11.  
  12. curLevelChar        =    $E748
  13. curLevel            =    $E749
  14. saveStack           =    $E74B
  15. dataStorage         =    $E74D
  16.  
  17. .org _asm_exec_ram
  18.  nop                     ;Mark program as AShell 1.1 compatable.
  19.  jp AsmStart             ;Jump to program init routine.
  20.  .dw 0                   ;Table version 0.
  21.  .dw strDesc             ;Pointer to description string.
  22.  
  23. mDown:
  24.  ld a, 7                 ;7 is the lowest row.
  25.  cp ixh
  26.  jr z, main              ;If we're already there, return.
  27.  call flipCursor         ;Remove old cursor.
  28.  inc ixh                 ;Move down.
  29.  call flipCursor         ;Put new cursor.
  30.  jr main
  31.  
  32. mUp:
  33.  xor a                   ;0 is the highest row.
  34.  cp ixh
  35.  jr z, main              ;If we're already there, return.
  36.  call flipCursor         ;Remove old cursor.
  37.  dec ixh                 ;Move up.
  38.  call flipCursor         ;Put new cursor.
  39.  jr main
  40.  
  41. mLeft:
  42.  xor a                   ;0 is the leftmost column.
  43.  cp ixl
  44.  jr z, main              ;If we're already there, return.
  45.  call flipCursor         ;Remove old cursor.
  46.  dec ixl                 ;Move left.
  47.  call flipCursor         ;Put new cursor.
  48.  jr main
  49.  
  50. goThree:
  51.  ld a, '3'               ;For display.
  52.  ld de, lTable3          ;Get the address of the third level.
  53.  jr goNum
  54. goTwo:
  55.  ld a, '2'               ;For display.
  56.  ld de, lTable2          ;Get the address of the second level.
  57.  jr goNum
  58. goOne:
  59.  ld a, '1'               ;For display.
  60.  ld de, lTable1          ;Get the address of the first level.
  61. goNum:
  62.  ld (curLevelChar), a    ;This is read to get level display character.
  63.  ld (curLevel), de       ;Write it to the current level address.
  64.  jr preMain              ;Redisplay screen before continuing.
  65.  
  66. AsmStart:
  67.  call _runindicoff
  68. nL_Restart:
  69.  call _clrScrn
  70.  ld ix, 0                ;ix is our r, c counter.
  71.  ld a, '1'               ;This is just the easiest way of keeping track of
  72.  ld (curLevelChar), a    ; the current level number.
  73.  ld hl, lTable1
  74.  ld (curLevel), hl       ;We display Level One first.
  75.  ld de, lTable1 + 1
  76.  ld bc, $5F
  77.  ld (hl), 0              ;Initialize first byte to zero.
  78.  ldir
  79. preMain:
  80.  call reDispScreen       ;Redraws the entire display.
  81. main:
  82.  call _get_key
  83.  dec a                   ;Move cursor down.
  84.  jr z, mDown
  85.  dec a                   ;Move cursor left.
  86.  jr z, mLeft
  87.  dec a                   ;Move cursor right.
  88.  jr z, mRight
  89.  dec a                   ;Move cursor up.
  90.  jr z, mUp
  91.  cp K_SECOND - 4         ;If 2nd was pressed, draw a normal block.
  92.  jr z, setBlockPrep1
  93.  cp K_EXIT - 4           ;If exit was pressed, draw a tough block.
  94.  jr z, setBlockPrep1
  95.  cp K_MORE - 4           ;If more was pressed, draw a solid block.
  96.  jr z, setBlockPrep1
  97.  cp K_ALPHA - 4          ;If alpha was pressed, clear a block.
  98.  jr z, setBlockPrep2
  99.  cp K_1 - 4              ;Load the first level.
  100.  jr z, goOne
  101.  cp K_2 - 4              ;Load the second level.
  102.  jr z, goTwo
  103.  cp K_3 - 4              ;Load the third level.
  104.  jr z, goThree
  105.  cp K_F1 - 4             ;Clear all levels and reset name.
  106.  jr z, newLevel
  107.  cp K_F2 - 4             ;Load a level set.
  108.  jp z, loadLevel
  109.  cp K_F3 - 4             ;Save the current level set.
  110.  jp z, saveLevel
  111.  cp K_F4 - 4             ;Test the cirrent level set.
  112.  jp z, testLevel
  113.  cp K_F5 - 4             ;If F5 was pressed, just exit.
  114.  jr nz, main
  115. doExit:
  116.  ld a, $E1               ;Used to clear shiftflags 3-6.
  117.  and (iy+shiftflags)
  118.  ld (iy + shiftflags), a
  119.  jp _clrScrn             ;Clear screen before returning to shell.
  120.  
  121. newLevel:
  122.  ld hl, strUntitled      ;Reset the name back to 'Untitled'
  123.  ld de, strName + 2
  124.  ld bc, $0008
  125.  ldir
  126.  ex de, hl
  127.  inc hl
  128.  ld (hl), $08            ;Reset the name length, too.
  129.  jr nL_Restart           ;See above, right after AsmStart.
  130.  
  131. mRight:
  132.  ld a, $0F               ;F is the rightmost column.
  133.  cp ixl
  134.  jr z, main              ;If we're already there, return.
  135.  call flipCursor         ;Remove old cursor.
  136.  inc ixl                 ;Move right.
  137.  call flipCursor         ;Put new cursor.
  138.  jr main
  139.  
  140. setBlockPrep1:
  141.  sub $05                 ;$32, $33, $34 -> $2D, $2E, $2F
  142. setBlockPrep2:
  143.  sub $2C                 ;$2C, $2D, $2E, $2F -> $00, $01, $02, $03
  144. setBlock:
  145.  push ix                 ;Copy the r, c code into hl.
  146.  pop hl
  147.  push af                 ;Save block type.
  148.  inc h                   ;This prevents the djnz from looping if h = 0.
  149.  ld a, -5                ;Trust me, this makes the code simpler.  <-----------------------+
  150.  ld c, $04               ;Number of bytes in a row.                                       |
  151.  ld b, h                 ;Loop count = # of rows.                                         |
  152. sB_Row:                  ;                                                                |
  153.  add a, c                ;See?  This gets executed once even if h=0, so subtract 4 from --+
  154.  djnz sB_Row             ;If we still have rows to go, loop.                              |
  155.  ld c, a                 ;We'll need a for the 'sub l' coming up.                         |
  156.  ld a, l                 ;We need to subtract _from_ l.                                   |
  157.  ld l, $04               ;Four blocks in a byte.                                          |
  158. sB_Col:                  ;                                                                |
  159.  inc c                   ;And this gets executed once if l=0, so subtract one from -------+
  160.  sub l
  161.  jr nc, sB_Col           ;If we still have bytes to go, loop.
  162.  ld b, 0                 ;Tricky way to ld bc, c.
  163.  ld hl, (curLevel)       ;Get the level offset.
  164.  add hl, bc              ;hl = current byte.
  165.  pop bc                  ;Restore block type.
  166.  push bc                 ;And save it again.
  167.  inc a                   ;If it's the 4th block, 
  168.  jr z, sB_10             ; operate on bits 1 and 0.
  169.  inc a                   ;If it's the 3rd block, 
  170.  jr z, sB_32             ; operate on bits 3 and 2.
  171.  inc a                   ;If it's the 2nd block, 
  172.  jr z, sB_54             ; operate on bits 5 and 4.
  173.  ld a, %00111111         ;Clear bits 7 and 6 (it's the first block).
  174.  and (hl)
  175.  rrc b                   ;Prepare b.
  176.  rrc b
  177.  jr sB_Done              ;To Be Continued...
  178. sB_54:
  179.  ld a, %11001111         ;Clear bits 5 and 4.
  180.  and (hl)
  181.  rrc b                   ;Prepare b.
  182.  rrc b
  183.  rrc b
  184.  rrc b
  185.  jr sB_Done
  186. sB_32:
  187.  ld a, %11110011         ;Clear bits 3 and 2.
  188.  and (hl)
  189.  rlc b                   ;Prepare b.
  190.  rlc b
  191.  jr sB_Done
  192. sB_10:
  193.  ld a, %11111100         ;Clear bits 1 and 0.
  194.  and (hl)
  195. sB_Done:
  196.  or b                    ;Plug the new type into a
  197.  ld (hl), a              ;Put the byte back.
  198.  pop af                  ;Restore block type.
  199.  call drawBlock          ;redraw the block.
  200.  ld hl, main
  201.  push hl                 ;For flipCursor fallthrough.
  202.  
  203. flipCursor:
  204.  call getOffset          ;Get screen offset of block ixh, ixl.
  205.  ld de, $0010            ;One full line on the screen.
  206.  add hl, de              ;Skip the first line.
  207.  ld a, $18               ;$18 = %00011000, the cursor half.
  208.  xor (hl)                ;Flip bits 3 & 4 in the screen byte.
  209.  ld (hl), a              ;Plug it back in.
  210.  add hl, de
  211.  ld a, $18
  212.  xor (hl)
  213.  ld (hl), a
  214.  ret
  215.  
  216. reDispScreen:
  217.  push ix
  218.  ld ix, 0                ;Start at the first brick.
  219.  ld de, (curLevel)       ;Load the memory offset of the current level.
  220.  ld b, $20               ;We need to process 32 bytes.
  221. rDS_byte:
  222.  push bc                 ;Save the byte count.
  223.  ld b, 4                 ;Four blocks per byte.
  224.  ld a, (de)              ;Get the current byte.
  225.  ld c, a
  226. rDS_block:
  227.  rlc c                   ;Bits 7 and 6 to 1 and 0.
  228.  rlc c
  229.  ld a, c
  230.  and $03                 ;Ignore bits 2-7.
  231.  push de                 ;Can't lose this!
  232.  call drawBlock          ;Draw whatever type of block bits 1 and 0 represent.
  233.  pop de                  ;Restore data pointer.
  234.  inc ixl                 ;Increment the column.
  235.  ld a, $10               ;If we hit the end of a line, 
  236.  cp ixl
  237.  jr nz, rDS_goBlock
  238.  ld ixl, 0
  239.  inc ixh                 ;Increment the row.
  240. rDS_goBlock:
  241.  djnz rDS_block          ;If we're not done with this byte, loop.
  242.  inc de                  ;Next byte!
  243.  pop bc                  ;Restore the byte count.
  244.  djnz rDS_byte           ;If we're not done with the level, loop.
  245.  ld hl, $0004            ;Just below the level display.
  246.  ld (_curRow), hl
  247.  ld a, (curLevelChar)    ;Get level number (stored as a char)
  248.  call _putc
  249.  ld hl, strName          ;Current name of the level set.
  250.  call _puts
  251.  ld hl, $3906            ;Set up menu at bottom of screen.
  252.  ld (_penCol), hl
  253.  ld hl, strNew
  254.  call _vputs             ;Display in small font.
  255.  ld hl, $391F
  256.  ld (_penCol), hl
  257.  ld hl, strLoad
  258.  call _vputs
  259.  ld hl, $3938
  260.  ld (_penCol), hl
  261.  ld hl, strSave
  262.  call _vputs
  263.  ld hl, $3951
  264.  ld (_penCol), hl
  265.  ld hl, strTest
  266.  call _vputs
  267.  ld hl, $396C
  268.  ld (_penCol), hl
  269.  ld hl, strExit
  270.  call _vputs
  271.  pop ix                  ;Restore cursor position.
  272.  jp flipCursor
  273.  
  274. testLevel:
  275.  push ix
  276.  ld (saveStack), sp      ;_exec_assembly isn't stack-friendly?
  277.  ld hl, dataArea         ;Store OrzEd86's data far enough above _asm_exec_ram
  278.  ld de, dataStorage      ; that it won't be overwritten by Orzunoid's code.
  279.  ld bc, dataEnd - dataArea
  280.  ldir
  281.  ld hl, lTable1 - 2      ;Current levels.
  282.  ld de, $C012            ;Level storage in RAM.
  283.  ld bc, $0062            ;# of bytes to copy (3 levels * $20 + 2)
  284.  ldir
  285.  ld hl, strOrzunoid - 1  ;Orzunoid VAT entry in _OP1 format.
  286.  rst 20h
  287.  rst 10h
  288.  jr c, tL_NotFound       ;Orzunoid isn't on the calc!
  289.  call _exec_assembly     ;Execute Orzunoid.
  290.  ld hl, dataStorage      ;Retrieve the entire data area of OrzEd86
  291.  ld de, dataArea
  292.  ld bc, dataEnd - dataArea
  293.  ldir
  294.  ld sp, (saveStack)      ;_exec_assembly isn't stack-friendly?
  295.  pop ix
  296.  jp preMain
  297. tL_NotFound:
  298.  pop ix
  299.  ld de, strNotFound
  300.  jp dispMsg
  301.  
  302. saveLevel:
  303.  call nameLevel          ;Get name to save as.
  304.  ld hl, strName          ;Copy name w/o leading length into _OP1.
  305.  rst 20h
  306.  ld a, (intNameLen)      ;Retrieve name length.
  307.  ld (_OP1 + 1), a        ;Add leading length byte (z80 is byte-reversed).
  308.  rst 10h                 ;Check to see if it already exists.
  309.  jr nc, sL_Exists        ;If it does, generate an error.
  310.  ld hl, $70              ;$60 data + $0E code + 2 asm header = $70.
  311.  call _createprog        ;Allocate program memory and create VAT entry.
  312.  ld a, b                 ;Move bde -> ahl.
  313.  ex de, hl
  314.  call _load_ram_ahl      ;Set RAM page and convert hl to ASIC.
  315.  ld de, rawProg          ;Copy program contents from _asm_exec_ram to
  316.  ld bc, $70              ; the memory just allocated by _CREATEPROG.
  317.  ex de, hl
  318.  inc de                  ;Skip the size bytes.
  319.  inc de
  320.  ldir
  321.  ld de, strGoodSave
  322.  jr dispMsg
  323. sL_Exists:
  324.  pop hl                  ;Restore stack.
  325.  pop hl
  326.  ld de, strExists        ;Display error text.
  327.  jr dispMsg
  328.  
  329. loadLevel:
  330.  call nameLevel          ;Get name to load from.
  331.  ld hl, strName          ;Put level set title into _OP1
  332.  rst 20h
  333.  ld a, (intNameLen)
  334.  ld (_OP1 + 1), a
  335.  rst 10h                 ;Gets var info if it exists.
  336.  jr c, lL_NoProg         ;If it doesn't, generate an error.
  337.  and $1F                 ;Mask out flags
  338.  cp $12                  ;Is it a program?
  339.  jr nz, lL_NotValid      ;If not, generate an error.
  340.  ld a, b                 ;move bde -> ahl
  341.  ex de, hl
  342.  call _load_ram_ahl      ;Load appropriate RAM page.
  343.  push hl                 ;We'll need this in a minute.
  344.  call $0033              ;ld hl, (hl)
  345.  ld de, $0070            ;Check to make sure the file is the proper length.
  346.  call _cphlde
  347.  pop hl
  348.  jr nz, lL_NotValid      ;Oops!  It's not the right length...
  349.  ld de, $0010            ;Find the marker bytes.
  350.  add hl, de
  351.  push hl                 ;We _still_ need this.
  352.  call $0033              ;ld hl, (hl)
  353.  ld de, $4FD0            ;$4FD0 = Orzunoid Level signature.
  354.  call _cphlde
  355.  pop hl
  356.  jr nz, lL_NotValid      ;If the signature doesn't exist, generate an error.
  357.  inc hl                  ;Otherwise, load the levels!
  358.  inc hl
  359.  ld de, lTable1
  360.  ld bc, $60
  361.  ldir
  362.  jp preMain
  363. lL_NoProg:
  364.  ld de, strNoProg
  365.  jr dispMsg
  366. lL_NotValid:
  367.  ld de, strNotValid
  368.  
  369. dispMsg:
  370.  ld hl, $0005            ;Display below name.
  371.  ld (_curRow), hl
  372.  ex de, hl               ;The offset of the text to display must be in de.
  373.  call _puts              ;Messages must be null-terminated.
  374.  call _pause             ;Hang around until they press a key.
  375.  ld hl, $FE80            ;$FE80 = video address of the sixth line.
  376.  ld de, $FE81
  377.  ld bc, $017F
  378.  ld (hl), 0
  379.  ldir
  380.  jp preMain              ;Just as a rule of thumb, rediplay the level.
  381.  
  382. nameLevel:
  383.  ld a, (iy + shiftflags) ;Get shiftflags.
  384.  or $50                  ;Set shiftAlpha and shiftALock.
  385.  ld (iy + shiftflags), a ;Save shiftslags.
  386.  call _cursorOn          ;We want the cursor displayed during text entry.
  387.  ld de, strName + 2      ;Where the characters will go.
  388.  ld a, (intNameLen)      ;But first, we need to add the current offset.
  389.  ld l, a
  390.  ld h, 0
  391.  add hl, de
  392.  push hl                 ;I think _getkey screws with de and hl...
  393. nL_Loop:                 ;Used to update the display.
  394.  ld hl, $0304            ;First letter of the name display.
  395.  ld (_curRow), hl
  396.  ld a, $20
  397.  ld b, 9
  398. nL_OverWrite:
  399.  call _putc
  400.  djnz nL_OverWrite
  401.  ld hl, $0304            ;First letter of the name display.
  402.  ld (_curRow), hl
  403.  ld hl, strName + 2      ;(Re)display the current name.
  404.  call _puts
  405. nL_GetKey:
  406.  call _getkey            ;Use _getkey so we get Alpha handled for us.
  407.  cp kEnter               ;If it's enter, try to use this filename.
  408.  jr z, nL_Next
  409.  cp kDel                 ;If it's delete, remove the last charater typed.
  410.  jr z, nL_Back
  411.  add a, $14              ;L0 (font code) - k0 (key code) = 14 hex.
  412.  cp L0                   ;If it's less than 0, it's a bad character.
  413.  jr c, nL_GetKey
  414.  cp L9 + 1               ;If it's not more than 9, it's a numeral.
  415.  jr c, nL_PrePutKey
  416.  add a, $5               ;LcapA - kCapA = $14 + $5
  417.  cp LcapA                ;If it's less that A, it's a bad character.
  418.  jr c, nL_GetKey
  419.  cp LcapZ + 1            ;If it's not more than Z, it's a capital letter.
  420.  jr c, nL_PutKey
  421.  add a, $6               ;Lz - kz = $14 + $5 + $6
  422.  cp Lz + 1               ;If it's not more than z, it's a lower-case letter.
  423.  jr nc, nL_GetKey        ;Otherwise, it's a bad character.
  424.  jr nL_PutKey
  425. nL_PrePutKey:            ;Need to make sure this isn't the first character.
  426.  ld c, a                 ;We'll need a.
  427.  ld a, (intNameLen)      ;Grab the name length.
  428.  ld b, 0                 ;The first character cannot be a number.
  429.  cp b
  430.  jr z, nL_GetKey         ;Numbers can't be the first character of a filename.
  431.  ld a, c
  432. nL_PutKey:
  433.  ld c, a                 ;We'll need a.
  434.  ld a, (intNameLen)      ;Grab the name length.
  435.  ld b, 8                 ;Filenames can't exceed 8 characters.
  436.  cp b
  437.  jr z, nL_GetKey
  438.  inc a                   ;Increase the character count.
  439.  ld (intNameLen), a      ;Store the name length.
  440.  pop hl                  ;Retrieve memory counter.
  441.  ld (hl), c              ;Load the character into memory.
  442.  inc hl                  ;Increment the memory counter.
  443.  push hl                 ;Store memory counter.
  444.  jr nL_Loop              ;Redisplay.
  445. nL_Back:
  446.  ld a, (intNameLen)      ;Grab the name length.
  447.  ld b, 0                 ;Can't backspace if it's there aren't any characters!
  448.  cp b
  449.  jr z, nL_GetKey
  450.  dec a                   ;Decrease the character count.
  451.  ld (intNameLen), a      ;Store the name length.
  452.  pop hl
  453.  dec hl                  ;Decrement the memory counter.
  454.  ld (hl), b              ;Zero out the last character.
  455.  push hl
  456.  jr nL_Loop              ;Redisplay
  457. nL_Next:
  458.  ld a, (intNameLen)      ;Grab the name length.
  459.  ld b, 0                 ;Can't use a zero-length name.
  460.  cp b
  461.  jr z, nL_GetKey
  462.  call _cursorOff         ;Get rid of cursor.
  463.  pop hl
  464.  ld (intNameLen), a      ;Store the name length.
  465.  ret
  466.  
  467. drawBlock:
  468.  call getOffset          ;Change hl into screen offset.
  469.  ld de, $0010            ;One full line on the screen.
  470.  or a                    ;Is a 0?
  471.  jr z, drawClear         ;If so, clear the block.
  472.  ld (hl), %11111111      ;All others start with $FF
  473.  add hl, de
  474.  dec a                   ;Was a 1?
  475.  jr z, drawNorm          ;If so, draw a normal block.
  476.  dec a                   ;Was a 2?
  477.  jr z, drawTough         ;If so, draw a tough block.
  478.  ld a, %11111111         ;Else, it's solid.
  479.  ld (hl), a
  480.  add hl, de              ;Move down one line.
  481.  ld (hl), a
  482.  add hl, de
  483.  ld (hl), a
  484.  ret
  485. drawTough:
  486.  ld (hl), %11000011      ;Second line of sprite.
  487.  add hl, de
  488.  ld (hl), %11000011      ;Third line of sprite.
  489.  add hl, de
  490.  ld (hl), %11111111      ;Last line of sprite.
  491.  ret
  492. drawNorm:
  493.  ld (hl), %10000001
  494.  add hl, de
  495.  ld (hl), %10000001
  496.  add hl, de
  497.  ld (hl), %11111111
  498.  ret
  499. drawClear:
  500.  ld (hl), a              ;a is already 0.
  501.  add hl, de
  502.  ld (hl), a
  503.  add hl, de
  504.  ld (hl), a
  505.  add hl, de
  506.  ld (hl), a
  507.  ret
  508.  
  509. getOffset:
  510.  push ix                 ;Copy ix into de.
  511.  pop de
  512.  ld l, d                 ;Change ixh into a 16-bit value in hl.
  513.  ld h, 0
  514.  ld d, $FC               ;Load d with the upper byte of the screen offset.
  515.  add hl, hl              ;hl = Row * 64
  516.  add hl, hl
  517.  add hl, hl
  518.  add hl, hl
  519.  add hl, hl
  520.  add hl, hl
  521.  add hl, de              ;hl = Screen Offset + Row * 64 + Column
  522.  ret
  523.  
  524. dataArea:
  525. strDesc:
  526.  .db "Orzunoid Level Editor v.8b", 0
  527. strExists:
  528.  .db "File already exists!", 0
  529. strGoodSave:
  530.  .db "Level set saved.", 0
  531. strName:
  532.  .db ": Untitled", 0
  533. intNameLen:
  534.  .db 8
  535. strNoProg:
  536.  .db "No such file exists!", 0
  537. strNotFound:
  538.  .db "Orzunoid not found!", 0
  539. strNotValid:
  540.  .db "Not a level set!", 0
  541. strOrzunoid:
  542.  .db 8, "Orzunoid"
  543. strUntitled:
  544.  .db "Untitled"
  545. strNew:
  546.  .db "New", 0
  547. strLoad:
  548.  .db "Load", 0
  549. strSave:
  550.  .db "Save", 0
  551. strTest:
  552.  .db "Test", 0
  553. strExit:
  554.  .db "Exit", 0
  555. rawProg:
  556.  .db $8E, $28            ;Assembly program ID bytes (TI)
  557.  ld de, $C012            ;Level storage in RAM.
  558.  ld hl, $D754            ;_asm_exec_ram + $0C
  559.  ld bc, $0062            ;# of bytes to copy (3 levels * $20 + 2)
  560.  ldir
  561.  ret
  562.  .db $D0, $4F            ;These tell Orzunoid that this is a valid level set.
  563.  
  564. progEnd:
  565. .end
  566.