diff options
author | B. Watson <yalhcru@gmail.com> | 2016-09-13 04:49:13 -0400 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2016-09-13 04:49:13 -0400 |
commit | 15ac1a8086971cb500bd09dd97bf62e111c2be90 (patch) | |
tree | f151be86d513450a2b33aaa169e21c0b7339b85e | |
parent | 9bcb6af0db2a32a4158f7e7c91e91634f562a3da (diff) | |
download | jumpmanjr-15ac1a8086971cb500bd09dd97bf62e111c2be90.tar.gz |
pokey emulation, plus more labels
-rw-r--r-- | jumpmanjr.dasm | 188 | ||||
-rw-r--r-- | jumpmanjr.info | 46 | ||||
-rw-r--r-- | leveldesc.info | 28 | ||||
-rw-r--r-- | main.info | 18 | ||||
-rw-r--r-- | mklevelinfo.pl | 2 | ||||
-rw-r--r-- | pokeytest/Makefile | 15 | ||||
-rw-r--r-- | pokeytest/playsdl2.c | 153 | ||||
-rw-r--r-- | pokeytest/playsnd.c | 114 | ||||
-rw-r--r-- | pokeytest/pokey.c | 764 | ||||
-rw-r--r-- | pokeytest/pokey.h | 77 | ||||
-rw-r--r-- | pokeytest/pokey11.txt | 277 | ||||
-rw-r--r-- | pokeytest/pokey11_readme.txt | 119 | ||||
-rw-r--r-- | pokeytest/readme.txt | 25 | ||||
-rw-r--r-- | porting_ideas.txt | 32 |
14 files changed, 1725 insertions, 133 deletions
diff --git a/jumpmanjr.dasm b/jumpmanjr.dasm index 433cb6f..881d65d 100644 --- a/jumpmanjr.dasm +++ b/jumpmanjr.dasm @@ -1,5 +1,5 @@ ; da65 V2.15 - Git 104f898 -; Created: 2016-09-07 15:56:49 +; Created: 2016-09-09 04:10:51 ; Input file: jumpmanjr.rom ; Page: 1 @@ -32,6 +32,8 @@ sa_tmp_2 := $00C8 ; used by calc_screen_addr dm_delta_x := $00C9 ; see draw_map and level_maps.txt dm_delta_y := $00CA ; see draw_map and level_maps.txt zp_temp1 := $00CB ; used for (zp,y) addressing, also for checking console keys in vblank_imm_isr +tmp_sprite := $00CD ; ZP pointer to player/missile data (e.g. jumpman's 10-byte animation frames) +tmp_sprite_height:= $00CF ; length of data pointed to by tmp_sprite num_in := $00D0 ; print_number input. 3-byte number (LSB first as usual) to be printed num_out := $00D3 ; area of (screen) memory where print_number stores its output num_color := $00D5 ; print_number adds this to numeric screencode output. normally 0, set to $80 on the end-of-game screen. @@ -59,7 +61,8 @@ jiffy_timer_1 := $061A ; gets incremented every frame jiffy_timer_2 := $061B ; gets incremented every frame odd_frame_flag := $061C ; a 1-bit frame counter (toggles every frame). possibly unused. speed_jiffy_timer:= $061E ; counts 0..initial_speed -falling_flag := $0621 ; 1 = falling, reset to 0 when jumpman hits the ground +start_falling_flag:= $0621 ; reset to 0 every frame, set to 1 when starting to fall +falling_flag := $0623 ; 0 = ok, 1 = falling, 2 = on ground. current_speed := $0624 ; can be modified, e.g. set to $08 when being electrocuted initial_speed := $0625 ; current user's chosen speed, set at game start bonus_jiffy_timer:= $0626 ; gets incremented every frame when playing a level, bonus-=100 when this wraps around to 0 @@ -80,8 +83,14 @@ snd_slot_audc := $0647 snd_slot_curpos := $064E ; address we've got to so far, playing this sfx snd_priority_tmp:= $0661 ; ?? num_tmp := $0665 ; temp used by print_number +player_enabled := $0668 ; 1 = draw this player, 0 = no. actually $0669 thru $066e +player_height := $0677 ; actually $0677 thru $067b +player_new_x := $067C ; HPOSxx, 1-indexed, $067d thru $0681 are p5, p3..p0 player_x_pos := $067E ; stored in HPOSP0 player_y_pos := $0683 ; $C6 is the bottom of the level (where you end up when you die) +player_new_y := $0686 ; $0687 thru $069b +player_x := $068B ; HPOSxx, $068c thru $06c0 +player_y := $0695 ; vertical positions, actually $0696 thru $069a bullet_x_pos := $069B ; 4 bytes, meaning we can never have >4 bullets on screen at once (makes sense, GTIA only has 4 missiles) bullet_y_pos_minus_one:= $069E bullet_y_pos := $069F ; another 4 bytes @@ -157,7 +166,7 @@ work_level_init := $07A2 ; called at start of level, $06E work_level_sub6 := $07A4 ; always $9740 aka game_main_loop work_level_sub_eol:= $07A6 ; called at end of level (all bombs picked up). $06E6 for all but level08 work_level_offs_40:= $07A8 ; all zeroes -work_level_colpf3:= $07AE ; color (not sure what gets drawn in this color yet) +work_level_colpf3:= $07AE ; color for missiles (aka 5th player) work_level_colpf0:= $07AF ; color for girders and up-ropes work_level_colpf1:= $07B0 ; color for ladders and down-ropes work_level_colpf2:= $07B1 ; color for bombs @@ -190,7 +199,7 @@ cur_level_init := $07E2 ; called at start of level, $06E cur_level_sub6 := $07E4 ; always $9740 aka game_main_loop cur_level_sub_eol:= $07E6 ; called at end of level (all bombs picked up). $06E6 for all but level08 cur_level_offs_40:= $07E8 ; all zeroes -cur_level_colpf3:= $07EE ; color (not sure what gets drawn in this color yet) +cur_level_colpf3:= $07EE ; color for missiles (aka 5th player) cur_level_colpf0:= $07EF ; color for girders and up-ropes cur_level_colpf1:= $07F0 ; color for ladders and down-ropes cur_level_colpf2:= $07F1 ; color for bombs @@ -816,12 +825,12 @@ next_plr: dec zp_temp1+1 ; 82F3 C6 CC .. dex ; 82F5 CA . beq position_done ; 82F6 F0 F0 .. - lda $0668,x ; 82F8 BD 68 06 .h. + lda player_enabled,x ; 82F8 BD 68 06 .h. beq next_plr ; 82FB F0 F6 .. - lda $067C,x ; 82FD BD 7C 06 .|. - cmp $068B,x ; 8300 DD 8B 06 ... + lda player_new_x,x ; 82FD BD 7C 06 .|. + cmp player_x,x ; 8300 DD 8B 06 ... beq position_pm_vert ; 8303 F0 1D .. - sta $068B,x ; 8305 9D 8B 06 ... + sta player_x,x ; 8305 9D 8B 06 ... sta HPOSP0_minus_two,x ; 8308 9D FE CF ... cpx #$01 ; 830B E0 01 .. bne position_pm_vert ; 830D D0 13 .. @@ -842,48 +851,51 @@ position_pm_vert: lda $0690,x ; 8322 BD 90 06 ... cmp $0681,x ; 8325 DD 81 06 ... bne skip_vert ; 8328 D0 0E .. - lda $0686,x ; 832A BD 86 06 ... - cmp $0695,x ; 832D DD 95 06 ... + lda player_new_y,x ; 832A BD 86 06 ... + cmp player_y,x ; 832D DD 95 06 ... beq next_plr ; 8330 F0 C1 .. - sta $0695,x ; 8332 9D 95 06 ... + sta player_y,x ; 8332 9D 95 06 ... lda $0690,x ; 8335 BD 90 06 ... skip_vert: sta zp_temp1 ; 8338 85 CB .. - lda $0677,x ; 833A BD 77 06 .w. - sta $CF ; 833D 85 CF .. + lda player_height,x ; 833A BD 77 06 .w. + sta tmp_sprite_height ; 833D 85 CF .. lda #$00 ; 833F A9 00 .. tay ; 8341 A8 . ; write zeroes to unused portion of this player/missile clear_pm: sta (zp_temp1),y ; 8342 91 CB .. iny ; 8344 C8 . - cpy $CF ; 8345 C4 CF .. + cpy tmp_sprite_height ; 8345 C4 CF .. bne clear_pm ; 8347 D0 F9 .. lda $0681,x ; 8349 BD 81 06 ... sta $0690,x ; 834C 9D 90 06 ... sta zp_temp1 ; 834F 85 CB .. lda $066D,x ; 8351 BD 6D 06 .m. - sta $CD ; 8354 85 CD .. + sta tmp_sprite ; 8354 85 CD .. lda $0672,x ; 8356 BD 72 06 .r. - sta $CE ; 8359 85 CE .. - ldy $0686,x ; 835B BC 86 06 ... + sta tmp_sprite+1 ; 8359 85 CE .. + ldy player_new_y,x ; 835B BC 86 06 ... clc ; 835E 18 . -L835F: dey ; 835F 88 . - beq L8370 ; 8360 F0 0E .. - lda $CF ; 8362 A5 CF .. - adc $CD ; 8364 65 CD e. - sta $CD ; 8366 85 CD .. - bcc L835F ; 8368 90 F5 .. - inc $CE ; 836A E6 CE .. +; adjust pointer if Y wraps around +adj_ptr:dey ; 835F 88 . + beq copy_pm_data ; 8360 F0 0E .. + lda tmp_sprite_height ; 8362 A5 CF .. + adc tmp_sprite ; 8364 65 CD e. + sta tmp_sprite ; 8366 85 CD .. + bcc adj_ptr ; 8368 90 F5 .. + inc tmp_sprite+1 ; 836A E6 CE .. clc ; 836C 18 . - jmp L835F ; 836D 4C 5F 83 L_. + jmp adj_ptr ; 836D 4C 5F 83 L_. ; ---------------------------------------------------------------------------- -L8370: lda ($CD),y ; 8370 B1 CD .. +; write to P/M memory +copy_pm_data: + lda (tmp_sprite),y ; 8370 B1 CD .. sta (zp_temp1),y ; 8372 91 CB .. iny ; 8374 C8 . - dec $CF ; 8375 C6 CF .. - bne L8370 ; 8377 D0 F7 .. + dec tmp_sprite_height ; 8375 C6 CF .. + bne copy_pm_data ; 8377 D0 F7 .. jmp next_plr ; 8379 4C F3 82 L.. ; ---------------------------------------------------------------------------- @@ -989,7 +1001,7 @@ no_wrap:inc jiffy_timer_1 ; 841F EE 1A 06 and #$01 ; 842B 29 01 ). sta odd_frame_flag ; 842D 8D 1C 06 ... lda #$00 ; 8430 A9 00 .. - sta falling_flag ; 8432 8D 21 06 .!. + sta start_falling_flag ; 8432 8D 21 06 .!. sta $0622 ; 8435 8D 22 06 .". sta $06FD ; 8438 8D FD 06 ... inc $061D ; 843B EE 1D 06 ... @@ -1002,7 +1014,7 @@ no_wrap:inc jiffy_timer_1 ; 841F EE 1A 06 bcc check_speed_timer ; 844E 90 1E .. lda #$00 ; 8450 A9 00 .. sta $061D ; 8452 8D 1D 06 ... - inc falling_flag ; 8455 EE 21 06 .!. + inc start_falling_flag ; 8455 EE 21 06 .!. inc $061F ; 8458 EE 1F 06 ... inc $0620 ; 845B EE 20 06 . . lda $061F ; 845E AD 1F 06 ... @@ -1234,7 +1246,7 @@ zero_filler_85f6: .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 85F6 00 00 00 00 00 00 00 00 ........ .byte $00,$00 ; 85FE 00 00 .. ; ---------------------------------------------------------------------------- -; convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out +; convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out. num_in is modified. print_number: ldx #$00 ; 8600 A2 00 .. ldy #$00 ; 8602 A0 00 .. @@ -1304,7 +1316,7 @@ print_score: ldx #$03 ; 8670 A2 03 .. ; number_of_users should be score-1 here. ps_loop:lda number_of_users,x ; 8672 BD FF 06 ... - sta $CF,x ; 8675 95 CF .. + sta tmp_sprite_height,x ; 8675 95 CF .. dex ; 8677 CA . bne ps_loop ; 8678 D0 F8 .. jsr print_number ; 867A 20 00 86 .. @@ -1319,7 +1331,7 @@ print_bonus: sta num_out+1 ; 8684 85 D4 .. ldx #$03 ; 8686 A2 03 .. pb_loop:lda work_level_points_per_bomb,x ; 8688 BD 90 07 ... - sta $CF,x ; 868B 95 CF .. + sta tmp_sprite_height,x ; 868B 95 CF .. dex ; 868D CA . bne pb_loop ; 868E D0 F8 .. jsr print_number ; 8690 20 00 86 .. @@ -1403,7 +1415,7 @@ prepare_level: lda #$00 ; 8731 A9 00 .. sta playing_level ; 8733 8D 27 06 .'. L8736: sta $0681,x ; 8736 9D 81 06 ... - sta $0668,x ; 8739 9D 68 06 .h. + sta player_enabled,x ; 8739 9D 68 06 .h. sta $069A,x ; 873C 9D 9A 06 ... jsr hide_player ; 873F 20 B8 8D .. dex ; 8742 CA . @@ -1673,9 +1685,9 @@ zero_filler_88f9: ; ---------------------------------------------------------------------------- ; called via vector in page 6 check_falling_2: - lda falling_flag ; 8900 AD 21 06 .!. + lda start_falling_flag ; 8900 AD 21 06 .!. beq L890F ; 8903 F0 0A .. - lda $0623 ; 8905 AD 23 06 .#. + lda falling_flag ; 8905 AD 23 06 .#. cmp #$01 ; 8908 C9 01 .. beq L8910 ; 890A F0 04 .. jmp L89F3 ; 890C 4C F3 89 L.. @@ -1712,7 +1724,7 @@ L8945: lda player_y_pos ; 8945 AD 83 06 sta AUDF1 ; 894E 8D 00 D2 ... sta AUDC1 ; 8951 8D 01 D2 ... sta $06EF ; 8954 8D EF 06 ... - inc $0623 ; 8957 EE 23 06 .#. + inc falling_flag ; 8957 EE 23 06 .#. jmp L89F3 ; 895A 4C F3 89 L.. ; ---------------------------------------------------------------------------- @@ -1788,7 +1800,7 @@ L89D1: clc ; 89D1 18 rts ; 89F2 60 ` ; ---------------------------------------------------------------------------- -L89F3: lda $0623 ; 89F3 AD 23 06 .#. +L89F3: lda falling_flag ; 89F3 AD 23 06 .#. cmp #$02 ; 89F6 C9 02 .. beq L89FB ; 89F8 F0 01 .. rts ; 89FA 60 ` @@ -1819,7 +1831,7 @@ L8A16: lda $0663 ; 8A16 AD 63 06 L8A25: lda #$09 ; 8A25 A9 09 .. sta current_speed ; 8A27 8D 24 06 .$. lda #$00 ; 8A2A A9 00 .. - sta $0623 ; 8A2C 8D 23 06 .#. + sta falling_flag ; 8A2C 8D 23 06 .#. sta player_x_pos ; 8A2F 8D 7E 06 .~. dec lives ; 8A32 CE 0A 07 ... sta $06EE ; 8A35 8D EE 06 ... @@ -2046,7 +2058,7 @@ no_cross: sta num_out+1 ; 8BF6 85 D4 .. ldx #$03 ; 8BF8 A2 03 .. L8BFA: lda struct_user_1,y ; 8BFA B9 0B 07 ... - sta $CF,x ; 8BFD 95 CF .. + sta tmp_sprite_height,x ; 8BFD 95 CF .. dey ; 8BFF 88 . dex ; 8C00 CA . bne L8BFA ; 8C01 D0 F7 .. @@ -2309,7 +2321,7 @@ L8DAA: jsr well_done_screen ; 8DAA 20 00 BC hide_player: lda #$02 ; 8DB8 A9 02 .. sta HPOSM3,x ; 8DBA 9D 07 D0 ... - sta $067C,x ; 8DBD 9D 7C 06 .|. + sta player_new_x,x ; 8DBD 9D 7C 06 .|. lda #$00 ; 8DC0 A9 00 .. sta $06EA,x ; 8DC2 9D EA 06 ... rts ; 8DC5 60 ` @@ -2411,7 +2423,7 @@ zero_filler_8e67: bullet_logic: lda $0622 ; 8E69 AD 22 06 .". beq no_bullet ; 8E6C F0 07 .. - lda $0623 ; 8E6E AD 23 06 .#. + lda falling_flag ; 8E6E AD 23 06 .#. cmp #$02 ; 8E71 C9 02 .. bne want_bullet ; 8E73 D0 01 .. no_bullet: @@ -2563,9 +2575,9 @@ check_pl_coll_no_pl: ora sav_m3pl ; 8F82 0D BB 06 ... and #$01 ; 8F85 29 01 ). beq L8F91 ; 8F87 F0 08 .. - lda $0623 ; 8F89 AD 23 06 .#. + lda falling_flag ; 8F89 AD 23 06 .#. bne L8F91 ; 8F8C D0 03 .. - inc $0623 ; 8F8E EE 23 06 .#. + inc falling_flag ; 8F8E EE 23 06 .#. L8F91: rts ; 8F91 60 ` ; ---------------------------------------------------------------------------- @@ -3465,10 +3477,10 @@ game_main_loop: L9743: jsr check_bomb_coll_jv ; 9743 20 33 80 3. lda work_level_num_bombs ; 9746 AD 8A 07 ... beq got_all_bombs ; 9749 F0 1B .. - lda $0623 ; 974B AD 23 06 .#. + lda falling_flag ; 974B AD 23 06 .#. cmp #$02 ; 974E C9 02 .. bne L9743 ; 9750 D0 F1 .. -L9752: lda $0623 ; 9752 AD 23 06 .#. +L9752: lda falling_flag ; 9752 AD 23 06 .#. cmp #$02 ; 9755 C9 02 .. beq L9752 ; 9757 F0 F9 .. lda lives ; 9759 AD 0A 07 ... @@ -3545,7 +3557,7 @@ mj_delay: mj_done:lda #$00 ; 97DB A9 00 .. sta AUDF4 ; 97DD 8D 06 D2 ... sta AUDC4 ; 97E0 8D 07 D2 ... - sta $0623 ; 97E3 8D 23 06 .#. + sta falling_flag ; 97E3 8D 23 06 .#. lda initial_speed ; 97E6 AD 25 06 .%. sta current_speed ; 97E9 8D 24 06 .$. inc playing_level ; 97EC EE 27 06 .'. @@ -3558,14 +3570,16 @@ zero_filler_97f0: ; ---------------------------------------------------------------------------- ; called via vector in page 6 check_falling_1: - lda falling_flag ; 9800 AD 21 06 .!. + lda start_falling_flag ; 9800 AD 21 06 .!. bne L9806 ; 9803 D0 01 .. -L9805: rts ; 9805 60 ` +cf_done:rts ; 9805 60 ` ; ---------------------------------------------------------------------------- -L9806: lda $0623 ; 9806 AD 23 06 .#. - bne L9805 ; 9809 D0 FA .. +L9806: lda falling_flag ; 9806 AD 23 06 .#. + bne cf_done ; 9809 D0 FA .. lda player_y_pos ; 980B AD 83 06 ... +; we're falling, have we hit the ground yet? +check_ground: cmp #$C6 ; 980E C9 C6 .. bcs L982E ; 9810 B0 1C .. lda jump_frame ; 9812 AD EB 06 ... @@ -3583,7 +3597,7 @@ check_collisions_2: ora sav_p1pf ; 9827 0D B5 06 ... and #$03 ; 982A 29 03 ). bne check_collisions_3 ; 982C D0 04 .. -L982E: inc $0623 ; 982E EE 23 06 .#. +L982E: inc falling_flag ; 982E EE 23 06 .#. rts ; 9831 60 ` ; ---------------------------------------------------------------------------- @@ -4427,7 +4441,7 @@ level01_sub_eol: ; all zeroes level01_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A028 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level01_colpf3: .byte $CA ; A02E CA . ; color for girders and up-ropes @@ -4534,7 +4548,7 @@ level02_sub_eol: ; all zeroes level02_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A068 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level02_colpf3: .byte $6A ; A06E 6A j ; color for girders and up-ropes @@ -4641,7 +4655,7 @@ level03_sub_eol: ; all zeroes level03_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A0A8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level03_colpf3: .byte $1A ; A0AE 1A . ; color for girders and up-ropes @@ -4748,7 +4762,7 @@ level04_sub_eol: ; all zeroes level04_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A0E8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level04_colpf3: .byte $CA ; A0EE CA . ; color for girders and up-ropes @@ -4855,7 +4869,7 @@ level05_sub_eol: ; all zeroes level05_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A128 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level05_colpf3: .byte $6A ; A12E 6A j ; color for girders and up-ropes @@ -4962,7 +4976,7 @@ level06_sub_eol: ; all zeroes level06_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A168 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level06_colpf3: .byte $56 ; A16E 56 V ; color for girders and up-ropes @@ -5069,7 +5083,7 @@ level07_sub_eol: ; all zeroes level07_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A1A8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level07_colpf3: .byte $CA ; A1AE CA . ; color for girders and up-ropes @@ -5176,7 +5190,7 @@ level08_sub_eol: ; all zeroes level08_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A1E8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level08_colpf3: .byte $6A ; A1EE 6A j ; color for girders and up-ropes @@ -5283,7 +5297,7 @@ level09_sub_eol: ; all zeroes level09_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A228 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level09_colpf3: .byte $1A ; A22E 1A . ; color for girders and up-ropes @@ -5390,7 +5404,7 @@ level10_sub_eol: ; all zeroes level10_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A268 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level10_colpf3: .byte $CA ; A26E CA . ; color for girders and up-ropes @@ -5497,7 +5511,7 @@ level11_sub_eol: ; all zeroes level11_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A2A8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level11_colpf3: .byte $6A ; A2AE 6A j ; color for girders and up-ropes @@ -5604,7 +5618,7 @@ level12_sub_eol: ; all zeroes level12_offs_40: .byte $00,$00,$00,$00,$00,$00 ; A2E8 00 00 00 00 00 00 ...... -; color (not sure what gets drawn in this color yet) +; color for missiles (aka 5th player) level12_colpf3: .byte $08 ; A2EE 08 . ; color for girders and up-ropes @@ -5733,9 +5747,9 @@ electrocution_bomb_pickup: lda LA563,y ; A4C1 B9 63 A5 .c. asl a ; A4C4 0A . adc #$20 ; A4C5 69 20 i - sta $0686 ; A4C7 8D 86 06 ... + sta player_new_y ; A4C7 8D 86 06 ... lda LA5A2,y ; A4CA B9 A2 A5 ... - sta $068B ; A4CD 8D 8B 06 ... + sta player_x ; A4CD 8D 8B 06 ... lda LA5A3,y ; A4D0 B9 A3 A5 ... sta PCOLR3 ; A4D3 8D C3 02 ... sta $066C ; A4D6 8D 6C 06 .l. @@ -5745,9 +5759,9 @@ electrocution_bomb_pickup: ; ---------------------------------------------------------------------------- ; turn off electrocution effect (?) electrocution_done: - lda $0623 ; A4DD AD 23 06 .#. + lda falling_flag ; A4DD AD 23 06 .#. bne LA4FF ; A4E0 D0 1D .. - lda falling_flag ; A4E2 AD 21 06 .!. + lda start_falling_flag ; A4E2 AD 21 06 .!. bne LA4E8 ; A4E5 D0 01 .. rts ; A4E7 60 ` @@ -5900,7 +5914,7 @@ dumbwaiter_sub0: sta $0770 ; A6D4 8D 70 07 .p. lda #$FF ; A6D7 A9 FF .. sta $0771 ; A6D9 8D 71 07 .q. -LA6DC: lda $0623 ; A6DC AD 23 06 .#. +LA6DC: lda falling_flag ; A6DC AD 23 06 .#. cmp #$02 ; A6DF C9 02 .. beq LA6BC ; A6E1 F0 D9 .. lda $0622 ; A6E3 AD 22 06 .". @@ -5938,7 +5952,7 @@ LA719: lda $2B00,x ; A719 BD 00 2B ; ---------------------------------------------------------------------------- ; gets called every frame dumbwaiter_sub3: - lda $0623 ; A724 AD 23 06 .#. + lda falling_flag ; A724 AD 23 06 .#. cmp #$02 ; A727 C9 02 .. beq LA778 ; A729 F0 4D .M lda $0622 ; A72B AD 22 06 .". @@ -6024,7 +6038,7 @@ hellstones_sub3: ; ---------------------------------------------------------------------------- hellstones_sub0: - lda $0623 ; A836 AD 23 06 .#. + lda falling_flag ; A836 AD 23 06 .#. cmp #$02 ; A839 C9 02 .. beq LA842 ; A83B F0 05 .. lda $0622 ; A83D AD 22 06 .". @@ -6598,7 +6612,7 @@ ltr_skip: ; per letter bonus_250_pts: lda $0770 ; AF96 AD 70 07 .p. - sta $0686 ; AF99 8D 86 06 ... + sta player_new_y ; AF99 8D 86 06 ... lda #$86 ; AF9C A9 86 .. sta $0681 ; AF9E 8D 81 06 ... clc ; AFA1 18 . @@ -6739,7 +6753,7 @@ blackout_bomb_sub: ; ---------------------------------------------------------------------------- ; copies pixels from rendered real map at $1000 to visible screen memory at $3000, centered around jumpman's location blackout_sub0: - lda falling_flag ; B140 AD 21 06 .!. + lda start_falling_flag ; B140 AD 21 06 .!. bne LB146 ; B143 D0 01 .. LB145: rts ; B145 60 ` @@ -6993,7 +7007,7 @@ hatch_bomb_sub: ; ---------------------------------------------------------------------------- hatch_sub0: - lda $0623 ; B457 AD 23 06 .#. + lda falling_flag ; B457 AD 23 06 .#. cmp #$02 ; B45A C9 02 .. bne LB46A ; B45C D0 0C .. lda #$00 ; B45E A9 00 .. @@ -7034,22 +7048,22 @@ LB49F: lda $0771 ; B49F AD 71 07 beq LB4C1 ; B4A6 F0 19 .. clc ; B4A8 18 . adc #$04 ; B4A9 69 04 i. - sta $068B ; B4AB 8D 8B 06 ... + sta player_x ; B4AB 8D 8B 06 ... inc $0771 ; B4AE EE 71 07 .q. lda $0680 ; B4B1 AD 80 06 ... sta $0681 ; B4B4 8D 81 06 ... lda $0685 ; B4B7 AD 85 06 ... - sta $0686 ; B4BA 8D 86 06 ... + sta player_new_y ; B4BA 8D 86 06 ... sta $066D ; B4BD 8D 6D 06 .m. rts ; B4C0 60 ` ; ---------------------------------------------------------------------------- -LB4C1: lda $068B ; B4C1 AD 8B 06 ... +LB4C1: lda player_x ; B4C1 AD 8B 06 ... and #$03 ; B4C4 29 03 ). clc ; B4C6 18 . adc #$04 ; B4C7 69 04 i. - sta $068B ; B4C9 8D 8B 06 ... - inc $068B ; B4CC EE 8B 06 ... + sta player_x ; B4C9 8D 8B 06 ... + inc player_x ; B4CC EE 8B 06 ... cmp #$07 ; B4CF C9 07 .. bne LB4E2 ; B4D1 D0 0F .. cue_woop_sound: @@ -7069,14 +7083,14 @@ LB4EE: sty $A0 ; B4EE 84 A0 adc $A0 ; B4F1 65 A0 e. sta $0681 ; B4F3 8D 81 06 ... ldy #$01 ; B4F6 A0 01 .. - lda $0686 ; B4F8 AD 86 06 ... + lda player_new_y ; B4F8 AD 86 06 ... cmp player_y_pos ; B4FB CD 83 06 ... bcc LB502 ; B4FE 90 02 .. ldy #$FF ; B500 A0 FF .. LB502: sty $A0 ; B502 84 A0 .. clc ; B504 18 . adc $A0 ; B505 65 A0 e. - sta $0686 ; B507 8D 86 06 ... + sta player_new_y ; B507 8D 86 06 ... rts ; B50A 60 ` ; ---------------------------------------------------------------------------- @@ -7155,7 +7169,7 @@ l12_unkn0: .byte $05 ; B690 05 . ; ---------------------------------------------------------------------------- hurr_sub0: - lda falling_flag ; B691 AD 21 06 .!. + lda start_falling_flag ; B691 AD 21 06 .!. bne falling_wind ; B694 D0 01 .. rts ; B696 60 ` @@ -7171,7 +7185,7 @@ hurr_sub1: lda current_speed ; B69B AD 24 06 .$. cmp #$09 ; B69E C9 09 .. bcs LB6A9 ; B6A0 B0 07 .. - lda $0623 ; B6A2 AD 23 06 .#. + lda falling_flag ; B6A2 AD 23 06 .#. cmp #$02 ; B6A5 C9 02 .. bne LB6BA ; B6A7 D0 11 .. LB6A9: lda $0768 ; B6A9 AD 68 07 .h. @@ -7707,7 +7721,7 @@ wd_wait_32j: lda #$0D ; BC79 A9 0D .. sta joystick_disabled ; BC7B 8D 32 06 .2. lda #$00 ; BC7E A9 00 .. - sta $0623 ; BC80 8D 23 06 .#. + sta falling_flag ; BC80 8D 23 06 .#. lda #$52 ; BC83 A9 52 .R sta work_level_sub1 ; BC85 8D 84 07 ... lda #$BD ; BC88 A9 BD .. @@ -7736,7 +7750,7 @@ print_total_score_msg: ldx #$03 ; BCB4 A2 03 .. ; display current user's score, number_of_users should be score-1 here. wd_xxx: lda number_of_users,x ; BCB6 BD FF 06 ... - sta $CF,x ; BCB9 95 CF .. + sta tmp_sprite_height,x ; BCB9 95 CF .. dex ; BCBB CA . bne wd_xxx ; BCBC D0 F8 .. jsr print_number_jv ; BCBE 20 09 80 .. @@ -7779,7 +7793,7 @@ well_done_map: ; ---------------------------------------------------------------------------- ; used in work_level_sub1 slot during well_doneused in work_level_sub1 slot during well_done well_done_sub1: - lda falling_flag ; BD52 AD 21 06 .!. + lda start_falling_flag ; BD52 AD 21 06 .!. bne wds1_cont ; BD55 D0 01 .. rts ; BD57 60 ` @@ -7816,7 +7830,7 @@ wds1_finish: lda #$C6 ; BD90 A9 C6 .. sta player_y_pos ; BD92 8D 83 06 ... lda #$00 ; BD95 A9 00 .. - sta falling_flag ; BD97 8D 21 06 .!. + sta start_falling_flag ; BD97 8D 21 06 .!. lda #$01 ; BD9A A9 01 .. sta $0688 ; BD9C 8D 88 06 ... rts ; BD9F 60 ` diff --git a/jumpmanjr.info b/jumpmanjr.info index bff050f..6ad7960 100644 --- a/jumpmanjr.info +++ b/jumpmanjr.info @@ -620,7 +620,10 @@ label { name "check_falling_2"; addr $8900; comment "called via vector in page 6 label { name "bullet_logic"; addr $8E69; comment "not sure what $0622, $0623 are for yet"; }; label { name "rand_1_to_3"; addr $8E86; comment "A = rand() % 3 + 1; // bullets only come from left, right, or top (never bottom)"; }; label { name "bullet_table_minus_one"; addr $8F42; comment "1-indexed"; }; -label { name "falling_flag"; addr $0621; comment "1 = falling, reset to 0 when jumpman hits the ground"; }; +label { name "start_falling_flag"; addr $0621; comment "reset to 0 every frame, set to 1 when starting to fall"; }; +label { name "check_ground"; addr $980E; comment "we're falling, have we hit the ground yet?"; }; +label { name "cf_done"; addr $9805; }; +label { name "falling_flag"; addr $0623; comment "0 = ok, 1 = falling, 2 = on ground."; }; label { name "jiffy_timer_1"; addr $061A; comment "gets incremented every frame"; }; label { name "jiffy_timer_2"; addr $061B; comment "gets incremented every frame"; }; label { name "jiffy_timer_3_lo"; addr $0619; comment "gets incremented every frame"; }; @@ -869,7 +872,7 @@ label { name "update_status_window"; addr $8694; comment "bottom 2 GR.1 lines on label { name "update_status_window_jv"; addr $8012; comment "bottom 2 GR.1 lines on the game board"; }; label { name "setup_gameboard_dlist"; addr $9B00; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; label { name "setup_gameboard_dlist_jv"; addr $8015; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; -label { name "print_number"; addr $8600; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out"; }; +label { name "print_number"; addr $8600; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out. num_in is modified."; }; label { name "print_number_jv"; addr $8009; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out"; }; label { name "num_tmp"; addr $0665; size 1; comment "temp used by print_number"; }; label { name "num_in"; addr $D0; size 3; comment "print_number input. 3-byte number (LSB first as usual) to be printed"; }; @@ -922,6 +925,17 @@ label { name "sfx_woop"; addr $B564; }; label { name "got_all_bombs"; addr $9766; }; label { name "call_eol_sub"; addr $976C; }; +label { name "player_new_x"; addr $067C; comment "HPOSxx, 1-indexed, $067d thru $0681 are p5, p3..p0"; }; +label { name "player_x"; addr $068B; comment "HPOSxx, $068c thru $06c0"; }; +label { name "player_new_y"; addr $0686; comment "$0687 thru $069b"; }; +label { name "player_y"; addr $0695; comment "vertical positions, actually $0696 thru $069a"; }; +label { name "player_height"; addr $0677; comment "actually $0677 thru $067b"; }; +label { name "player_enabled"; addr $0668; comment "1 = draw this player, 0 = no. actually $0669 thru $066e"; }; +label { name "tmp_sprite"; addr $CD; size 2; comment "ZP pointer to player/missile data (e.g. jumpman's 10-byte animation frames)"; }; +label { name "tmp_sprite_height"; addr $CF; size 1; comment "length of data pointed to by tmp_sprite"; }; +label { name "copy_pm_data"; addr $8370; comment "write to P/M memory"; }; +label { name "adj_ptr"; addr $835F; comment "adjust pointer if Y wraps around"; }; + # end of main.info, everything below here is generated by mklevelinfo.pl label { name "work_level_desc"; addr $0780; size 2; comment "first 2 bytes are level number in screencodes"; }; label { name "work_level_sub0"; addr $0782; size 2; comment "a subroutine"; }; @@ -948,7 +962,7 @@ label { name "work_level_init"; addr $07a2; size 2; comment "called at start of label { name "work_level_sub6"; addr $07a4; size 2; comment "always $9740 aka game_main_loop"; }; label { name "work_level_sub_eol"; addr $07a6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; label { name "work_level_offs_40"; addr $07a8; size 6; comment "all zeroes"; }; -label { name "work_level_colpf3"; addr $07ae; size 1; comment "color (not sure what gets drawn in this color yet)"; }; +label { name "work_level_colpf3"; addr $07ae; size 1; comment "color for missiles (aka 5th player)"; }; label { name "work_level_colpf0"; addr $07af; size 1; comment "color for girders and up-ropes"; }; label { name "work_level_colpf1"; addr $07b0; size 1; comment "color for ladders and down-ropes"; }; label { name "work_level_colpf2"; addr $07b1; size 1; comment "color for bombs"; }; @@ -982,7 +996,7 @@ label { name "cur_level_init"; addr $07e2; size 2; comment "called at start of l label { name "cur_level_sub6"; addr $07e4; size 2; comment "always $9740 aka game_main_loop"; }; label { name "cur_level_sub_eol"; addr $07e6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; label { name "cur_level_offs_40"; addr $07e8; size 6; comment "all zeroes"; }; -label { name "cur_level_colpf3"; addr $07ee; size 1; comment "color (not sure what gets drawn in this color yet)"; }; +label { name "cur_level_colpf3"; addr $07ee; size 1; comment "color for missiles (aka 5th player)"; }; label { name "cur_level_colpf0"; addr $07ef; size 1; comment "color for girders and up-ropes"; }; label { name "cur_level_colpf1"; addr $07f0; size 1; comment "color for ladders and down-ropes"; }; label { name "cur_level_colpf2"; addr $07f1; size 1; comment "color for bombs"; }; @@ -1016,7 +1030,7 @@ range { name "level01_init"; start $a022; end $a023; type addrtable; comment "ca range { name "level01_sub6"; start $a024; end $a025; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level01_sub_eol"; start $a026; end $a027; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level01_offs_40"; start $a028; end $a02d; type bytetable; comment "all zeroes"; }; -range { name "level01_colpf3"; start $a02e; end $a02e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level01_colpf3"; start $a02e; end $a02e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level01_colpf0"; start $a02f; end $a02f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level01_colpf1"; start $a030; end $a030; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level01_colpf2"; start $a031; end $a031; type bytetable; comment "color for bombs"; }; @@ -1050,7 +1064,7 @@ range { name "level02_init"; start $a062; end $a063; type addrtable; comment "ca range { name "level02_sub6"; start $a064; end $a065; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level02_sub_eol"; start $a066; end $a067; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level02_offs_40"; start $a068; end $a06d; type bytetable; comment "all zeroes"; }; -range { name "level02_colpf3"; start $a06e; end $a06e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level02_colpf3"; start $a06e; end $a06e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level02_colpf0"; start $a06f; end $a06f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level02_colpf1"; start $a070; end $a070; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level02_colpf2"; start $a071; end $a071; type bytetable; comment "color for bombs"; }; @@ -1084,7 +1098,7 @@ range { name "level03_init"; start $a0a2; end $a0a3; type addrtable; comment "ca range { name "level03_sub6"; start $a0a4; end $a0a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level03_sub_eol"; start $a0a6; end $a0a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level03_offs_40"; start $a0a8; end $a0ad; type bytetable; comment "all zeroes"; }; -range { name "level03_colpf3"; start $a0ae; end $a0ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level03_colpf3"; start $a0ae; end $a0ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level03_colpf0"; start $a0af; end $a0af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level03_colpf1"; start $a0b0; end $a0b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level03_colpf2"; start $a0b1; end $a0b1; type bytetable; comment "color for bombs"; }; @@ -1118,7 +1132,7 @@ range { name "level04_init"; start $a0e2; end $a0e3; type addrtable; comment "ca range { name "level04_sub6"; start $a0e4; end $a0e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level04_sub_eol"; start $a0e6; end $a0e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level04_offs_40"; start $a0e8; end $a0ed; type bytetable; comment "all zeroes"; }; -range { name "level04_colpf3"; start $a0ee; end $a0ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level04_colpf3"; start $a0ee; end $a0ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level04_colpf0"; start $a0ef; end $a0ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level04_colpf1"; start $a0f0; end $a0f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level04_colpf2"; start $a0f1; end $a0f1; type bytetable; comment "color for bombs"; }; @@ -1152,7 +1166,7 @@ range { name "level05_init"; start $a122; end $a123; type addrtable; comment "ca range { name "level05_sub6"; start $a124; end $a125; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level05_sub_eol"; start $a126; end $a127; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level05_offs_40"; start $a128; end $a12d; type bytetable; comment "all zeroes"; }; -range { name "level05_colpf3"; start $a12e; end $a12e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level05_colpf3"; start $a12e; end $a12e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level05_colpf0"; start $a12f; end $a12f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level05_colpf1"; start $a130; end $a130; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level05_colpf2"; start $a131; end $a131; type bytetable; comment "color for bombs"; }; @@ -1186,7 +1200,7 @@ range { name "level06_init"; start $a162; end $a163; type addrtable; comment "ca range { name "level06_sub6"; start $a164; end $a165; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level06_sub_eol"; start $a166; end $a167; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level06_offs_40"; start $a168; end $a16d; type bytetable; comment "all zeroes"; }; -range { name "level06_colpf3"; start $a16e; end $a16e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level06_colpf3"; start $a16e; end $a16e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level06_colpf0"; start $a16f; end $a16f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level06_colpf1"; start $a170; end $a170; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level06_colpf2"; start $a171; end $a171; type bytetable; comment "color for bombs"; }; @@ -1220,7 +1234,7 @@ range { name "level07_init"; start $a1a2; end $a1a3; type addrtable; comment "ca range { name "level07_sub6"; start $a1a4; end $a1a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level07_sub_eol"; start $a1a6; end $a1a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level07_offs_40"; start $a1a8; end $a1ad; type bytetable; comment "all zeroes"; }; -range { name "level07_colpf3"; start $a1ae; end $a1ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level07_colpf3"; start $a1ae; end $a1ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level07_colpf0"; start $a1af; end $a1af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level07_colpf1"; start $a1b0; end $a1b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level07_colpf2"; start $a1b1; end $a1b1; type bytetable; comment "color for bombs"; }; @@ -1254,7 +1268,7 @@ range { name "level08_init"; start $a1e2; end $a1e3; type addrtable; comment "ca range { name "level08_sub6"; start $a1e4; end $a1e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level08_sub_eol"; start $a1e6; end $a1e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level08_offs_40"; start $a1e8; end $a1ed; type bytetable; comment "all zeroes"; }; -range { name "level08_colpf3"; start $a1ee; end $a1ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level08_colpf3"; start $a1ee; end $a1ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level08_colpf0"; start $a1ef; end $a1ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level08_colpf1"; start $a1f0; end $a1f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level08_colpf2"; start $a1f1; end $a1f1; type bytetable; comment "color for bombs"; }; @@ -1288,7 +1302,7 @@ range { name "level09_init"; start $a222; end $a223; type addrtable; comment "ca range { name "level09_sub6"; start $a224; end $a225; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level09_sub_eol"; start $a226; end $a227; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level09_offs_40"; start $a228; end $a22d; type bytetable; comment "all zeroes"; }; -range { name "level09_colpf3"; start $a22e; end $a22e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level09_colpf3"; start $a22e; end $a22e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level09_colpf0"; start $a22f; end $a22f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level09_colpf1"; start $a230; end $a230; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level09_colpf2"; start $a231; end $a231; type bytetable; comment "color for bombs"; }; @@ -1322,7 +1336,7 @@ range { name "level10_init"; start $a262; end $a263; type addrtable; comment "ca range { name "level10_sub6"; start $a264; end $a265; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level10_sub_eol"; start $a266; end $a267; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level10_offs_40"; start $a268; end $a26d; type bytetable; comment "all zeroes"; }; -range { name "level10_colpf3"; start $a26e; end $a26e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level10_colpf3"; start $a26e; end $a26e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level10_colpf0"; start $a26f; end $a26f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level10_colpf1"; start $a270; end $a270; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level10_colpf2"; start $a271; end $a271; type bytetable; comment "color for bombs"; }; @@ -1356,7 +1370,7 @@ range { name "level11_init"; start $a2a2; end $a2a3; type addrtable; comment "ca range { name "level11_sub6"; start $a2a4; end $a2a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level11_sub_eol"; start $a2a6; end $a2a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level11_offs_40"; start $a2a8; end $a2ad; type bytetable; comment "all zeroes"; }; -range { name "level11_colpf3"; start $a2ae; end $a2ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level11_colpf3"; start $a2ae; end $a2ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level11_colpf0"; start $a2af; end $a2af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level11_colpf1"; start $a2b0; end $a2b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level11_colpf2"; start $a2b1; end $a2b1; type bytetable; comment "color for bombs"; }; @@ -1390,7 +1404,7 @@ range { name "level12_init"; start $a2e2; end $a2e3; type addrtable; comment "ca range { name "level12_sub6"; start $a2e4; end $a2e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level12_sub_eol"; start $a2e6; end $a2e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level12_offs_40"; start $a2e8; end $a2ed; type bytetable; comment "all zeroes"; }; -range { name "level12_colpf3"; start $a2ee; end $a2ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level12_colpf3"; start $a2ee; end $a2ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level12_colpf0"; start $a2ef; end $a2ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level12_colpf1"; start $a2f0; end $a2f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level12_colpf2"; start $a2f1; end $a2f1; type bytetable; comment "color for bombs"; }; diff --git a/leveldesc.info b/leveldesc.info index bbe8179..68fd94c 100644 --- a/leveldesc.info +++ b/leveldesc.info @@ -23,7 +23,7 @@ label { name "work_level_init"; addr $07a2; size 2; comment "called at start of label { name "work_level_sub6"; addr $07a4; size 2; comment "always $9740 aka game_main_loop"; }; label { name "work_level_sub_eol"; addr $07a6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; label { name "work_level_offs_40"; addr $07a8; size 6; comment "all zeroes"; }; -label { name "work_level_colpf3"; addr $07ae; size 1; comment "color (not sure what gets drawn in this color yet)"; }; +label { name "work_level_colpf3"; addr $07ae; size 1; comment "color for missiles (aka 5th player)"; }; label { name "work_level_colpf0"; addr $07af; size 1; comment "color for girders and up-ropes"; }; label { name "work_level_colpf1"; addr $07b0; size 1; comment "color for ladders and down-ropes"; }; label { name "work_level_colpf2"; addr $07b1; size 1; comment "color for bombs"; }; @@ -57,7 +57,7 @@ label { name "cur_level_init"; addr $07e2; size 2; comment "called at start of l label { name "cur_level_sub6"; addr $07e4; size 2; comment "always $9740 aka game_main_loop"; }; label { name "cur_level_sub_eol"; addr $07e6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; label { name "cur_level_offs_40"; addr $07e8; size 6; comment "all zeroes"; }; -label { name "cur_level_colpf3"; addr $07ee; size 1; comment "color (not sure what gets drawn in this color yet)"; }; +label { name "cur_level_colpf3"; addr $07ee; size 1; comment "color for missiles (aka 5th player)"; }; label { name "cur_level_colpf0"; addr $07ef; size 1; comment "color for girders and up-ropes"; }; label { name "cur_level_colpf1"; addr $07f0; size 1; comment "color for ladders and down-ropes"; }; label { name "cur_level_colpf2"; addr $07f1; size 1; comment "color for bombs"; }; @@ -91,7 +91,7 @@ range { name "level01_init"; start $a022; end $a023; type addrtable; comment "ca range { name "level01_sub6"; start $a024; end $a025; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level01_sub_eol"; start $a026; end $a027; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level01_offs_40"; start $a028; end $a02d; type bytetable; comment "all zeroes"; }; -range { name "level01_colpf3"; start $a02e; end $a02e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level01_colpf3"; start $a02e; end $a02e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level01_colpf0"; start $a02f; end $a02f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level01_colpf1"; start $a030; end $a030; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level01_colpf2"; start $a031; end $a031; type bytetable; comment "color for bombs"; }; @@ -125,7 +125,7 @@ range { name "level02_init"; start $a062; end $a063; type addrtable; comment "ca range { name "level02_sub6"; start $a064; end $a065; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level02_sub_eol"; start $a066; end $a067; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level02_offs_40"; start $a068; end $a06d; type bytetable; comment "all zeroes"; }; -range { name "level02_colpf3"; start $a06e; end $a06e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level02_colpf3"; start $a06e; end $a06e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level02_colpf0"; start $a06f; end $a06f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level02_colpf1"; start $a070; end $a070; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level02_colpf2"; start $a071; end $a071; type bytetable; comment "color for bombs"; }; @@ -159,7 +159,7 @@ range { name "level03_init"; start $a0a2; end $a0a3; type addrtable; comment "ca range { name "level03_sub6"; start $a0a4; end $a0a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level03_sub_eol"; start $a0a6; end $a0a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level03_offs_40"; start $a0a8; end $a0ad; type bytetable; comment "all zeroes"; }; -range { name "level03_colpf3"; start $a0ae; end $a0ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level03_colpf3"; start $a0ae; end $a0ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level03_colpf0"; start $a0af; end $a0af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level03_colpf1"; start $a0b0; end $a0b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level03_colpf2"; start $a0b1; end $a0b1; type bytetable; comment "color for bombs"; }; @@ -193,7 +193,7 @@ range { name "level04_init"; start $a0e2; end $a0e3; type addrtable; comment "ca range { name "level04_sub6"; start $a0e4; end $a0e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level04_sub_eol"; start $a0e6; end $a0e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level04_offs_40"; start $a0e8; end $a0ed; type bytetable; comment "all zeroes"; }; -range { name "level04_colpf3"; start $a0ee; end $a0ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level04_colpf3"; start $a0ee; end $a0ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level04_colpf0"; start $a0ef; end $a0ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level04_colpf1"; start $a0f0; end $a0f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level04_colpf2"; start $a0f1; end $a0f1; type bytetable; comment "color for bombs"; }; @@ -227,7 +227,7 @@ range { name "level05_init"; start $a122; end $a123; type addrtable; comment "ca range { name "level05_sub6"; start $a124; end $a125; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level05_sub_eol"; start $a126; end $a127; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level05_offs_40"; start $a128; end $a12d; type bytetable; comment "all zeroes"; }; -range { name "level05_colpf3"; start $a12e; end $a12e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level05_colpf3"; start $a12e; end $a12e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level05_colpf0"; start $a12f; end $a12f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level05_colpf1"; start $a130; end $a130; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level05_colpf2"; start $a131; end $a131; type bytetable; comment "color for bombs"; }; @@ -261,7 +261,7 @@ range { name "level06_init"; start $a162; end $a163; type addrtable; comment "ca range { name "level06_sub6"; start $a164; end $a165; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level06_sub_eol"; start $a166; end $a167; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level06_offs_40"; start $a168; end $a16d; type bytetable; comment "all zeroes"; }; -range { name "level06_colpf3"; start $a16e; end $a16e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level06_colpf3"; start $a16e; end $a16e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level06_colpf0"; start $a16f; end $a16f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level06_colpf1"; start $a170; end $a170; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level06_colpf2"; start $a171; end $a171; type bytetable; comment "color for bombs"; }; @@ -295,7 +295,7 @@ range { name "level07_init"; start $a1a2; end $a1a3; type addrtable; comment "ca range { name "level07_sub6"; start $a1a4; end $a1a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level07_sub_eol"; start $a1a6; end $a1a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level07_offs_40"; start $a1a8; end $a1ad; type bytetable; comment "all zeroes"; }; -range { name "level07_colpf3"; start $a1ae; end $a1ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level07_colpf3"; start $a1ae; end $a1ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level07_colpf0"; start $a1af; end $a1af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level07_colpf1"; start $a1b0; end $a1b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level07_colpf2"; start $a1b1; end $a1b1; type bytetable; comment "color for bombs"; }; @@ -329,7 +329,7 @@ range { name "level08_init"; start $a1e2; end $a1e3; type addrtable; comment "ca range { name "level08_sub6"; start $a1e4; end $a1e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level08_sub_eol"; start $a1e6; end $a1e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level08_offs_40"; start $a1e8; end $a1ed; type bytetable; comment "all zeroes"; }; -range { name "level08_colpf3"; start $a1ee; end $a1ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level08_colpf3"; start $a1ee; end $a1ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level08_colpf0"; start $a1ef; end $a1ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level08_colpf1"; start $a1f0; end $a1f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level08_colpf2"; start $a1f1; end $a1f1; type bytetable; comment "color for bombs"; }; @@ -363,7 +363,7 @@ range { name "level09_init"; start $a222; end $a223; type addrtable; comment "ca range { name "level09_sub6"; start $a224; end $a225; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level09_sub_eol"; start $a226; end $a227; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level09_offs_40"; start $a228; end $a22d; type bytetable; comment "all zeroes"; }; -range { name "level09_colpf3"; start $a22e; end $a22e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level09_colpf3"; start $a22e; end $a22e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level09_colpf0"; start $a22f; end $a22f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level09_colpf1"; start $a230; end $a230; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level09_colpf2"; start $a231; end $a231; type bytetable; comment "color for bombs"; }; @@ -397,7 +397,7 @@ range { name "level10_init"; start $a262; end $a263; type addrtable; comment "ca range { name "level10_sub6"; start $a264; end $a265; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level10_sub_eol"; start $a266; end $a267; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level10_offs_40"; start $a268; end $a26d; type bytetable; comment "all zeroes"; }; -range { name "level10_colpf3"; start $a26e; end $a26e; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level10_colpf3"; start $a26e; end $a26e; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level10_colpf0"; start $a26f; end $a26f; type bytetable; comment "color for girders and up-ropes"; }; range { name "level10_colpf1"; start $a270; end $a270; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level10_colpf2"; start $a271; end $a271; type bytetable; comment "color for bombs"; }; @@ -431,7 +431,7 @@ range { name "level11_init"; start $a2a2; end $a2a3; type addrtable; comment "ca range { name "level11_sub6"; start $a2a4; end $a2a5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level11_sub_eol"; start $a2a6; end $a2a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level11_offs_40"; start $a2a8; end $a2ad; type bytetable; comment "all zeroes"; }; -range { name "level11_colpf3"; start $a2ae; end $a2ae; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level11_colpf3"; start $a2ae; end $a2ae; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level11_colpf0"; start $a2af; end $a2af; type bytetable; comment "color for girders and up-ropes"; }; range { name "level11_colpf1"; start $a2b0; end $a2b0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level11_colpf2"; start $a2b1; end $a2b1; type bytetable; comment "color for bombs"; }; @@ -465,7 +465,7 @@ range { name "level12_init"; start $a2e2; end $a2e3; type addrtable; comment "ca range { name "level12_sub6"; start $a2e4; end $a2e5; type addrtable; comment "always $9740 aka game_main_loop"; }; range { name "level12_sub_eol"; start $a2e6; end $a2e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level08"; }; range { name "level12_offs_40"; start $a2e8; end $a2ed; type bytetable; comment "all zeroes"; }; -range { name "level12_colpf3"; start $a2ee; end $a2ee; type bytetable; comment "color (not sure what gets drawn in this color yet)"; }; +range { name "level12_colpf3"; start $a2ee; end $a2ee; type bytetable; comment "color for missiles (aka 5th player)"; }; range { name "level12_colpf0"; start $a2ef; end $a2ef; type bytetable; comment "color for girders and up-ropes"; }; range { name "level12_colpf1"; start $a2f0; end $a2f0; type bytetable; comment "color for ladders and down-ropes"; }; range { name "level12_colpf2"; start $a2f1; end $a2f1; type bytetable; comment "color for bombs"; }; @@ -618,7 +618,10 @@ label { name "check_falling_2"; addr $8900; comment "called via vector in page 6 label { name "bullet_logic"; addr $8E69; comment "not sure what $0622, $0623 are for yet"; }; label { name "rand_1_to_3"; addr $8E86; comment "A = rand() % 3 + 1; // bullets only come from left, right, or top (never bottom)"; }; label { name "bullet_table_minus_one"; addr $8F42; comment "1-indexed"; }; -label { name "falling_flag"; addr $0621; comment "1 = falling, reset to 0 when jumpman hits the ground"; }; +label { name "start_falling_flag"; addr $0621; comment "reset to 0 every frame, set to 1 when starting to fall"; }; +label { name "check_ground"; addr $980E; comment "we're falling, have we hit the ground yet?"; }; +label { name "cf_done"; addr $9805; }; +label { name "falling_flag"; addr $0623; comment "0 = ok, 1 = falling, 2 = on ground."; }; label { name "jiffy_timer_1"; addr $061A; comment "gets incremented every frame"; }; label { name "jiffy_timer_2"; addr $061B; comment "gets incremented every frame"; }; label { name "jiffy_timer_3_lo"; addr $0619; comment "gets incremented every frame"; }; @@ -867,7 +870,7 @@ label { name "update_status_window"; addr $8694; comment "bottom 2 GR.1 lines on label { name "update_status_window_jv"; addr $8012; comment "bottom 2 GR.1 lines on the game board"; }; label { name "setup_gameboard_dlist"; addr $9B00; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; label { name "setup_gameboard_dlist_jv"; addr $8015; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; -label { name "print_number"; addr $8600; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out"; }; +label { name "print_number"; addr $8600; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out. num_in is modified."; }; label { name "print_number_jv"; addr $8009; comment "convert the 3-byte integer stored at num_in to screen codes, store into memory pointed to by num_out"; }; label { name "num_tmp"; addr $0665; size 1; comment "temp used by print_number"; }; label { name "num_in"; addr $D0; size 3; comment "print_number input. 3-byte number (LSB first as usual) to be printed"; }; @@ -920,4 +923,15 @@ label { name "sfx_woop"; addr $B564; }; label { name "got_all_bombs"; addr $9766; }; label { name "call_eol_sub"; addr $976C; }; +label { name "player_new_x"; addr $067C; comment "HPOSxx, 1-indexed, $067d thru $0681 are p5, p3..p0"; }; +label { name "player_x"; addr $068B; comment "HPOSxx, $068c thru $06c0"; }; +label { name "player_new_y"; addr $0686; comment "$0687 thru $069b"; }; +label { name "player_y"; addr $0695; comment "vertical positions, actually $0696 thru $069a"; }; +label { name "player_height"; addr $0677; comment "actually $0677 thru $067b"; }; +label { name "player_enabled"; addr $0668; comment "1 = draw this player, 0 = no. actually $0669 thru $066e"; }; +label { name "tmp_sprite"; addr $CD; size 2; comment "ZP pointer to player/missile data (e.g. jumpman's 10-byte animation frames)"; }; +label { name "tmp_sprite_height"; addr $CF; size 1; comment "length of data pointed to by tmp_sprite"; }; +label { name "copy_pm_data"; addr $8370; comment "write to P/M memory"; }; +label { name "adj_ptr"; addr $835F; comment "adjust pointer if Y wraps around"; }; + # end of main.info, everything below here is generated by mklevelinfo.pl diff --git a/mklevelinfo.pl b/mklevelinfo.pl index 988606f..66401f8 100644 --- a/mklevelinfo.pl +++ b/mklevelinfo.pl @@ -26,7 +26,7 @@ 36 => [ 2, 'sub6', 'always $9740 aka game_main_loop' ], 38 => [ 2, 'sub_eol', 'called at end of level (all bombs picked up). $06E6 for all but level08' ], 40 => [ 6, 'offs', 'all zeroes' ], - 46 => [ 1, 'colpf3', 'color (not sure what gets drawn in this color yet)' ], + 46 => [ 1, 'colpf3', 'color for missiles (aka 5th player)' ], 47 => [ 1, 'colpf0', 'color for girders and up-ropes' ], 48 => [ 1, 'colpf1', 'color for ladders and down-ropes' ], 49 => [ 1, 'colpf2', 'color for bombs' ], diff --git a/pokeytest/Makefile b/pokeytest/Makefile new file mode 100644 index 0000000..e629344 --- /dev/null +++ b/pokeytest/Makefile @@ -0,0 +1,15 @@ + +all: + gcc -O2 -Wall -o playsdl2 playsdl2.c pokey.c `pkg-config sdl2 --cflags --libs` + +#gcc -O2 -Wall -o playsnd playsnd.c pokey.c + +#test: all +#./playsnd > 1.raw +#aplay -r 44100 -c 1 -t raw -f u8 1.raw + +test: all + ./playsdl2 $(TEST_SFX) + +clean: + rm -f *.o playsnd playsdl2 *.raw core diff --git a/pokeytest/playsdl2.c b/pokeytest/playsdl2.c new file mode 100644 index 0000000..3970a2e --- /dev/null +++ b/pokeytest/playsdl2.c @@ -0,0 +1,153 @@ +#include <SDL.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "pokey.h" + +#define ROM_FILE "../jumpmanjr.rom" +#define ROM_SIZE 0x4000 + +#define FREQ 44100 + +#define PAL_BUF_SIZE 882 +#define NTSC_BUF_SIZE 735 + +#define PAL_DELAY 20 +#define NTSC_DELAY 17 + +unsigned char sndbuf[PAL_BUF_SIZE + 1]; + +int buf_size = NTSC_BUF_SIZE; +int delay = NTSC_DELAY; + +unsigned char rom[ROM_SIZE]; + +void usage(void) { + fprintf(stderr, "usage: playsnd [-p] 0xaddr\n"); + exit(1); +} + +void load_rom(void) { + int size; + FILE *f; + + f = fopen(ROM_FILE, "rb"); + if(!f) { + perror(ROM_FILE); + usage(); + } + + size = fread(rom, 1, ROM_SIZE, f); + if(size != ROM_SIZE) { + fprintf(stderr, "file %s should be %d bytes long, not %d\n", + ROM_FILE, ROM_SIZE, size); + usage(); + } + + fprintf(stderr, "loaded ROM %s, %d bytes\n", ROM_FILE, size); +} + +void play_frames(unsigned char count) { + fprintf(stderr, "playing for %d frames\n", count); + while(count--) { + SDL_Delay(delay); + } +} + +void play_sfx(int addr) { + unsigned char *p = rom + (addr - 0x8000); + + while(1) { + fprintf(stderr, "$%04lx: $%02x\n", (p - rom + 0x8000), *p); + switch(*p) { + case 0: + fprintf(stderr, "opcode 0 (snd_end)\n"); + return; + case 1: + fprintf(stderr, "opcode 1 (snd_audc)\n"); + Update_pokey_sound(audc1, *++p); + play_frames(*++p); + ++p; + break; + case 2: + fprintf(stderr, "opcode 2 (snd_jump)\n"); + addr = *++p; + addr |= ( (*++p) << 8); + addr -= 0x8000; + p = rom + addr; + break; + case 3: + fprintf(stderr, "opcode 3 (snd_rest)\n"); + Update_pokey_sound(audc1, 0); + play_frames(*++p); + ++p; + break; + default: + fprintf(stderr, "opcode $%02x (snd_note)\n", *p); + Update_pokey_sound(audf1, *p); + play_frames(*++p); + ++p; + break; + } + } +} + +void sdl_audio_callback(void *userdata, Uint8* stream, int len) { + Pokey_process(stream, len); +} + +void init_sdl_audio(void) { + SDL_AudioSpec want, have; + SDL_AudioDeviceID dev; + + if(SDL_Init(SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + exit(-1); + } + atexit(SDL_Quit); + + SDL_memset(&want, 0, sizeof(want)); + want.freq = FREQ; + want.format = AUDIO_U8; + want.channels = 1; + want.samples = buf_size; + want.callback = sdl_audio_callback; + + dev = SDL_OpenAudioDevice(0, 0, &want, &have, 0); + if(!dev) { + fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError()); + exit(-1); + } + + SDL_PauseAudioDevice(dev, 0); +} + +int main(int argc, char **argv) { + int addr; + + if(argc < 2 || argc > 3) usage(); + + if(argc == 3) { + buf_size = PAL_BUF_SIZE; + delay = PAL_DELAY; + addr = (int)strtol(argv[2], 0, 16); + } else { + addr = (int)strtol(argv[1], 0, 16); + } + + if(addr < 0x8000 || addr > 0xbfff) { + fprintf(stderr, "invalid address, must be 0x8fff thru 0xbfff\n"); + usage(); + } + + load_rom(); + + fprintf(stderr, "playing sfx at $%04x, buf_size %d\n", addr, buf_size); + + Pokey_sound_init(FREQ_17_APPROX, FREQ); + init_sdl_audio(); + play_sfx(addr); + + return(0); +} diff --git a/pokeytest/playsnd.c b/pokeytest/playsnd.c new file mode 100644 index 0000000..0f76879 --- /dev/null +++ b/pokeytest/playsnd.c @@ -0,0 +1,114 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "pokey.h" + +#define ROM_FILE "../jumpmanjr.rom" +#define ROM_SIZE 0x4000 + +#define PAL_BUF_SIZE 882 +#define NTSC_BUF_SIZE 735 + +unsigned char sndbuf[PAL_BUF_SIZE + 1]; + +unsigned char rom[ROM_SIZE]; + +void usage(void) { + fprintf(stderr, "usage: playsnd [-p] 0xaddr\n"); + exit(1); +} + +void load_rom(void) { + int size; + FILE *f; + + f = fopen(ROM_FILE, "rb"); + if(!f) { + perror(ROM_FILE); + usage(); + } + + size = fread(rom, 1, ROM_SIZE, f); + if(size != ROM_SIZE) { + fprintf(stderr, "file %s should be %d bytes long, not %d\n", + ROM_FILE, ROM_SIZE, size); + usage(); + } + + fprintf(stderr, "loaded ROM %s, %d bytes\n", ROM_FILE, size); +} + +void play_frames(unsigned char count, int buf_size) { + fprintf(stderr, "playing for %d frames\n", count); + while(count--) { + Pokey_process(sndbuf, buf_size); + fwrite(sndbuf, buf_size, 1, stdout); + } +} + +void play_sfx(int addr, int buf_size) { + unsigned char *p = rom + (addr - 0x8000); + + while(1) { + fprintf(stderr, "$%04lx: $%02x\n", (p - rom + 0x8000), *p); + switch(*p) { + case 0: + fprintf(stderr, "opcode 0 (snd_end)\n"); + return; + case 1: + fprintf(stderr, "opcode 1 (snd_audc)\n"); + Update_pokey_sound(audc1, *++p); + play_frames(*++p, buf_size); + ++p; + break; + case 2: + fprintf(stderr, "opcode 2 (snd_jump)\n"); + addr = *++p; + addr |= ( (*++p) << 8); + addr -= 0x8000; + p = rom + addr; + break; + case 3: + fprintf(stderr, "opcode 3 (snd_rest)\n"); + Update_pokey_sound(audc1, 0); + play_frames(*++p, buf_size); + ++p; + break; + default: + fprintf(stderr, "opcode $%02x (snd_note)\n", *p); + Update_pokey_sound(audf1, *p); + play_frames(*++p, buf_size); + ++p; + break; + } + } +} + +int main(int argc, char **argv) { + int buf_size = NTSC_BUF_SIZE; + int addr; + + if(argc < 2 || argc > 3) usage(); + + if(argc == 3) { + buf_size = PAL_BUF_SIZE; + addr = (int)strtol(argv[2], 0, 0); + } else { + addr = (int)strtol(argv[1], 0, 0); + } + + if(addr < 0x8000 || addr > 0xbfff) { + fprintf(stderr, "invalid address, must be 0x8fff thru 0xbfff\n"); + usage(); + } + + load_rom(); + + fprintf(stderr, "playing sfx at $%04x, buf_size %d\n", addr, buf_size); + + Pokey_sound_init(FREQ_17_APPROX, 44100); + play_sfx(addr, buf_size); + + return(0); +} + diff --git a/pokeytest/pokey.c b/pokeytest/pokey.c new file mode 100644 index 0000000..11a51af --- /dev/null +++ b/pokeytest/pokey.c @@ -0,0 +1,764 @@ +/*****************************************************************************/ +/* */ +/* Module: POKEY Chip Simulator, V1.1 */ +/* Purpose: To emulate the sound generation hardware of the Atari POKEY chip.*/ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/*****************************************************************************/ +/* */ +/* License Information and Copyright Notice */ +/* ======================================== */ +/* */ +/* PokeySound is Copyright(c) 1996 by Ron Fries */ +/* */ +/* This library is free software; you can redistribute it and/or modify it */ +/* under the terms of version 2 of the GNU Library General Public License */ +/* as published by the Free Software Foundation. */ +/* */ +/* This library is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ +/* General Public License for more details. */ +/* To obtain a copy of the GNU Library General Public License, write to the */ +/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* */ +/* Any permitted reproduction of these routines, in whole or in part, must */ +/* bear this legend. */ +/* */ +/*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "pokey.h" + +/* CONSTANT DEFINITIONS */ + +/* definitions for AUDCx (D201, D203, D205, D207) */ +#define NOTPOLY5 0x80 /* selects POLY5 or direct CLOCK */ +#define POLY4 0x40 /* selects POLY4 or POLY17 */ +#define PURE 0x20 /* selects POLY4/17 or PURE tone */ +#define VOL_ONLY 0x10 /* selects VOLUME OUTPUT ONLY */ +#define VOLUME_MASK 0x0f /* volume mask */ + +/* definitions for AUDCTL (D208) */ +#define POLY9 0x80 /* selects POLY9 or POLY17 */ +#define CH1_179 0x40 /* selects 1.78979 MHz for Ch 1 */ +#define CH3_179 0x20 /* selects 1.78979 MHz for Ch 3 */ +#define CH1_CH2 0x10 /* clocks channel 1 w/channel 2 */ +#define CH3_CH4 0x08 /* clocks channel 3 w/channel 4 */ +#define CH1_FILTER 0x04 /* selects channel 1 high pass filter */ +#define CH2_FILTER 0x02 /* selects channel 2 high pass filter */ +#define CLOCK_15 0x01 /* selects 15.6999kHz or 63.9210kHz */ + +#define AUDF1_C 0xd200 +#define AUDC1_C 0xd201 +#define AUDF2_C 0xd202 +#define AUDC2_C 0xd203 +#define AUDF3_C 0xd204 +#define AUDC3_C 0xd205 +#define AUDF4_C 0xd206 +#define AUDC4_C 0xd207 +#define AUDCTL_C 0xd208 + +/* for accuracy, the 64kHz and 15kHz clocks are exact divisions of + the 1.79MHz clock */ +#define DIV_64 28 /* divisor for 1.79MHz clock to 64 kHz */ +#define DIV_15 114 /* divisor for 1.79MHz clock to 15 kHz */ + +/* the size (in entries) of the 4 polynomial tables */ +#define POLY4_SIZE 0x000f +#define POLY5_SIZE 0x001f +#define POLY9_SIZE 0x01ff + +#ifdef COMP16 /* if 16-bit compiler */ +#define POLY17_SIZE 0x00007fffL /* reduced to 15 bits for simplicity */ +#else +#define POLY17_SIZE 0x0001ffffL /* else use the full 17 bits */ +#endif + +/* channel definitions */ +#define CHAN1 0 +#define CHAN2 1 +#define CHAN3 2 +#define CHAN4 3 +#define SAMPLE 4 + + +#define FALSE 0 +#define TRUE 1 + + +/* GLOBAL VARIABLE DEFINITIONS */ + +/* structures to hold the 9 pokey control bytes */ +static uint8 AUDF[4]; /* AUDFx (D200, D202, D204, D206) */ +static uint8 AUDC[4]; /* AUDCx (D201, D203, D205, D207) */ +static uint8 AUDCTL; /* AUDCTL (D208) */ + +static uint8 Outbit[4]; /* current state of the output (high or low) */ + +static uint8 Outvol[4]; /* last output volume for each channel */ + + +/* Initialze the bit patterns for the polynomials. */ + +/* The 4bit and 5bit patterns are the identical ones used in the pokey chip. */ +/* Though the patterns could be packed with 8 bits per byte, using only a */ +/* single bit per byte keeps the math simple, which is important for */ +/* efficient processing. */ + +static uint8 bit4[POLY4_SIZE] = + { 1,1,0,1,1,1,0,0,0,0,1,0,1,0,0 }; + +static uint8 bit5[POLY5_SIZE] = + { 0,0,1,1,0,0,0,1,1,1,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1,0,0,0,0,0,1 }; + +static uint8 bit17[POLY17_SIZE]; /* Rather than have a table with 131071 */ + /* entries, I use a random number generator. */ + /* It shouldn't make much difference since */ + /* the pattern rarely repeats anyway. */ + +static uint32 Poly17_size; /* global for the poly 17 size, since it can */ + /* be changed from 17 bit to 9 bit */ + +static uint32 Poly_adjust; /* the amount that the polynomial will need */ + /* to be adjusted to process the next bit */ + +static uint32 P4=0, /* Global position pointer for the 4-bit POLY array */ + P5=0, /* Global position pointer for the 5-bit POLY array */ + P17=0; /* Global position pointer for the 17-bit POLY array */ + +static uint32 Div_n_cnt[4], /* Divide by n counter. one for each channel */ + Div_n_max[4]; /* Divide by n maximum, one for each channel */ + +static uint32 Samp_n_max, /* Sample max. For accuracy, it is *256 */ + Samp_n_cnt[2]; /* Sample cnt. */ + +static uint32 Base_mult; /* selects either 64Khz or 15Khz clock mult */ + +/*****************************************************************************/ +/* In my routines, I treat the sample output as another divide by N counter */ +/* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */ +/* which has 8 binary digits to the right of the decimal point. I use a two */ +/* byte array to give me a minimum of 40 bits, and then use pointer math to */ +/* reference either the 24.8 whole/fraction combination or the 32-bit whole */ +/* only number. This is mainly used to keep the math simple for */ +/* optimization. See below: */ +/* */ +/* xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | xxxxxxxx xxxxxxxx xxxxxxxx.xxxxxxxx */ +/* unused unused unused whole whole whole whole fraction */ +/* */ +/* Samp_n_cnt[0] gives me a 32-bit int 24 whole bits with 8 fractional bits, */ +/* while (uint32 *)((uint8 *)(&Samp_n_cnt[0])+1) gives me the 32-bit whole */ +/* number only. */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* Module: Pokey_sound_init() */ +/* Purpose: to handle the power-up initialization functions */ +/* these functions should only be executed on a cold-restart */ +/* */ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/* Inputs: freq17 - the value for the '1.79MHz' Pokey audio clock */ +/* playback_freq - the playback frequency in samples per second */ +/* */ +/* Outputs: Adjusts local globals - no return value */ +/* */ +/*****************************************************************************/ + +void Pokey_sound_init (uint32 freq17, uint16 playback_freq) +{ + uint8 chan; + int32 n; + + /* fill the 17bit polynomial with random bits */ + for (n=0; n<POLY17_SIZE; n++) + { + bit17[n] = rand() & 0x01; /* fill poly 17 with random bits */ + } + + /* start all of the polynomial counters at zero */ + Poly_adjust = 0; + P4 = 0; + P5 = 0; + P17 = 0; + + /* calculate the sample 'divide by N' value based on the playback freq. */ + Samp_n_max = ((uint32)freq17 << 8) / playback_freq; + + Samp_n_cnt[0] = 0; /* initialize all bits of the sample */ + Samp_n_cnt[1] = 0; /* 'divide by N' counter */ + + Poly17_size = POLY17_SIZE; + + for (chan = CHAN1; chan <= CHAN4; chan++) + { + Outvol[chan] = 0; + Outbit[chan] = 0; + Div_n_cnt[chan] = 0; + Div_n_max[chan] = 0x7fffffffL; + AUDC[chan] = 0; + AUDF[chan] = 0; + } + + AUDCTL = 0; + + Base_mult = DIV_64; +} + + +/*****************************************************************************/ +/* Module: Update_pokey_sound() */ +/* Purpose: To process the latest control values stored in the AUDF, AUDC, */ +/* and AUDCTL registers. It pre-calculates as much information as */ +/* possible for better performance. This routine has not been */ +/* optimized. */ +/* */ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/* Inputs: addr - the address of the parameter to be changed */ +/* val - the new value to be placed in the specified address */ +/* */ +/* Outputs: Adjusts local globals - no return value */ +/* */ +/*****************************************************************************/ + +void Update_pokey_sound (uint16 addr, uint8 val) +{ + uint32 new_val = 0; + uint8 chan; + uint8 chan_mask; + + /* determine which address was changed */ + switch (addr) + { + case AUDF1_C: + AUDF[CHAN1] = val; + chan_mask = 1 << CHAN1; + + if (AUDCTL & CH1_CH2) /* if ch 1&2 tied together */ + chan_mask |= 1 << CHAN2; /* then also change on ch2 */ + break; + + case AUDC1_C: + AUDC[CHAN1] = val; + chan_mask = 1 << CHAN1; + break; + + case AUDF2_C: + AUDF[CHAN2] = val; + chan_mask = 1 << CHAN2; + break; + + case AUDC2_C: + AUDC[CHAN2] = val; + chan_mask = 1 << CHAN2; + break; + + case AUDF3_C: + AUDF[CHAN3] = val; + chan_mask = 1 << CHAN3; + + if (AUDCTL & CH3_CH4) /* if ch 3&4 tied together */ + chan_mask |= 1 << CHAN4; /* then also change on ch4 */ + break; + + case AUDC3_C: + AUDC[CHAN3] = val; + chan_mask = 1 << CHAN3; + break; + + case AUDF4_C: + AUDF[CHAN4] = val; + chan_mask = 1 << CHAN4; + break; + + case AUDC4_C: + AUDC[CHAN4] = val; + chan_mask = 1 << CHAN4; + break; + + case AUDCTL_C: + AUDCTL = val; + chan_mask = 15; /* all channels */ + + /* set poly17 counter to 9- or 17-bit */ + if (AUDCTL & POLY9) + Poly17_size = POLY9_SIZE; + else + Poly17_size = POLY17_SIZE; + + /* determine the base multiplier for the 'div by n' calculations */ + if (AUDCTL & CLOCK_15) + Base_mult = DIV_15; + else + Base_mult = DIV_64; + + break; + + default: + chan_mask = 0; + break; + } + + /************************************************************/ + /* As defined in the manual, the exact Div_n_cnt values are */ + /* different depending on the frequency and resolution: */ + /* 64 kHz or 15 kHz - AUDF + 1 */ + /* 1 MHz, 8-bit - AUDF + 4 */ + /* 1 MHz, 16-bit - AUDF[CHAN1]+256*AUDF[CHAN2] + 7 */ + /************************************************************/ + + /* only reset the channels that have changed */ + + if (chan_mask & (1 << CHAN1)) + { + /* process channel 1 frequency */ + if (AUDCTL & CH1_179) + new_val = AUDF[CHAN1] + 4; + else + new_val = (AUDF[CHAN1] + 1) * Base_mult; + + if (new_val != Div_n_max[CHAN1]) + { + Div_n_max[CHAN1] = new_val; + Div_n_cnt[CHAN1] = 0; + } + } + + if (chan_mask & (1 << CHAN2)) + { + /* process channel 2 frequency */ + if (AUDCTL & CH1_CH2) + if (AUDCTL & CH1_179) + new_val = AUDF[CHAN2] * 256 + AUDF[CHAN1] + 7; + else + new_val = (AUDF[CHAN2] * 256 + AUDF[CHAN1] + 1) * Base_mult; + else + new_val = (AUDF[CHAN2] + 1) * Base_mult; + + if (new_val != Div_n_max[CHAN2]) + { + Div_n_max[CHAN2] = new_val; + Div_n_cnt[CHAN2] = 0; + } + } + + if (chan_mask & (1 << CHAN3)) + { + /* process channel 3 frequency */ + if (AUDCTL & CH3_179) + new_val = AUDF[CHAN3] + 4; + else + new_val= (AUDF[CHAN3] + 1) * Base_mult; + + if (new_val!= Div_n_max[CHAN3]) + { + Div_n_max[CHAN3] = new_val; + Div_n_cnt[CHAN3] = 0; + } + } + + if (chan_mask & (1 << CHAN4)) + { + /* process channel 4 frequency */ + if (AUDCTL & CH3_CH4) + if (AUDCTL & CH3_179) + new_val = AUDF[CHAN4] * 256 + AUDF[CHAN3] + 7; + else + new_val = (AUDF[CHAN4] * 256 + AUDF[CHAN3] + 1) * Base_mult; + else + new_val = (AUDF[CHAN4] + 1) * Base_mult; + + if (new_val != Div_n_max[CHAN4]) + { + Div_n_max[CHAN4] = new_val; + Div_n_cnt[CHAN4] = 0; + } + } + + /* if channel is volume only, set current output */ + for (chan = CHAN1; chan <= CHAN4; chan++) + { + if (chan_mask & (1 << chan)) + { + /* I've disabled any frequencies that exceed the sampling + frequency. There isn't much point in processing frequencies + that the hardware can't reproduce. I've also disabled + processing if the volume is zero. */ + + /* if the channel is volume only */ + /* or the channel is off (volume == 0) */ + /* or the channel freq is greater than the playback freq */ + if ((AUDC[chan] & VOL_ONLY) || + ((AUDC[chan] & VOLUME_MASK) == 0) || + (Div_n_max[chan] < (Samp_n_max >> 8))) + { + /* then set the channel to the selected volume */ + Outvol[chan] = AUDC[chan] & VOLUME_MASK; + /* and set channel freq to max to reduce processing */ + Div_n_max[chan] = 0x7fffffffL; + } + } + } +} + + +/*****************************************************************************/ +/* Module: Pokey_process_2() */ +/* Purpose: To fill the output buffer with the sound output based on the */ +/* pokey chip parameters. This routine has not been optimized. */ +/* Though it is not used by the program, I've left it for reference.*/ +/* */ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/* Inputs: *buffer - pointer to the buffer where the audio output will */ +/* be placed */ +/* n - size of the playback buffer */ +/* */ +/* Outputs: the buffer will be filled with n bytes of audio - no return val */ +/* */ +/*****************************************************************************/ + +void Pokey_process_2 (register unsigned char *buffer, register uint16 n) +{ + register uint32 *samp_cnt_w_ptr; + register uint32 event_min; + register uint8 next_event; + register uint8 cur_val; + register uint8 chan; + + /* set a pointer to the whole portion of the samp_n_cnt */ + samp_cnt_w_ptr = (uint32 *)((uint8 *)(&Samp_n_cnt[0])+1); + + /* loop until the buffer is filled */ + while (n) + { + /* Normally the routine would simply decrement the 'div by N' */ + /* counters and react when they reach zero. Since we normally */ + /* won't be processing except once every 80 or so counts, */ + /* I've optimized by finding the smallest count and then */ + /* 'accelerated' time by adjusting all pointers by that amount. */ + + /* find next smallest event (either sample or chan 1-4) */ + next_event = SAMPLE; + event_min = *samp_cnt_w_ptr; + + for (chan = CHAN1; chan <= CHAN4; chan++) + { + if (Div_n_cnt[chan] <= event_min) + { + event_min = Div_n_cnt[chan]; + next_event = chan; + } + } + + + /* decrement all counters by the smallest count found */ + for (chan = CHAN1; chan <= CHAN4; chan++) + { + Div_n_cnt[chan] -= event_min; + } + + *samp_cnt_w_ptr -= event_min; + + /* since the polynomials require a mod (%) function which is + division, I don't adjust the polynomials on the SAMPLE events, + only the CHAN events. I have to keep track of the change, + though. */ + Poly_adjust += event_min; + + /* if the next event is a channel change */ + if (next_event != SAMPLE) + { + /* shift the polynomial counters */ + P4 = (P4 + Poly_adjust) % POLY4_SIZE; + P5 = (P5 + Poly_adjust) % POLY5_SIZE; + P17 = (P17 + Poly_adjust) % Poly17_size; + + /* reset the polynomial adjust counter to zero */ + Poly_adjust = 0; + + /* adjust channel counter */ + Div_n_cnt[next_event] += Div_n_max[next_event]; + + /* From here, a good understanding of the hardware is required */ + /* to understand what is happening. I won't be able to provide */ + /* much description to explain it here. */ + + /* if the output is pure or the output is poly5 and the poly5 bit */ + /* is set */ + if ((AUDC[next_event] & NOTPOLY5) || bit5[P5]) + { + /* if the PURE bit is set */ + if (AUDC[next_event] & PURE) + { + /* then simply toggle the output */ + Outbit[next_event] = !Outbit[next_event]; + } + /* otherwise if POLY4 is selected */ + else if (AUDC[next_event] & POLY4) + { + /* then use the poly4 bit */ + Outbit[next_event] = bit4[P4]; + } + else + { + /* otherwise use the poly17 bit */ + Outbit[next_event] = bit17[P17]; + } + } + + /* At this point I haven't emulated the filters. Though I don't + expect it to be complicated, I don't believe this feature is + used much anyway. I'll work on it later. */ + if ((next_event == CHAN1) || (next_event == CHAN3)) + { + /* INSERT FILTER HERE */ + } + + /* if the current output bit is set */ + if (Outbit[next_event]) + { + /* then set to the current volume */ + Outvol[next_event] = AUDC[next_event] & VOLUME_MASK; + } + else + { + /* set the volume to zero */ + Outvol[next_event] = 0; + } + } + else /* otherwise we're processing a sample */ + { + /* adjust the sample counter - note we're using the 24.8 integer + which includes an 8 bit fraction for accuracy */ + *Samp_n_cnt += Samp_n_max; + + cur_val = 0; + + /* add the output values of all 4 channels */ + for (chan = CHAN1; chan <= CHAN4; chan++) + { + cur_val += Outvol[chan]; + } + + /* multiply the volume by 4 and add 8 to center around 128 */ + /* NOTE: this statement could be eliminated for efficiency, */ + /* though the volume would be lower. */ + cur_val = (cur_val << 2) + 8; + + /* add the current value to the output buffer */ + *buffer++ = cur_val; + + /* and indicate one less byte in the buffer */ + n--; + } + } +} + + +/*****************************************************************************/ +/* Module: Pokey_process() */ +/* Purpose: To fill the output buffer with the sound output based on the */ +/* pokey chip parameters. This routine has not been optimized. */ +/* Though it is not used by the program, I've left it for reference.*/ +/* */ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/* Inputs: *buffer - pointer to the buffer where the audio output will */ +/* be placed */ +/* n - size of the playback buffer */ +/* */ +/* Outputs: the buffer will be filled with n bytes of audio - no return val */ +/* */ +/*****************************************************************************/ + +void Pokey_process (register unsigned char *buffer, register uint16 n) +{ + register uint32 *div_n_ptr; + register uint32 *samp_cnt_w_ptr; + register uint32 event_min; + register uint8 next_event; + register uint8 cur_val; + register uint8 *out_ptr; + register uint8 audc; + register uint8 toggle; + + + /* set a pointer to the whole portion of the samp_n_cnt */ + samp_cnt_w_ptr = (uint32 *)((uint8 *)(&Samp_n_cnt[0])+1); + + /* set a pointer for optimization */ + out_ptr = Outvol; + + /* The current output is pre-determined and then adjusted based on each */ + /* output change for increased performance (less over-all math). */ + /* add the output values of all 4 channels */ + cur_val = 2; /* start with a small offset */ + cur_val += *out_ptr++; + cur_val += *out_ptr++; + cur_val += *out_ptr++; + cur_val += *out_ptr++; + + /* loop until the buffer is filled */ + while (n) + { + /* Normally the routine would simply decrement the 'div by N' */ + /* counters and react when they reach zero. Since we normally */ + /* won't be processing except once every 80 or so counts, */ + /* I've optimized by finding the smallest count and then */ + /* 'accelerated' time by adjusting all pointers by that amount. */ + + /* find next smallest event (either sample or chan 1-4) */ + next_event = SAMPLE; + event_min = *samp_cnt_w_ptr; + + /* Though I could have used a loop here, this is faster */ + div_n_ptr = Div_n_cnt; + if (*div_n_ptr <= event_min) + { + event_min = *div_n_ptr; + next_event = CHAN1; + } + div_n_ptr++; + if (*div_n_ptr <= event_min) + { + event_min = *div_n_ptr; + next_event = CHAN2; + } + div_n_ptr++; + if (*div_n_ptr <= event_min) + { + event_min = *div_n_ptr; + next_event = CHAN3; + } + div_n_ptr++; + if (*div_n_ptr <= event_min) + { + event_min = *div_n_ptr; + next_event = CHAN4; + } + + /* decrement all counters by the smallest count found */ + /* again, no loop for efficiency */ + *div_n_ptr -= event_min; + div_n_ptr--; + *div_n_ptr -= event_min; + div_n_ptr--; + *div_n_ptr -= event_min; + div_n_ptr--; + *div_n_ptr -= event_min; + + *samp_cnt_w_ptr -= event_min; + + /* since the polynomials require a mod (%) function which is + division, I don't adjust the polynomials on the SAMPLE events, + only the CHAN events. I have to keep track of the change, + though. */ + Poly_adjust += event_min; + + /* if the next event is a channel change */ + if (next_event != SAMPLE) + { + /* shift the polynomial counters */ + P4 = (P4 + Poly_adjust) % POLY4_SIZE; + P5 = (P5 + Poly_adjust) % POLY5_SIZE; + P17 = (P17 + Poly_adjust) % Poly17_size; + + /* reset the polynomial adjust counter to zero */ + Poly_adjust = 0; + + /* adjust channel counter */ + Div_n_cnt[next_event] += Div_n_max[next_event]; + + /* get the current AUDC into a register (for optimization) */ + audc = AUDC[next_event]; + + /* set a pointer to the current output (for opt...) */ + out_ptr = &Outvol[next_event]; + + /* assume no changes to the output */ + toggle = FALSE; + + /* From here, a good understanding of the hardware is required */ + /* to understand what is happening. I won't be able to provide */ + /* much description to explain it here. */ + + /* if the output is pure or the output is poly5 and the poly5 bit */ + /* is set */ + if ((audc & NOTPOLY5) || bit5[P5]) + { + /* if the PURE bit is set */ + if (audc & PURE) + { + /* then simply toggle the output */ + toggle = TRUE; + } + /* otherwise if POLY4 is selected */ + else if (audc & POLY4) + { + /* then compare to the poly4 bit */ + toggle = (bit4[P4] == !(*out_ptr)); + } + else + { + /* otherwise compare to the poly17 bit */ + toggle = (bit17[P17] == !(*out_ptr)); + } + } + + /* At this point I haven't emulated the filters. Though I don't + expect it to be complicated, I don't believe this feature is + used much anyway. I'll work on it later. */ + if ((next_event == CHAN1) || (next_event == CHAN3)) + { + /* INSERT FILTER HERE */ + } + + /* if the current output bit has changed */ + if (toggle) + { + if (*out_ptr) + { + /* remove this channel from the signal */ + cur_val -= *out_ptr; + + /* and turn the output off */ + *out_ptr = 0; + } + else + { + /* turn the output on */ + *out_ptr = audc & VOLUME_MASK; + + /* and add it to the output signal */ + cur_val += *out_ptr; + } + } + } + else /* otherwise we're processing a sample */ + { + /* adjust the sample counter - note we're using the 24.8 integer + which includes an 8 bit fraction for accuracy */ + *Samp_n_cnt += Samp_n_max; + + /* add the current value to the output buffer */ + *buffer++ = cur_val << 2; + + /* and indicate one less byte in the buffer */ + n--; + } + } +} + + diff --git a/pokeytest/pokey.h b/pokeytest/pokey.h new file mode 100644 index 0000000..ee2c6e3 --- /dev/null +++ b/pokeytest/pokey.h @@ -0,0 +1,77 @@ +/*****************************************************************************/ +/* */ +/* Module: POKEY Chip Simulator Includes, V1.1 */ +/* Purpose: To emulate the sound generation hardware of the Atari POKEY chip.*/ +/* Author: Ron Fries */ +/* Date: September 22, 1996 */ +/* */ +/*****************************************************************************/ +/* */ +/* License Information and Copyright Notice */ +/* ======================================== */ +/* */ +/* PokeySound is Copyright(c) 1996 by Ron Fries */ +/* */ +/* This library is free software; you can redistribute it and/or modify it */ +/* under the terms of version 2 of the GNU Library General Public License */ +/* as published by the Free Software Foundation. */ +/* */ +/* This library is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ +/* General Public License for more details. */ +/* To obtain a copy of the GNU Library General Public License, write to the */ +/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* */ +/* Any permitted reproduction of these routines, in whole or in part, must */ +/* bear this legend. */ +/* */ +/*****************************************************************************/ + +#ifndef _POKEYSOUND_H +#define _POKEYSOUND_H + +#include <stdint.h> + +#define int8 int8_t +#define int16 int16_t +#define int32 int32_t +#define uint8 uint8_t +#define uint16 uint16_t +#define uint32 uint32_t + +#define audf1 (0xd200 + 0x00) +#define audc1 (0xd200 + 0x01) +#define audf2 (0xd200 + 0x02) +#define audc2 (0xd200 + 0x03) +#define audf3 (0xd200 + 0x04) +#define audc3 (0xd200 + 0x05) +#define audf4 (0xd200 + 0x06) +#define audc4 (0xd200 + 0x07) +#define audctl (0xd200 + 0x08) + +/* CONSTANT DEFINITIONS */ + +/* As an alternative to using the exact frequencies, selecting a playback + frequency that is an exact division of the main clock provides a higher + quality output due to less aliasing. For best results, a value of + 1787520 MHz is used for the main clock. With this value, both the + 64 kHz and 15 kHz clocks are evenly divisible. Selecting a playback + frequency that is also a division of the clock provides the best + results. The best options are FREQ_64 divided by either 2, 3, or 4. + The best selection is based on a trade off between performance and + sound quality. + + Of course, using a main clock frequency that is not exact will affect + the pitch of the output. With these numbers, the pitch will be low + by 0.127%. (More than likely, an actual unit will vary by this much!) */ + +#define FREQ_17_EXACT 1789790 /* exact 1.79 MHz clock freq */ +#define FREQ_17_APPROX 1787520 /* approximate 1.79 MHz clock freq */ + +void Pokey_sound_init (uint32 freq17, uint16 playback_freq); +void Update_pokey_sound (uint16 addr, uint8 val); +void Pokey_process_2 (register unsigned char *buffer, register uint16 n); +void Pokey_process (register unsigned char *buffer, register uint16 n); + +#endif diff --git a/pokeytest/pokey11.txt b/pokeytest/pokey11.txt new file mode 100644 index 0000000..498d768 --- /dev/null +++ b/pokeytest/pokey11.txt @@ -0,0 +1,277 @@ + Atari POKEY Chip Simulator V1.1 + =============================== + by Ron Fries + 23 Sep 96 + +The POKEY Chip Simulator is designed to emulate the functionality of the +Atari POKEY Chip Hardware through 'C' Sourcecode. I have seen very good +results. The simulator is able to produce sounds which are essentially +identical to the original Atari, including the exact distortions and +pitches. + +The simulator is designed to run in a 32-bit environment. Though it can +compiled and run in a 16-bit environment, it is slow. + + +Features: +--------- + +Version 1.1 of the 'POKEY' simulator supports the following functions: + +1) All polynomial sound generators: + a) 4-bit poly - actual bit pattern determined from sampled sound + b) 5-bit poly - actual bit pattern determined from sampled sound + c) 17-bit poly - simulated random bit pattern + d) 9-bit poly - derived from simulated 17-bit poly + +2) Full support of all 'Divide by N' counter clocks: + a) 1.79 MHz (high limited to playback sample rate) + b) 64 KHz (high limited to playback sample rate) + c) 15 KHz + +3) Full support of all 'Divide by N' resolutions: + a) 8-bit - single channel + b) 16-bit - double channel + +4) Full support of all distortions + a) 5-bit poly, then 17-bit poly + b) 5-bit poly only + c) 5-bit poly, then 4-bit poly + d) 17-bit poly only + e) no poly counters (pure tone) + f) 5-bit poly only + +5) Full support of volume control + +6) Full support of all pitches - distortions will vary exactly as the + original Atari based on different pitches + +7) Accurate pitch generation + +8) Support of any playback sample rate (e.g. 22050) + + +The 'POKEY' simulator does not currently support the following functions: + +1) High pass filters + + +Though I don't believe adding support for the High-Pass filters is very +complicated, I decided not to add support right now because I don't +believe this feature is used much. I'm also not sure how much impact it +would have on performance. + +You'll notice in the code there are two separate versions. The original +process function, now called Pokey_process_2(), is the non-optimized +version. I've left it in for reference. The other function, +Pokey_process(), is optimized. In my tests using the 'Maximize Speed' +option of the compiler, I've seen very good performance. On my 486DX2-66, +it typically takes about 0.15 seconds to produce about 3 seconds of audio. +These times were calculated under WIN95. + +One of the unique features of the optimized version is that the processing +time will vary based on the frequency. Since the routine only calculates +new output values when a change is sensed, the lower frequencies (which +change less frequently) will require less processing time. + + +Differences Between the Simulator and the Actual POKEY Chip: +------------------------------------------------------------ + +The biggest difference between the simulator and the original hardware is +that the simulator emulates an 'ideal' POKEY chip. All output from the +simulator is a based on a precise square wave, whereas the output from the +original chip has decay. Though the output is slightly different, I +don't believe this difference is easily discernible. + +Another slight difference is the 17-bit/9-bit poly. Since the polynomial +is large (2^17 bits), I choose to create the sample using a random number +generator rather than a table. I don't believe this difference is +significant. + +There are also a few differences which are introduced by aliasing. This is +a direct result of using an output sampling rate which is not identical to +the original sound rate. It is most evident with high frequencies. + +A final difference is the lack of support for the High-Pass Filter +functionality. I plan to add this in a future release if necessary. + + +Sample/Test Application: +------------------------ + +The test program I've distributed is a 16-bit DOS application created with +the Borland 'C' compiler. The only reason I used 16-bit was because I +already had a set of working SB drivers in 16-bit. Since the test system +is dedicated to generating sounds, the performance in 16-bit is more than +adequate. + + +POKEY11.C +========== + +The POKEY11.C file is the heart of the POKEY Sound Emulation program. +Although the routines in the file must work together, no other files are +modules are required for operation. A header file, 'POKEY11.H', has +been included for use in other modules, and provides the necessary +function prototypes. I've attempted to make the routines as portable as +possible, so the file should compile on almost any compiler with little +or no modification. + +I have made some attempts at optimizing the routines, though I am sure +more optimization can be done. They are currently only available in 'C'. +I'll be happy to convert them to assembly language if desired. Please feel +free to send me e-mail at rfries@tcmail.frco.com. + +The routines are easy to use. Detailed descriptions on the function calls +are listed below. + +The POKEY11.C module can be compiled in a 32-bit or 16-bit environment. +Since these routines are optimized for 32-bit use, the code will default +to 32-bit. To compile in 16-bits, use a command line option to define +the variable COMP16. + + +GENERAL OVERVIEW +---------------- + +On start-up of the system, a single call should be made to Pokey_sound_init. +This routine will prepare the structures for sound output. This routine +can be called again if necessary during warm-start or other reset. + +Once in the main loop, there are two other functions that will be used. +Whenever the system needs to write to either the AUDC or AUDF values, +a call should be made to the Update_pokey_sound routine. This routine will +take care of updating the internal registers. It will pre-calculate several +values to help with optimization. + +The only other routine that is called is the Pokey_process function. This +function will fill a audio buffer with a specified number of bytes. This +function should be called whenever a new audio buffer is required. + +For best results, I recommend using at least two output buffers. Using this +scheme, the sound card can be playing one buffer while the system is filling +the other. + + +DETAILED FUNCTION DESCRIPTIONS +------------------------------ + +Pokey_sound_init(uint32 freq17, uint16 playback_freq) +-------------------------------------------------------- + +This function initializes the structures used by the PokeySound routines. +This function takes two parameters: the main clock frequency and the +playback frequency. + +The main clock frequency is the frequency of the 1.79MHz source clock. +To provide exact results, freq17 should be set equal to 1789790 Hz. As an +alternative, freq17 can be set to an approximate frequency of 1787520 Hz. +Using this approximate frequency will reduce aliasing and thus produce a +clearer output signal. + +A constant has been defined for both of these values for your convenience. +The names are FREQ_17_EXACT and FREQ_17_APPROX. + +The playback frequency is the frequency of the sound playback (the frequency +used by the sound card). For best results, the playback frequency should +be an even division of the main clock frequency. Since most of the sounds +will be generated using the 64kHz clock, I also recommend making the +playback frequency an even division of the 64kHz clock. + +The 64kHz clock is exactly equal to the main clock divided by 28. For +the playback frequency, I recommend one of the following values: + +1) FREQ_17_APPROX / (28*1), which is equal to 63840. Of course, most sound + cards can't reproduce this frequency. + +2) FREQ_17_APPROX / (28*2), which is equal to 31920. All of the newer cards + will support this frequency. + +3) FREQ_17_APPROX / (28*3), which is equal to 21280. All of the SB + compatibles should support this frequency. + +4) FREQ_17_APPROX / (28*4), which is equal to 15960. This may be the + best choice, as it offers good sound reproduction with good performance. + +Of course, these options also assume you are using the approximate +frequency for the main clock as well. Any of these choices will offer the +best results when the main 64kHz clock is used, reasonable results when the +15kHz clock is selected, and marginal results when the 1.79MHz clock is +selected (the only way to produce good results in all cases is to set the +playback frequency to 1.79MHz!) + +Feel free to experiment to find other alternatives as well. + +This function has no return value (void). + + +Update_pokey_sound (uint16 addr, uint8 val) +----------------------------------------- + +This function should be called each time an AUDC, AUDF or AUDCTL value +changes. This function takes two parameters: the address to change and +the new value. The address should be one of the following values: + + Addr Description + ------ ----------- + 0xd200 AUDF1 + 0xd201 AUDC1 + 0xd202 AUDF2 + 0xd203 AUDC2 + 0xd204 AUDF3 + 0xd205 AUDC3 + 0xd206 AUDF4 + 0xd207 AUDC4 + 0xd208 AUDCTL + +Any values outside of this range will be ignored. + +The routine pre-calculates several values that are needed by the +processing function. This is done to optimize performance. + +This function has no return value (void). + + +Pokey_process (unsigned char *buffer, uint16 n) +--------------------------------------------- + +This function calculates and fills a buffer with unsigned 8-bit mono audio. +This function takes two parameters: a pointer to the buffer to fill and +the size of the buffer (limited to 65535). This function fills the +buffer based on the requested size and returns. It automatically +updates the pointers for the next call, so subsequent calls to this function +will provide a continuous stream of data. + +The size of the buffer that is needed depends on the playback frequency. +It is best to keep the buffer as small as possible to maximize response time +to changes in the sound. Of course, the minimum size is dependent on +system and emulator performance. + +Selecting the correct buffer size is a careful balance. Selecting a buffer +size that is too small will produce noticeable clicks in the output, though +selecting a size that is too large will cause a poor response time and +possible delays in the system when the new buffer is filled. + +This function has no return value (void). + + +License Information and Copyright Notice +======================================== + +PokeySound is Copyright(c) 1996 by Ron Fries + +This library is free software; you can redistribute it and/or modify it under +the terms of version 2 of the GNU Library General Public License as published +by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +details. + +To obtain a copy of the GNU Library General Public License, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Any permitted reproduction of these routines, in whole or in part, must bear +this legend. diff --git a/pokeytest/pokey11_readme.txt b/pokeytest/pokey11_readme.txt new file mode 100644 index 0000000..31eac81 --- /dev/null +++ b/pokeytest/pokey11_readme.txt @@ -0,0 +1,119 @@ + ATARI 800 - POKEY SOUND EMULATION LIBRARY V1.1 + ============================================== + September 23, 1996 + +The Pokey Sound Emulation Library consists of source code and example +executables that are designed to emulate the sound output characteristics +of the Atari 800 Pokey chip. Contained in this distribution, you should +also have the following files: + + +README.TXT - This file +FILE_ID.DIZ - A quick description of the release. +SOUND.C - The SB Driver Source Code. +SOUND.H - The SB Driver Header File which contains the function + prototypes. +SOUND.TXT - A text file which explains the operation of the SB Driver + module. + +POKEY11.C - The Pokey Sound Emulation Source Code. +POKEY11.H - The Pokey Sound Emulation Header File which contains the + function prototypes. +POKEY11.TXT - A text file which explains the operation of the Pokey Sound + Emulation module. +SNDTEST.C - The Main Test routine Source Code. Provided as an example + of how the routines can be used. +SNDTEST.EXE - An pre-compiled executable based on the code provided. + + +These routines are available for your use free of charge, provided you give +me proper recognition, and also provided you don't make a profit off of my +work. See the GNU Library Public License for more information. + +If the final product you are creating will be sold for a profit, please +contact me at rfries@frmail.frco.com so we can discuss terms. + + +THE LIBRARY +----------- + +The Pokey Sound Emulation software consists of two main files. The +functions have been divided into these two files depending on your needs. +If you only need the sound generation routines, the only file you'll need +to compile and link is the POKEY11.C file. If you need full SB drivers as +well, then link both the POKEY11.C and the SOUND.C files into your +application. + +The POKEY11.C file was designed to be as portable as possible. You should +be able to use the file with little or no modification on any 'C' compiler. +It is currently only available in 'C', though I'll be happy to convert the +file to Assembly Language if necessary. For best results, this file should +be compiled in a 32-bit environment with the 'maximize speed' option. + +The SOUND.C file was designed to work with the Borland 'C' compiler. It +may also work directly with other compilers, though some modification may +be required. The SB driver routines in this file have several limitations +which are described in detail in the SOUND.TXT file. NOTE: The SB driver +routines are written in 16-bit. + +The POKEY11.C routines should be very stable, though I'm not as confident +with the SB routines. They work correctly on my system, though I offer no +guarantees. + +Depending on your needs, you will use one of the following algorithms: + + +1) POKEY11.C only - in this case, it is assumed you already have audio + driver routines + + The general design is as follows: + + a) During startup, make a single call to Pokey_sound_init() + b) Whenever an AUDC or AUDF value changes, call Update_pokey_sound() + c) When a new buffer needs to be filled, call Pokey_process() + + +2) POKEY11.C and SOUND.C - using the SB driver routines I've provided + (note: the SB driver routines are written for a 16-bit compiler) + + The general design is as follows: + + a) During startup, make a single call to OpenSB() + b) During startup, make a single call to Pokey_sound_init() + c) Whenever an AUDC or AUDF value changes, call Update_pokey_sound() + d) Periodically call FillBuffer() + e) During shutdown, make a single call to CloseSB() + + +Each function call has its own set of parameters. Check with the +POKEY11.TXT and SOUND.TXT files for more information. + +The SNDTEST.C file has also been provided as an example. I wrote it mainly +for my testing, but it should give you a little insight on how to correctly +use the routines. You can also run the SNDTEST.EXE to play with the sounds. + +Since the SNDTEST.EXE program uses my SOUND SB driver routines, it is subject +to the same limitations. It only supports IRQs 0-7 and DMAs 0-3. It also +only supports low-speed audio output (max freq is approx. 22KHz), and requires +that you have the BLASTER environment variable configured. + + +License Information and Copyright Notice +======================================== + +PokeySound is Copyright(c) 1996 by Ron Fries + +This library is free software; you can redistribute it and/or modify it under +the terms of version 2 of the GNU Library General Public License as published +by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +details. + +To obtain a copy of the GNU Library General Public License, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Any permitted reproduction of these routines, in whole or in part, must bear +this legend. diff --git a/pokeytest/readme.txt b/pokeytest/readme.txt new file mode 100644 index 0000000..be49295 --- /dev/null +++ b/pokeytest/readme.txt @@ -0,0 +1,25 @@ + +This is an attempt at a sound player for Jumpman Junior, using SDL2 and +the pokey sound library by Ron Fries. + +Usage: ./playsdl2 [-p] addr + +Default is to play at NTSC speed, 60 frames/sec. -p means play at PAL +speed, 50 frames/sec. + +addr is a 4-digit hex address from the ROM (../jumpmanjr.rom). Look for +labels beginning with sfx_ in ../jumpmanjr.dasm. Don't use a leading $, +although a leading 0x is allowed (but not needed). + +Right now this only plays one sound, so you can't play all the parts to +the 2- and 4-part harmony music yet. Also, parts that repeat will repeat +forever (press ^C in that case). Eventually this will evolve into the +sound engine for the SDL2 source port of Jumpman Junior, meaning it'll +handle up to 4 voices, with priority levels, etc (same as the original). + +I tried to use the later 2.3 version of the pokey library, both the +standalone one and the modified from from the atari800 emulator, but +couldn't get either to work (no doubt due to my own ignorance). So +this uses version 1.1 of the library, which should be fine for this +game since we don't need support for things like volume-only sound or +high-pass filters. diff --git a/porting_ideas.txt b/porting_ideas.txt index ecad971..c61512a 100644 --- a/porting_ideas.txt +++ b/porting_ideas.txt @@ -1,36 +1,42 @@ can't really do a pure game engine that just uses the binary for data, because parts of the game mechanics are implemented purely as 6502 -code. also the sound effects would need the engine to execute 6502 code -*and* emulate POKEY. however, it can at least use this much of the binary: +code. however, it can at least use this much of the ROM: - sprite and font bitmaps -- level layout data +- level maps - level names -- possibly color data (using an atari palette) +- level graphics (girders/etc) +- color data (using an atari palette) +- sound effects & music this stuff can either be read out of the binary at runtime, or be coverted into source and/or config files when building the engine. either way, the original game binary will be required, but doing it at build time means you don't need the binary at runtime (engine will be a standalone -port of the game). +port of the game). I lean towards reading it at runtime, so people can +modify the ROM to create their own levels (though, this won't work if +the levels use new 6502 code). the various specials (hail, hatchlings, invisible level, etc) will have to be rewritten in C (or whatever the engine ends up being written in). -probably just hardcode which specials appear on which levels. +probably just hardcode which specials appear on which levels. actually +the level data will tell us this, we just match up subroutine addresses +in the ROM with functions in our code. the basic game rules that don't change from level to level will of course be part of the engine. running, jumping, climbing/descending ropes, picking up bombs, collision detection, most levels have generic bullets. -the sound effects and music can just be .wav files captured from the -original game running on the emulator. +the sound effects and music will be done with pokey chip emulation (see +the stuff in pokeytest/). However, it might be nice to allow an option to +use .wav files instead, which would let people use samples from the C=64, +or I could get fancy and record myself playing the music on guitar... I'm thinking C with SDL2. render the game in an atari-sized window -(320x192 or whatever it really is) and let SDL2 scale it, which seems a -lot nicer than SDL1's basically nonexistent scaling. other possibility -would be perl-SDL, provided it's got full SDL2 support (not sure, seems -cpan doesn't have it) +(160x192 or whatever it really is) and let SDL2 scale it, which seems +a lot nicer than SDL1's basically nonexistent scaling. Thought about +perl-SDL, but there's no SDL2 support, and I really want HW scaling. might add high-score saving a la original Jumpman (the one thing I really missed, for the cart-based Junior). also maybe a randomizer mode. @@ -46,5 +52,5 @@ Jumpman, though. unless that turns out to be easier than I think, of course. also inevitably someone will want updated graphics/sound, a "high res -apack" dd-on or such. I'm not opposed to such a thing existing but I +pack" add-on or such. I'm not opposed to such a thing existing but I really only care about the original game. |